def demo(): """Demonstrates solution for exercise: example of usage""" print "Ising Demo, T=Tc-0.1, N=100, nSteps=50" Tc = T=2./scipy.log(1.+scipy.sqrt(2.))-0.1 N = 100 nSweeps = 20 ising = IsingModel(100, T=Tc) dl = DynamicLattice.DynamicLattice((N,N)) print "Heat Bath Algorithm" for t in range(nSweeps): dl.display(ising.lattice) ising.SweepHeatBath() if not yesno(): return print "Metropolis Algorithm" ising = IsingModel(100, T=Tc) dl = DynamicLattice.DynamicLattice((N,N)) for t in range(nSweeps): dl.display(ising.lattice) ising.SweepMetropolis() if not yesno(): return print "Wolff Algorithm" ising = IsingModel(100, T=Tc) dl = DynamicLattice.DynamicLattice((N,N)) for t in range(nSweeps): dl.display(ising.lattice) partialSweep=0 partialSweep = ising.SweepWolff(partialSweep=partialSweep)
def __init__(self, N=100, dx=1.0, eps=0.2, gamma=0.8, beta=0.7): """Initialize a FitzNag2D2D class, consisting of NxN points on a square grid with lattice spacing dx, and model parameters eps, gamma and beta; the FitzHugh-Nagumo equations are: dv_dt = laplacian(v) + (1./eps) * (v - (1./3.)*v**3 - w) dw_dt = eps*(v - gamma*w + beta) The __init__ method will need to store the values of the specified parameters, and create the fields v and w (as scipy arrays of the appropriate size). v and w should be initialized uniformly to their values at the fixed point (resting state), vstar and wstar, except for the initialization of a pulse of height XX within a square of size 10 at the center of the simulation grid. The __init__ method should also set a member variable, e.g., self.pulseheight, that will indicate the height of the pulse generated by interactive mouse events. Animated displays will be taken care of by the DynamicLattice class which has been imported. The FitzNag2D class should initialize an instance of DynamicLattice within the __init__ method: self.DL = DynamicLattice((N, N), zmin=-2.0, zmax=2.0) This particular instance will animate dynamics on an NxN grid, creating grayscale images of a specified field based on the field value in the interval (zmin=-2.0, zmax=2.0). """ self.DL = DynamicLattice((N, N), zmin=-2.0, zmax=2.0) self.N = N self.dx = dx self.L = N*dx self.D = scipy.ones((N,N), float) self.eps = eps * scipy.ones((N,N), float) self.gamma = gamma * scipy.ones((N,N), float) self.beta = beta * scipy.ones((N,N), float) self.pulseheight = 3.0 vstar, wstar = FindFixedPoint(gamma, beta) self.v = vstar*scipy.ones((N, N), float) self.w = wstar*scipy.ones((N, N), float) self.beta[(N/2-5):(N/2+5), (N/2-5):(N/2+5)] = 0.4 self.t = 0.
def test2(shape=(100,100)): dl = DynamicLattice.DynamicLattice(shape) a = RandomArray.randint(0, 2, shape) dl.display(a) for i in range(shape[0]/2): for j in range(shape[0]/2): a[i,j] = 0 dl.display(a, (i,j))
def runMetropolis(N=100, nSweepsPerShow=1, nShow=500): """ Same as runHeatBath except use SweepMetropolis """ ising = IsingModel(N, T=2./scipy.log(1.+scipy.sqrt(2.)) -0.1) dl = DynamicLattice.DynamicLattice((N,N)) for t in range(nShow): dl.display(ising.lattice) ising.SweepMetropolis(nSweepsPerShow)
def runWolff(N=100, nSweeps=500): """ Same as runHeatBath except initialize partialSweep=0, and use SweepWolff(partialSweep=partialSweep) """ ising = IsingModel(N) dl = DynamicLattice.DynamicLattice((N,N)) partialSweep=0 for t in range(nSweeps): dl.display(ising.lattice) ising.SweepWolff(partialSweep=partialSweep)
def runHeatBath(N=100, nSweepsPerShow=1, nShow=500): """ Set up ising as an IsingModel Set up dl as an NxN DynamicLattice (dl = DynamicLattice.DynamicLattice(N,N)) for t in range nShow, display lattice with dl.display(ising.Lattice) and then sweep with ising.SweepHeatBath(nSweepsPerShow) """ ising = IsingModel(N, T=2./scipy.log(1.+scipy.sqrt(2.)) -0.1) dl = DynamicLattice.DynamicLattice((N,N)) for t in range(nShow): dl.display(ising.lattice) ising.SweepHeatBath(nSweepsPerShow)
def test(shape=(100,100)): dl = DynamicLattice.DynamicLattice(shape) for n in range(20): a = RandomArray.randint(0, 2, shape) dl.display(a)
class FitzNag2D: """FitzNag2D is a class to support the simulation of the FitzHugh-Nagumo equations on a 2D square grid.""" def __init__(self, N=100, dx=1.0, eps=0.2, gamma=0.8, beta=0.7): """Initialize a FitzNag2D2D class, consisting of NxN points on a square grid with lattice spacing dx, and model parameters eps, gamma and beta; the FitzHugh-Nagumo equations are: dv_dt = laplacian(v) + (1./eps) * (v - (1./3.)*v**3 - w) dw_dt = eps*(v - gamma*w + beta) The __init__ method will need to store the values of the specified parameters, and create the fields v and w (as scipy arrays of the appropriate size). v and w should be initialized uniformly to their values at the fixed point (resting state), vstar and wstar, except for the initialization of a pulse of height XX within a square of size 10 at the center of the simulation grid. The __init__ method should also set a member variable, e.g., self.pulseheight, that will indicate the height of the pulse generated by interactive mouse events. Animated displays will be taken care of by the DynamicLattice class which has been imported. The FitzNag2D class should initialize an instance of DynamicLattice within the __init__ method: self.DL = DynamicLattice((N, N), zmin=-2.0, zmax=2.0) This particular instance will animate dynamics on an NxN grid, creating grayscale images of a specified field based on the field value in the interval (zmin=-2.0, zmax=2.0). """ self.DL = DynamicLattice((N, N), zmin=-2.0, zmax=2.0) self.N = N self.dx = dx self.L = N * dx self.eps = eps self.gamma = gamma self.beta = beta self.pulseheight = 3.0 vstar, wstar = FindFixedPoint(gamma, beta) self.v = vstar * scipy.ones((N, N), float) self.w = wstar * scipy.ones((N, N), float) self.v[(N / 2 - 5):(N / 2 + 5), (N / 2 - 5):(N / 2 + 5)] = self.pulseheight self.t = 0. def rhs(self): """self.rhs() sets the instantaneous value of the right-hand-side of the FitzHugh-Nagumo equations, by creating two scipy arrays self.dv_dt and self.dw_dt, which describe the time evolution of the v and w fields, respectively. self.rhs() will be called by the step() method as part of the Euler time-stepping scheme.""" self.dv_dt = del2(self.v, self.dx) + \ (1./self.eps) * (self.v - (1./3.)*self.v**3 - self.w) self.dw_dt = self.eps * (self.v - self.gamma * self.w + self.beta) def step(self, dt): """self.step(dt) increments the fields v and w by dt. The first and last rows and columns of our arrays are "ghost cells", which are added to the boundaries in order to make it convenient to enforce the boundary conditions. Our no-flow boundary condition wants the normal derivative (derivative perpendicular to the boundary) to equal zero. step(dt) first uses CopyGhost to copy the boundary (ghost) cells to ensure the zero--derivative (no-flow) boundary condition. It then implements an Euler step, by calling self.rhs() to set the current values of the fields dv_dt and dw_dt, and then incrementing v by dt*dv_dt and similarly for w. You may wish to make dv_dt and dw_dt member variables of the FitzNag2D class. """ CopyGhost(self.v) self.rhs() self.v += dt * self.dv_dt self.w += dt * self.dw_dt def run(self, T, dt): """self.run(T, dt) integrates the FitzHugh-Nagumo equations for a time interval T, by taking steps of size dt. self.run() should also increment an overall time counter by dt. Every DISPLAYINTERVAL steps (e.g., 10), interaction with the self.DL object should be undertaken, to update the display of the v field, and to determine if a pulse box has been selected with the mouse. The display can be updated with the self.DL.display() method, which takes an array to be displayed as an argument (e.g., self.v). An additional nicety is to set the title of the self.DL window with the current simulation time, using the self.DL.setTitle() method. The self.DL object supports the query IsBoxSelected(), to ascertain whether a region (box) of the grid has been selected with the mouse. If a box has been selected, the self.DL.GetMouseBox() can be called to unpack a set of grid points (x0, y0, x1, y1) delineating the selected box. The v field within the selected box should be set to the pre-selected pulseheight. """ count = 0 t0 = self.t while self.t < t0 + T: if count % DISPLAYINTERVAL == 0: if self.DL.IsBoxSelected(): x0, y0, x1, y1 = self.DL.GetMouseBox() self.v[x0:x1, y0:y1] = self.pulseheight self.DL.setTitle('t = %f' % self.t) self.DL.display(self.v) self.step(dt) self.t += dt count += 1