1

Here's a program that I am trying to run for Potts Model. It gives the plot once and then keeps repeating the line <Figure size 432x288 with 0 Axes>. What's the solution to get various plots after certain time steps showing the evolution of the system?

import math
import numpy as np
import matplotlib.pyplot as plt


def largest_primes_under(N):
    n = N - 1
    while n >= 2:
        if all(n % d for d in range(2, int(n ** 0.5 + 1))):
            return n
        n -= 1

def Neighbors(Lattice,i,j,n=1):
    ''' Returns an flat array of all neighboring sites in the n-th coordination sphere including the center'''
    N, M = Lattice.shape
    rows = [(i-1) % N, i, (i+1) % N]
    cols = [(j-1) % N, j, (j+1) % M]
    return Lattice[rows][:, cols].flatten()

def calc_dE(Lattice, x, y, z):
    N, M = Lattice.shape
    old_energy = 0
    new_energy = 0
    for i in [0,1,-1]:
        for j in [0,1,-1]:
            if i == 0 and j == 0: 
                continue
            if Lattice[x%N,y%M] == Lattice[(x+i)%N,(y+j)%M]:
                old_energy += 1
            elif z == Lattice[(x+i)%N,(y+j)%M]: 
                new_energy += 1 
    return old_energy-new_energy

N, M = 100,100
orientations = 3
MCS = int(10)

a = largest_primes_under(N*M)
L = np.random.randint(1,orientations+1,size=(N,M))

mat = plt.matshow(L,cmap = plt.get_cmap('plasma', orientations+1), vmin = -0.5, vmax = orientations+0.5, interpolation='kaiser')
plt.axis('off')

for t in range(1,MCS+1):
    rand = np.random.random_integers(N*M)
    for i in range(0,N**2):
        index = (a*i + rand) % (N**2)
        x = index % N
        y = index // N
        n = Neighbors(L,x,y)
        if len(n)-1 == 0: 
            continue
        else: 
            z = np.random.choice(n)
        dE = calc_dE(L,x,y,z)
        if  (dE < 0): 
            L[x%N,y%N] = z      
        elif np.random.sample() < math.exp(-dE*2.5): 
            L[x%N,y%N] = z

    mat.set_data(L)
    plt.draw()
    plt.pause(0.1)
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Blue Panda
  • 15
  • 4

1 Answers1

1
  • mat.set_data(L) is not updating the data
  • In the for-loop, replace mat.set_data(L) with:
    • mat = plt.matshow(L, cmap = plt.get_cmap('plasma', orientations+1), vmin = -0.5, vmax = orientations+0.5, interpolation='kaiser')
  • The plots successfully showed up when I tested the code with the change.
  • Also np.random.random_integers(N*M) is deprecated in numpy v1.20.1. In the code below, np.random.randint(N*M) is used, but this change isn't related to the question in the OP.
for t in range(1, MCS+1):
    rand = np.random.randint(N*M)
    for i in range(0, N**2):
        index = (a*i + rand) % (N**2)
        x = index % N
        y = index // N
        n = Neighbors(L, x, y)
        if len(n)-1 == 0: 
            continue
        else: 
            z = np.random.choice(n)
        dE = calc_dE(L, x, y, z)
        if  (dE < 0): 
            L[x%N, y%N] = z      
        elif np.random.sample() < math.exp(-dE*2.5): 
            L[x%N, y%N] = z

    mat = plt.matshow(L, cmap = plt.get_cmap('plasma', orientations+1), vmin = -0.5, vmax = orientations+0.5, interpolation='kaiser')
#     mat.set_data(L)
    plt.draw()
    plt.pause(0.1)

Alternative

  • In this case it might be more interesting to animate the progression
  • Implemented with Animate quadratic grid changes (matshow)
  • In the following code, save_count=MCS takes the place of the original outer loop for t in range(1, MCS+1), where t was just a throwaway variable.
import matplotlib.animation as animation

def generate_data():
    rand = np.random.randint(N*M)
    for i in range(0, N**2):
        index = (a*i + rand) % (N**2)
        x = index % N
        y = index // N
        n = Neighbors(L, x, y)
        if len(n)-1 == 0: 
            continue
        else: 
            z = np.random.choice(n)
        dE = calc_dE(L, x, y, z)
        if  (dE < 0): 
            L[x%N, y%N] = z      
        elif np.random.sample() < math.exp(-dE*2.5): 
            L[x%N, y%N] = z
    return L


def update(data):
    mat.set_data(data)
    return mat 


def data_gen():
    while True:
        yield generate_data()


N, M = 100, 100
orientations = 3
MCS = 10

a = largest_primes_under(N*M)
L = np.random.randint(1, orientations+1, size=(N, M))

fig, ax = plt.subplots()

mat = ax.matshow(generate_data(), cmap=plt.get_cmap('plasma', orientations+1), vmin=-0.5, vmax=orientations+0.5, interpolation='kaiser')
plt.colorbar(mat)
ani = animation.FuncAnimation(fig, update, data_gen, interval=500, save_count=MCS)
plt.show()

ani.save('animation.gif')

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
  • 1
    (I hope I am replying to you, I am new to this site) @TrentonMcKinney this worked! Thank you so much for this. Now I can work on my project! :D – Blue Panda Apr 25 '21 at 15:01