root / Ising / MPI / Ising2D-MPI.py @ 308
Historique | Voir | Annoter | Télécharger (7,03 ko)
1 |
#!/usr/bin/env python
|
---|---|
2 |
#!/usr/bin/env python
|
3 |
#
|
4 |
# Ising2D model using mpi4py MPI implementation for Python
|
5 |
#
|
6 |
# CC BY-NC-SA 2011 : <emmanuel.quemener@ens-lyon.fr>
|
7 |
#
|
8 |
# Thanks to Lisandro Dalcin for MPI4PY :
|
9 |
# http://mpi4py.scipy.org/
|
10 |
|
11 |
import sys |
12 |
import numpy |
13 |
#import pylab
|
14 |
from PIL import Image |
15 |
from math import exp |
16 |
from random import random |
17 |
import time |
18 |
# MPI librairie call
|
19 |
from mpi4py import MPI |
20 |
import getopt |
21 |
import matplotlib.pyplot as plt |
22 |
|
23 |
LAPIMAGE=False
|
24 |
|
25 |
def partition ( lst, n ): |
26 |
return [ lst[i::n] for i in xrange(n) ] |
27 |
|
28 |
def ImageOutput(sigma,prefix): |
29 |
Max=sigma.max() |
30 |
Min=sigma.min() |
31 |
|
32 |
# Normalize value as 8bits Integer
|
33 |
SigmaInt=(255*(sigma-Min)/(Max-Min)).astype('uint8') |
34 |
image = Image.fromarray(SigmaInt) |
35 |
image.save("%s.jpg" % prefix)
|
36 |
|
37 |
def Metropolis(sigma,J,B,T,Iterations): |
38 |
start=time.time() |
39 |
|
40 |
SizeX,SizeY=sigma.shape |
41 |
|
42 |
for p in xrange(0,Iterations): |
43 |
# Random access coordonate
|
44 |
X,Y=numpy.random.randint(SizeX),numpy.random.randint(SizeY) |
45 |
|
46 |
DeltaE=sigma[X,Y]*(2*J*(sigma[X,(Y+1)%SizeY]+ |
47 |
sigma[X,(Y-1)%SizeY]+
|
48 |
sigma[(X-1)%SizeX,Y]+
|
49 |
sigma[(X+1)%SizeX,Y])+B)
|
50 |
|
51 |
if DeltaE < 0. or random() < exp(-DeltaE/T): |
52 |
sigma[X,Y]=-sigma[X,Y] |
53 |
duration=time.time()-start |
54 |
return(duration)
|
55 |
|
56 |
def Magnetization(sigma,M): |
57 |
return(numpy.sum(sigma)/(sigma.shape[0]*sigma.shape[1]*1.0)) |
58 |
|
59 |
def CriticalT(T,E): |
60 |
|
61 |
Epoly=numpy.poly1d(numpy.polyfit(T,E,T.size/3))
|
62 |
dEpoly=numpy.diff(Epoly(T)) |
63 |
dEpoly=numpy.insert(dEpoly,0,0) |
64 |
return(T[numpy.argmin(dEpoly)])
|
65 |
|
66 |
def DisplayCurves(T,E,M,J,B): |
67 |
|
68 |
plt.xlabel("Temperature")
|
69 |
plt.ylabel("Energy")
|
70 |
|
71 |
Experience,=plt.plot(T,E,label="Energy")
|
72 |
|
73 |
plt.legend() |
74 |
plt.show() |
75 |
|
76 |
def Energy(sigma,J,B): |
77 |
# Copier et caster
|
78 |
E=numpy.copy(sigma).astype(numpy.float32) |
79 |
|
80 |
# Appel par slice
|
81 |
E[1:-1,1:-1]=E[1:-1,1:-1]*(2.*J*(E[:-2,1:-1]+E[2:,1:-1]+ |
82 |
E[1:-1,:-2]+E[1:-1,2:])+B) |
83 |
|
84 |
# Bien nettoyer la peripherie
|
85 |
E[:,0]=0 |
86 |
E[:,-1]=0 |
87 |
E[0,:]=0 |
88 |
E[-1,:]=0 |
89 |
|
90 |
Energy=numpy.sum(E) |
91 |
|
92 |
return(Energy/(E.shape[0]*E.shape[1]*1.0)) |
93 |
|
94 |
if __name__=='__main__': |
95 |
|
96 |
ToSave=[] |
97 |
|
98 |
# MPI Init
|
99 |
comm = MPI.COMM_WORLD |
100 |
rank = comm.Get_rank() |
101 |
|
102 |
# Define number of Nodes on with computing is performed (exclude 0)
|
103 |
NODES=comm.Get_size()-1
|
104 |
|
105 |
# pass explicit MPI datatypes
|
106 |
if rank == 0: |
107 |
|
108 |
# Set defaults values
|
109 |
# Coupling factor
|
110 |
J=1.
|
111 |
# Magnetic Field
|
112 |
B=0.
|
113 |
# Size of Lattice
|
114 |
Size=256
|
115 |
# Default Temperatures (start, end, step)
|
116 |
Tmin=0.1
|
117 |
Tmax=5.
|
118 |
Tstep=0.1
|
119 |
# Default Number of Iterations
|
120 |
Iterations=Size*Size*Size |
121 |
|
122 |
# Curves is True to print the curves
|
123 |
Curves=False
|
124 |
|
125 |
try:
|
126 |
opts, args = getopt.getopt(sys.argv[1:],"hcj:b:z:i:s:e:p:",["coupling=","magneticfield=","size=","Iterations=","tempstart=","tempend=","tempstep=","units"]) |
127 |
except getopt.GetoptError:
|
128 |
print '%s -j <Coupling Factor> -b <Magnetic Field> -z <Size of Square Lattice> -i <Iterations> -s <Minimum Temperature> -e <Maximum Temperature> -p <steP Temperature> -c (Print Curves)' % sys.argv[0] |
129 |
sys.exit(2)
|
130 |
|
131 |
for opt, arg in opts: |
132 |
if opt == '-h': |
133 |
print '%s -j <Coupling Factor> -b <Magnetic Field> -z <Size of Square Lattice> -i <Iterations> -s <Minimum Temperature> -e <Maximum Temperature> -p <steP Temperature> -c (Print Curves)' % sys.argv[0] |
134 |
sys.exit() |
135 |
elif opt == '-c': |
136 |
Curves=True
|
137 |
elif opt in ("-j", "--coupling"): |
138 |
J = float(arg)
|
139 |
elif opt in ("-b", "--magneticfield"): |
140 |
B = float(arg)
|
141 |
elif opt in ("-s", "--tempmin"): |
142 |
Tmin = float(arg)
|
143 |
elif opt in ("-e", "--tempmax"): |
144 |
Tmax = arg |
145 |
elif opt in ("-p", "--tempstep"): |
146 |
Tstep = numpy.uint32(arg) |
147 |
elif opt in ("-i", "--iterations"): |
148 |
Iterations = int(arg)
|
149 |
elif opt in ("-z", "--size"): |
150 |
Size = int(arg)
|
151 |
|
152 |
print "Coupling Factor J : %s" % J |
153 |
print "Magnetic Field B : %s" % B |
154 |
print "Size of lattice : %s" % Size |
155 |
print "Iterations : %s" % Iterations |
156 |
print "Temperature on start : %s" % Tmin |
157 |
print "Temperature on end : %s" % Tmax |
158 |
print "Temperature step : %s" % Tstep |
159 |
|
160 |
LAPIMAGE=False
|
161 |
|
162 |
sigmaIn=numpy.where(numpy.random.randn(Size,Size)>0,1,-1).astype(numpy.int8) |
163 |
|
164 |
ImageOutput(sigmaIn,"Ising2D_MPI_%i_Initial" % (Size))
|
165 |
|
166 |
Trange=numpy.arange(Tmin,Tmax+Tstep,Tstep) |
167 |
|
168 |
sigmaIn=numpy.where(numpy.random.randn(Size,Size)>0
|
169 |
,1,-1).astype(numpy.int8) |
170 |
|
171 |
numpy.random.seed(int(time.time()))
|
172 |
|
173 |
# Master control distribution of computing
|
174 |
print "Distributing work to %i node(s)..." % NODES |
175 |
Distribution=numpy.array_split(Trange,NODES) |
176 |
|
177 |
for i in range(NODES): |
178 |
|
179 |
Input=Distribution[i] |
180 |
print "Send from 0 to %i %s" % (i+1,Input) |
181 |
ToSend=sigmaIn,J,B,Iterations,Input |
182 |
# Send MPI call to each node
|
183 |
comm.send(ToSend, dest=i+1, tag=11) |
184 |
|
185 |
print "Retreive results..." |
186 |
|
187 |
Results=[] |
188 |
for i in range(NODES): |
189 |
# Receive MPI call from each node
|
190 |
Output=comm.recv(source=i+1,tag=11) |
191 |
print "Result from %i: %s" % (i+1,Output) |
192 |
Results+=Output |
193 |
|
194 |
E=numpy.array(Results)[:,1]
|
195 |
M=numpy.array(Results)[:,2]
|
196 |
|
197 |
numpy.savez("Ising2D_MPI_%i_%.8i" % (Size,Iterations),(Trange,E,M))
|
198 |
|
199 |
# Estimate Critical temperature
|
200 |
print "The critical temperature on %ix%i lattice with J=%f, B=%f is %f " % (Size,Size,J,B,CriticalT(Trange,E)) |
201 |
|
202 |
if Curves:
|
203 |
DisplayCurves(Trange,E,M,J,B) |
204 |
else:
|
205 |
numpy.random.seed(int(time.time()/rank))
|
206 |
# Slave applies simulation to set provided by master
|
207 |
# Receive MPI call with Input set
|
208 |
ToSplit=comm.recv(source=0, tag=11) |
209 |
sigmaIn,J,B,Iterations,Input=ToSplit |
210 |
print "Rank %i receive with %ix%i lattice at J=%.2f, B=%.2f with %i iterations and T=%s" % (rank,sigmaIn.shape[0],sigmaIn.shape[1],J,B,Iterations,Input) |
211 |
Output=[] |
212 |
# Launch simulations on the set, one by one
|
213 |
for T in Input: |
214 |
print "Processing T=%.2f on rank %i" % (T,rank) |
215 |
# Reinitialize to original
|
216 |
sigma=numpy.copy(sigmaIn) |
217 |
duration=Metropolis(sigma,J,B,T,Iterations) |
218 |
print "CPU Time : %f" % (duration) |
219 |
E=Energy(sigma,J,B) |
220 |
M=Magnetization(sigma,0.)
|
221 |
ImageOutput(sigma,"Ising2D_MPI_%i_%1.1f_Final" %
|
222 |
(sigmaIn.shape[0],T))
|
223 |
Output.append([T,E,M]) |
224 |
comm.send(Output, dest=0, tag=11) |