"""" From "COMPUTATIONAL PHYSICS" & "COMPUTER PROBLEMS in PHYSICS" by RH Landau, MJ Paez, and CC Bordeianu (deceased) Copyright R Landau, Oregon State Unv, MJ Paez, Univ Antioquia, C Bordeianu, Univ Bucharest, 2017. Please respect copyright & acknowledge our work.""" # WangLandau.py: Wang Landau algorithm for 2-D spin system """ Author in Java: Oscar A. Restrepo, Universidad de Antioquia, Medellin, Colombia Each time fac changes, a new histogrm is generated. Only the first Histogram plotted to reduce computational time""" from visual import * import random; from visual.graph import * L = 8; N = (L*L) # Set up graphics entgr = gdisplay(x=0,y=0,width=500,height=250,title='Density of States',\ xtitle= 'E/N', ytitle='log g(E)', xmax=2., xmin=-2.,ymax=45,ymin=0) entrp = gcurve(color = color.yellow, display = entgr) energygr = gdisplay(x=0, y=250, width=500, height=250, title='E vs T',\ xtitle = 'T', ytitle='U(T)/N', xmax=8.,xmin=0, ymax =0.,ymin=-2.) energ = gcurve(color = color.cyan, display = energygr) histogr = display(x = 0, y = 500, width = 500, height = 300,\ title = '1st histogram: H(E) vs. E/N, corresponds to log(f) = 1') histo = curve(x = list(range(0, N+1)), color=color.red, display=histogr) xaxis = curve(pos = [( - N, - 10), (N, - 10)]) minE = label(text = ' - 2', pos = ( - N + 3, - 15), box = 0) maxE = label(text = '2', pos = (N - 3, - 15), box = 0) zeroE = label(text = '0', pos = (0, - 15), box = 0) ticm = curve(pos = [( - N, - 10), ( - N, - 13)]) tic0 = curve(pos = [(0, - 10), (0, - 13)]) ticM = curve(pos = [(N, - 10), (N, - 13)]) enr = label(text = 'E/N', pos = (N/2, - 15), box = 0) sp = zeros( (L, L) ) # Grid size, spins hist = zeros( (N + 1) ) prhist = zeros( (N + 1) ) # Histograms S = zeros( (N + 1), float) # Entropy = log g(E) def iE(e): return int((e + 2*N)/4) def IntEnergy(): exponent = 0.0 for T in arange (0.2, 8.2, 0.2 ): # Select lambda max Ener = - 2*N maxL = 0.0 # Initialize for i in range(0, N + 1): if S[i]!= 0 and (S[i] - Ener/T)>maxL: maxL = S[i] - Ener/T Ener = Ener + 4 sumdeno = 0 sumnume = 0 Ener = -2*N for i in range(0, N): if S[i] != 0: exponent = S[i] - Ener/T - maxL sumnume += Ener*exp(exponent) sumdeno += exp(exponent) Ener = Ener + 4.0 U = sumnume/sumdeno/N # internal energy U(T)/N energ.plot(pos = (T, U) ) def WL(): # Wang - Landau sampling Hinf = 1.e10 # initial values for Histogram Hsup = 0. tol = 1.e-3 # tolerance, stops the algorithm ip = zeros(L) im = zeros(L) # BC R or down, L or up height = abs(Hsup - Hinf)/2. # Initialize histogram ave = (Hsup + Hinf)/2. # about average of histogram percent = height / ave for i in range(0, L): for j in range(0, L): sp[i, j] = 1 # Initial spins for i in range(0, L): ip[i] = i + 1 im[i] = i - 1 # Case plus, minus ip[L - 1] = 0 im[0] = L - 1 # Borders Eold = - 2*N # Initialize energy for j in range(0, N + 1): S[j] = 0 # Entropy initialized iter = 0 fac = 1 while fac > tol : i = int(N*random.random() ) # Select random spin xg = i%L # Must be i//L, not i/L for Python 3: yg = i//L # Localize x, y, grid point Enew = Eold + 2*(sp[ip[xg],yg] + sp[im[xg],yg] + sp[xg,ip[yg]] + sp[xg, im[yg]] ) * sp[xg, yg] # Change energy deltaS = S[iE(Enew)] - S[iE(Eold)] if deltaS <= 0 or random.random() < exp( - deltaS): Eold = Enew; sp[xg, yg] *= - 1 # Flip spin S[iE(Eold)] += fac; # Change entropy if iter%10000 == 0: # Check flatness every 10000 sweeps for j in range( 0, N + 1): if j == 0 : Hsup = 0 Hinf = 1e10 # Initialize new histogram if hist[j] == 0 : continue # Energies never visited if hist[j] > Hsup: Hsup = hist[j] if hist[j] < Hinf: Hinf = hist[j] height = Hsup - Hinf ave = Hsup + Hinf percent = 1.0* height/ave # 1.0 to make it float number if percent < 0.3 : # Histogram flat? print(" iter ", iter, " log(f) ", fac) for j in range(0, N + 1): prhist[j] = hist[j] # to plot hist[j] = 0 # Save hist fac *= 0.5 # Equivalent to log(sqrt(f)) iter += 1 hist[iE(Eold)] += 1 # Change histogram, add 1, update if fac >= 0.5: # just show the first histogram # Speed up by using array calculations: histo.x = 2.0*arange(0,N+1) - N histo.y = 0.025*hist-10 deltaS = 0.0 print("wait because iter > 13 000 000") # not always the same WL() # Call Wang Landau algorithm deltaS = 0.0 for j in range(0, N + 1): rate(150) order = j*4 - 2*N deltaS = S[j] - S[0] + log(2) if S[j] != 0 : entrp.plot(pos = (1.*order/N, deltaS)) # plot entropy IntEnergy(); print("Done")