Esempio n. 1
0
def metropolis_sim_epoch(Lattice, K, nearest_neighbors=1):
    '''
    :param Lattice:
    :param K: beta*J, temperature/coupling strength
    :param nearest_neighbors: number of nearest neighbors
    :return:
    '''
    N = Lattice.shape
    N_sites = np.prod(N)
    for i in range(N_sites):
        #convert i to a coordinate
        r = np.unravel_index(i, N)
        site = Lattice[r]
        # propose a change
        proposal = -site
        # calculate energy change from neighbors in this:
        NN = getNN(r, N, nearest_neighbors)
        deltaE = 0
        for nn_site in NN:
            neighbor = Lattice[nn_site]
            deltaE += K * (neighbor * (site - proposal))
        if (deltaE < 0):  # accept immediately
            Lattice[r] = -1 * Lattice[r]
        else:
            # calculate Boltzmann Weight
            Boltzmann = np.exp(-deltaE)
            # generate random number
            p = np.random.rand()
            if (p < Boltzmann):
                Lattice[r] = -1 * Lattice[r]
    return Lattice
Esempio n. 2
0
def SW_BFS(lattice, bonded, clusters, start, beta, J, nearest_neighbors=1):
    '''
    function currently cannot generalize to dimensions higher than 2...
    main idea is that we populate a lattice with clusters according to SW using a BFS from a root coord
    :param lattice: lattice
    :param bonded: 1 or 0, indicates whether a site has been assigned to a cluster
           or not
    :param clusters: dictionary containing all existing clusters, keys are an integer
            denoting natural index of root of cluster
    :param start: root node of graph (x,y)
    :param beta: temperature
    :param J: strength of lattice coupling
    :param nearest_neighbors: number or NN to probe
    :return:
    '''
    p = 1 - np.exp(-2 * beta * J)
    #bond forming probability
    N = lattice.shape
    visited = np.zeros(N)
    #indexes whether we have visited nodes during
    #this particular BFS search
    queue = list()
    if (bonded[tuple(start)] != 0):  #cannot construct a cluster from this site
        return bonded, clusters, visited

    queue.append(start)
    cluster_spin = lattice[tuple(start)]
    color = np.max(bonded) + 1

    ## need to make sub2ind work in arbitrary dimensions
    index = np.ravel_multi_index(tuple(start), dims=tuple(N), order='C')
    clusters[index] = list()
    #whatever the input coordinates are
    while (len(queue) > 0):
        #print(queue)
        r = tuple(queue.pop(0))
        ##print(x,y)
        if (visited[r] == 0):  #if not visited
            visited[r] = 1
            clusters[index].append(r)
            #to see clusters, always use different numbers
            bonded[r] = color
            NN = getNN(r, N, nearest_neighbors)
            for nn_coords in NN:
                rn = tuple(nn_coords)
                if(lattice[rn] == cluster_spin and bonded[rn] == 0\
                   and visited[rn] == 0): #require spins to be aligned
                    random = np.random.rand()
                    if (random < p):  # accept bond proposal
                        queue.append(rn)
                        #add coordinate to search
                        clusters[index].append(rn)  #add point to the cluster
                        bonded[rn] = color
                        #indicate site is no longer available
    return bonded, clusters, visited
Esempio n. 3
0
def metropolis_sim_vectorized(Lattice, K, epochs, num_views=1):
    N = Lattice.shape
    N_sites = np.prod(N)
    epoch = 100
    nearest_neighbors = 1
    # begin iterating over epochs
    for t in range(epoch):
        print('epoch: ' + str(t))
        computations_tracker = 0
        # scan through every element of the lattice

        #for every site, propose a change as a matrix
        proposal_matrix = -Lattice

        #calculate energy change using the original Lattice
        # need a shift operator...

        for i in range(N_sites):
            # convert i to a coordinate
            r = np.unravel_index(i, N)
            site = Lattice[r]
            # propose a change
            proposal = -site

            # calculate energy change from neighbors in this:
            NN = getNN(r, N, nearest_neighbors)
            deltaE = 0
            for a in NN:
                neighbor = Lattice[a[0], a[1]]
                deltaE += K * (neighbor * (site - proposal))

            if (
                    deltaE < 0
            ):  # accept immediately...we initiate a change with every flip so that NN may be affected
                ## in a vectorized version, we would actually have to do this on a checkerboard...
                Lattice[r] = -1 * Lattice[r]
            else:
                # calculate Boltzmann Weight
                Boltzmann = np.exp(-deltaE)
                # generate random number
                p = np.random.rand()
                if (p < Boltzmann):
                    Lattice[r] = -1 * Lattice[r]
        if (t % int(epochs / num_views) == 0):
            plt.imshow(Lattice)
            plt.show()
Esempio n. 4
0
def metropolis_simulation(Lattice,
                          K,
                          epochs,
                          thermalization=100,
                          num_views=1,
                          view_lattice=False):
    N = Lattice.shape
    N_sites = np.prod(N)
    nearest_neighbors = 1
    # begin iterating over epochs
    data = list()
    for t in range(epochs):
        computations_tracker = 0
        # scan through every element of the lattice
        for i in range(N_sites):
            #convert i to a coordinate
            r = np.unravel_index(i, N)
            computations_tracker += 1
            site = Lattice[r]
            # propose a change
            proposal = -site
            # calculate energy change from neighbors in this:
            NN = getNN(r, N, nearest_neighbors)
            deltaE = 0
            for nn_site in NN:
                neighbor = Lattice[nn_site]
                deltaE += K * (neighbor * (site - proposal))

            if (deltaE < 0):  # accept immediately
                Lattice[r] = -1 * Lattice[r]
            else:
                # calculate Boltzmann Weight
                Boltzmann = np.exp(-deltaE)
                # generate random number
                p = np.random.rand()
                if (p < Boltzmann):
                    Lattice[r] = -1 * Lattice[r]
        if (t % int(epochs / num_views) == 0):
            print('epoch: ' + str(t))
        if (t % int(epochs / num_views) == 0 and view_lattice):
            plt.imshow(Lattice)
            plt.show()
        if (t > thermalization):
            data.append(magnetization(Lattice))
    return Lattice, data
Esempio n. 5
0
def run_Wolff_epoch(Lattice, N, p):
    '''
    run one wolff epoch
    :param Lattice:
    :param N:
    :param p: 1-exp(-2K);
    :return:
    '''

    change_tracker = np.ones(N)
    visited = np.zeros(N)
    root = []
    # generate random coordinate by sampling from uniform random...
    for i in range(len(N)):
        root.append(np.random.randint(0, N[i], 1)[0])
    root = tuple(root)
    visited[root] = 1
    C = [root]
    # denotes cluster coordinates
    F_old = [root]
    # old frontier
    change_tracker[root] = -1
    while (len(F_old) != 0):
        F_new = []
        for site in F_old:
            site_spin = Lattice[tuple(site)]
            # get neighbors
            NN_list = getNN(site, N, num_NN=1)
            for NN_site in NN_list:  ## if we do the full search, this is bad, because
                nn = tuple(NN_site)
                if (Lattice[nn] == site_spin and visited[nn] == 0):
                    if (np.random.rand() < p):
                        F_new.append(nn)
                        visited[nn] = 1
                        C.append(nn)
                        change_tracker[nn] = -1
        F_old = F_new
    Lattice = Lattice * change_tracker

    return Lattice
Esempio n. 6
0
def Wolff_simulation(Lattice,
                     K,
                     epochs,
                     thermalization_epochs=100,
                     num_views=10):
    '''
    :param Lattice:
    :param K:
    :param epochs:
    :param thermalization_epochs:
    :param num_views:
    :return:
    '''
    plt.ion()
    ## wolff test using Frontier idea
    N = Lattice.shape
    # generate random particle
    Lattice_History = list()
    p = 1 - np.exp(-2 * K)
    data = list()
    for t in range(epochs):
        change_tracker = np.ones(N)
        visited = np.zeros(N)
        root = []
        # generate random coordinate by sampling from uniform random...
        for i in range(len(N)):
            root.append(np.random.randint(0, N[i], 1)[0])
        root = tuple(root)
        visited[root] = 1
        C = [root]
        # denotes cluster coordinates
        F_old = [root]
        # old frontier
        change_tracker[root] = -1
        while (len(F_old) != 0):
            F_new = []
            for site in F_old:
                site_spin = Lattice[tuple(site)]
                # get neighbors
                NN_list = getNN(site, N, num_NN=1)
                for NN_site in NN_list:  ## if we do the full search, this is bad, because
                    nn = tuple(NN_site)
                    if (Lattice[nn] == site_spin and visited[nn] == 0):
                        if (np.random.rand() < p):
                            F_new.append(nn)
                            visited[nn] = 1
                            C.append(nn)
                            change_tracker[nn] = -1
            F_old = F_new

        # update the cluster
        Lattice = Lattice * change_tracker
        if (t > thermalization_epochs):
            data.append(magnetization(Lattice))
        # for site in C:
        #     Lattice[site] = -1 * Lattice[site]
        # if (t % int(epochs/num_views) == 0):
        #     print('epoch: ' + str(t));
        #     plt.imshow(Lattice);
        #     plt.pause(0.05)

    # plt.imshow(Lattice);
    # plt.show()
    return Lattice, data