Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
伊辛模型[Python]_Python_Python 3.x_Physics_Montecarlo_Complex Networks - Fatal编程技术网

伊辛模型[Python]

伊辛模型[Python],python,python-3.x,physics,montecarlo,complex-networks,Python,Python 3.x,Physics,Montecarlo,Complex Networks,我试图在Barabasi-Albert网络中模拟伊辛相变,并试图复制一些观测结果,如磁化和能量,就像伊辛网格模拟中观察到的那样。然而,我在解释我的结果时遇到了困难:不确定是物理错误还是实现中存在错误。以下是一个最低限度的工作示例: import numpy as np import networkx as nx import random import math ## sim params # coupling constant J = 1.0 # ferromagnetic # tem

我试图在Barabasi-Albert网络中模拟伊辛相变,并试图复制一些观测结果,如磁化和能量,就像伊辛网格模拟中观察到的那样。然而,我在解释我的结果时遇到了困难:不确定是物理错误还是实现中存在错误。以下是一个最低限度的工作示例:

import numpy as np 
import networkx as nx
import random
import math

## sim params

# coupling constant
J = 1.0 # ferromagnetic

# temperature range, in units of J/kT
t0 = 1.0
tn = 10.0
nt = 10.
T = np.linspace(t0, tn, nt)

# mc steps
steps = 1000

# generate BA network, 200 nodes with preferential attachment to 3rd node
G = nx.barabasi_albert_graph(200, 3)

# convert csr matrix to adjacency matrix, a_{ij}
adj_matrix = nx.adjacency_matrix(G)
top = adj_matrix.todense()
N = len(top)

# initialize spins in the network, ferromagnetic
def init(N):
    return np.ones(N)

# calculate net magnetization
def netmag(state):
    return np.sum(state)

# calculate net energy, E = \sum J *a_{ij} *s_i *s_j
def netenergy(N, state):
    en = 0.
    for i in range(N):
        for j in range(N):
            en += (-J)* top[i,j]*state[i]*state[j] 
    return en

# random sampling, metropolis local update
def montecarlo(state, N, beta, top):

    # initialize difference in energy between E_{old} and E_{new}
    delE = []

    # pick a random source node
    rsnode = np.random.randint(0,N)

    # get the spin of this node
    s2 = state[rsnode]

    # calculate energy by summing up its interaction and append to delE
    for tnode in range(N):
        s1 = state[tnode]
        delE.append(J * top[tnode, rsnode] *state[tnode]* state[rsnode])

    # calculate probability of a flip
    prob = math.exp(-np.sum(delE)*beta)

    # if this probability is greater than rand[0,1] drawn from an uniform distribution, accept it
    # else retain current state
    if prob> random.random():
        s2 *= -1
    state[rsnode] = s2

    return state

def simulate(N, top):

    # initialize arrays for observables
    magnetization = []
    energy = []
    specificheat = []
    susceptibility = []

    for count, t in enumerate(T):


        # some temporary variables
        e0 = m0 = e1 = m1 = 0.

        print 't=', t

        # initialize spin vector
        state = init(N)

        for i in range(steps):

            montecarlo(state, N, 1/t, top)

            mag = netmag(state)
            ene = netenergy(N, state)

            e0 = e0 + ene
            m0 = m0 + mag
            e1 = e0 + ene * ene
            m1 = m0 + mag * mag

        # calculate thermodynamic variables and append to initialized arrays
        energy.append(e0/( steps * N))
        magnetization.append( m0 / ( steps * N)) 
        specificheat.append( e1/steps - e0*e0/(steps*steps) /(N* t * t))
        susceptibility.append( m1/steps - m0*m0/(steps*steps) /(N* t *t))

        print energy, magnetization, specificheat, susceptibility

        plt.figure(1)
        plt.plot(T, np.abs(magnetization), '-ko' )
        plt.xlabel('Temperature (kT)')
        plt.ylabel('Average Magnetization per spin')

        plt.figure(2)
        plt.plot(T, energy, '-ko' )
        plt.xlabel('Temperature (kT)')
        plt.ylabel('Average energy')

        plt.figure(3)
        plt.plot(T, specificheat, '-ko' )
        plt.xlabel('Temperature (kT)')
        plt.ylabel('Specific Heat')

        plt.figure(4)
        plt.plot(T, susceptibility, '-ko' )
        plt.xlabel('Temperature (kT)')
        plt.ylabel('Susceptibility')

simulate(N, top)
观察结果

  • 我试着对代码进行大量的注释,如果我忽略了什么,请询问

    问题

  • 磁化趋势正确吗?磁化强度随温度升高而降低,但不能确定相变的临界温度
  • 随着温度的升高,能量接近零,这似乎与伊辛网格中观察到的一致。为什么我会得到负的比热值
  • 如何选择蒙特卡罗步骤的数量?这仅仅是基于网络节点数量的点击和试用吗

  • 编辑:02.06::反铁磁配置的模拟故障首先,因为这是一个编程站点,让我们分析一下程序。您的计算效率非常低,这使得探索更大的图形变得不切实际。在您的例子中,邻接矩阵是200x200(40000)个元素,只有大约3%的非零元素。将其转换为稠密矩阵意味着在计算
    montecarlo
    例程中的能量差和
    netenergy
    中的净能量时要进行更多的计算。以下代码在我的系统上执行速度快5倍,更大的图形预期会有更好的加速:

    #将拓扑保持为稀疏矩阵
    top=nx.邻接矩阵(G)
    def净能量(N,状态):
    en=0。
    对于范围(N)中的i:
    ss=np.sum(状态[top[i].非零()
    en+=状态[i]*ss
    返回-0.5*J*en
    
    注意因子中的0.5-因为邻接矩阵是对称的,每对自旋计数两次

    def montecarlo(州、N、beta、顶部):
    #选择一个随机源节点
    rsnode=np.random.randint(0,N)
    #获取此节点的旋转
    s=状态[rsnode]
    #所有相邻旋转的总和
    ss=np.sum(状态[top[rsnode].nonzero()[1]])
    #过渡能
    delE=2.0*J*ss*s
    #计算转移概率
    prob=math.exp(-delE*beta)
    #有条件地接受过渡
    如果prob>random.random():
    s=-s
    状态[rsnode]=s
    返回状态
    
    请注意转换能量中的系数2.0-您的代码中缺少它

    这里有一些
    numpy
    索引魔法
    top[i]
    是节点i的稀疏邻接行向量,
    top[i]。nonzero()[1]
    是非零元素的列索引(
    top[i]。nonzero()[0]
    是行索引,因为它是行向量,所以都等于0)<代码>状态[top[i]。非零()[1]]因此是节点i的相邻节点的值

    现在来谈谈物理学。热力学性质是错误的,因为:

    e1=e0+ene*ene
    m1=m0+mag*mag
    
    应该是:

    e1=e1+ene*ene
    m1=m1+mag*mag
    
    以及:

    specificheat.append(e1/步骤-e0*e0/(步骤*steps)/(N*t*t))
    附加(m1/步数-m0*m0/(步数*步数)/(N*t*t))
    
    应该是:

    specificheat.append((e1/steps/N-e0*e0/(steps*steps*N*N))/(t*t))
    附加((m1/steps/N-m0*m0/(steps*steps*N*N))/t)
    
    (您最好尽早对能量和磁化进行平均)

    这使得陆地的热容和磁化率为正值。注意敏感性分母中的单个
    t

    既然程序(希望)是正确的,让我们谈谈物理。对于每个温度,你从一个全向上的自旋状态开始,然后让它一次演化一个自旋。显然,除非温度为零,否则该初始状态远离热平衡,因此系统将开始向与给定温度相对应的状态空间部分漂移。这一过程被称为热化,在此期间收集静态信息毫无意义。您必须始终将给定温度下的模拟分为两部分-热化和实际有效运行。需要多少次迭代才能达到平衡?很难说-使用能量的移动平均值,当它变得(相对)稳定时进行监测

    其次,更新算法每次迭代只改变一次旋转,这意味着程序将非常缓慢地探索状态空间,并且需要大量迭代才能获得分区函数的良好近似值。有了200次旋转,1000次迭代就足够了


    其余的问题真的不属于这里。

    这看起来更多的是关于物理编程的问题——你可能在这方面运气更好。谢谢!我也在那个平台上添加了这个问题[.到目前为止运气不好.是的--我担心你的问题非常具体,需要很多在这个领域不太常见的专家知识,所以可能很难得到答案.祝你好运。