root / Ising / MP / Ising2D-MP.py @ 148
Historique | Voir | Annoter | Télécharger (5,38 ko)
1 | 18 | equemene | #!/usr/bin/env python
|
---|---|---|---|
2 | 18 | equemene | #
|
3 | 18 | equemene | # Ising2D model in serial mode
|
4 | 18 | equemene | #
|
5 | 18 | equemene | # CC BY-NC-SA 2011 : <emmanuel.quemener@ens-lyon.fr>
|
6 | 18 | equemene | |
7 | 18 | equemene | import sys |
8 | 18 | equemene | import numpy |
9 | 18 | equemene | from PIL import Image |
10 | 18 | equemene | from math import exp |
11 | 18 | equemene | from random import random |
12 | 18 | equemene | import time |
13 | 18 | equemene | import getopt |
14 | 18 | equemene | import matplotlib.pyplot as plt |
15 | 18 | equemene | |
16 | 18 | equemene | from multiprocessing import Pool |
17 | 18 | equemene | |
18 | 18 | equemene | def ImageOutput(sigma,prefix): |
19 | 18 | equemene | Max=sigma.max() |
20 | 18 | equemene | Min=sigma.min() |
21 | 18 | equemene | |
22 | 18 | equemene | # Normalize value as 8bits Integer
|
23 | 18 | equemene | SigmaInt=(255*(sigma-Min)/(Max-Min)).astype('uint8') |
24 | 18 | equemene | image = Image.fromarray(SigmaInt) |
25 | 18 | equemene | image.save("%s.jpg" % prefix)
|
26 | 18 | equemene | |
27 | 18 | equemene | def Metropolis(sigma,J,B,T,iterations): |
28 | 18 | equemene | start=time.time() |
29 | 18 | equemene | |
30 | 18 | equemene | SizeX,SizeY=sigma.shape |
31 | 18 | equemene | |
32 | 18 | equemene | for p in xrange(0,iterations): |
33 | 18 | equemene | # Random access coordonate
|
34 | 18 | equemene | X,Y=numpy.random.randint(SizeX),numpy.random.randint(SizeY) |
35 | 18 | equemene | |
36 | 88 | equemene | DeltaE=sigma[X,Y]*(2*J*(sigma[X,(Y+1)%SizeY]+ |
37 | 18 | equemene | sigma[X,(Y-1)%SizeY]+
|
38 | 18 | equemene | sigma[(X-1)%SizeX,Y]+
|
39 | 18 | equemene | sigma[(X+1)%SizeX,Y])+B)
|
40 | 18 | equemene | |
41 | 18 | equemene | if DeltaE < 0. or random() < exp(-DeltaE/T): |
42 | 18 | equemene | sigma[X,Y]=-sigma[X,Y] |
43 | 18 | equemene | duration=time.time()-start |
44 | 18 | equemene | return(duration)
|
45 | 18 | equemene | |
46 | 18 | equemene | def Magnetization(sigma,M): |
47 | 18 | equemene | return(numpy.sum(sigma)/(sigma.shape[0]*sigma.shape[1]*1.0)) |
48 | 18 | equemene | |
49 | 88 | equemene | def Energy(sigma,J,B): |
50 | 18 | equemene | # Copier et caster
|
51 | 18 | equemene | E=numpy.copy(sigma).astype(numpy.float32) |
52 | 18 | equemene | |
53 | 18 | equemene | # Appel par slice
|
54 | 88 | equemene | E[1:-1,1:-1]=E[1:-1,1:-1]*(2.*J*(E[:-2,1:-1]+E[2:,1:-1]+ |
55 | 88 | equemene | E[1:-1,:-2]+E[1:-1,2:])+B) |
56 | 18 | equemene | |
57 | 18 | equemene | # Bien nettoyer la peripherie
|
58 | 18 | equemene | E[:,0]=0 |
59 | 18 | equemene | E[:,-1]=0 |
60 | 18 | equemene | E[0,:]=0 |
61 | 18 | equemene | E[-1,:]=0 |
62 | 18 | equemene | |
63 | 18 | equemene | Energy=numpy.sum(E) |
64 | 18 | equemene | |
65 | 18 | equemene | return(Energy/(E.shape[0]*E.shape[1]*1.0)) |
66 | 18 | equemene | |
67 | 88 | equemene | def CriticalT(T,E): |
68 | 88 | equemene | |
69 | 88 | equemene | Epoly=numpy.poly1d(numpy.polyfit(T,E,T.size/3))
|
70 | 88 | equemene | dEpoly=numpy.diff(Epoly(T)) |
71 | 88 | equemene | dEpoly=numpy.insert(dEpoly,0,0) |
72 | 88 | equemene | return(T[numpy.argmin(dEpoly)])
|
73 | 88 | equemene | |
74 | 18 | equemene | def DisplayCurves(T,E,M,J,B): |
75 | 18 | equemene | |
76 | 18 | equemene | plt.xlabel("Temperature")
|
77 | 18 | equemene | plt.ylabel("Energy")
|
78 | 18 | equemene | |
79 | 18 | equemene | Experience,=plt.plot(T,E,label="Energy")
|
80 | 18 | equemene | |
81 | 18 | equemene | plt.legend() |
82 | 18 | equemene | plt.show() |
83 | 18 | equemene | |
84 | 18 | equemene | |
85 | 18 | equemene | if __name__=='__main__': |
86 | 18 | equemene | |
87 | 18 | equemene | # Set defaults values
|
88 | 18 | equemene | # Coupling factor
|
89 | 18 | equemene | J=1.
|
90 | 18 | equemene | # Magnetic Field
|
91 | 18 | equemene | B=0.
|
92 | 18 | equemene | # Size of Lattice
|
93 | 18 | equemene | Size=256
|
94 | 18 | equemene | # Default Temperatures (start, end, step)
|
95 | 18 | equemene | Tmin=0.1
|
96 | 18 | equemene | Tmax=5
|
97 | 18 | equemene | Tstep=0.1
|
98 | 18 | equemene | # Default Number of Iterations
|
99 | 96 | equemene | Iterations=Size*Size*Size |
100 | 18 | equemene | # Default Number of Procs Used
|
101 | 18 | equemene | Procs=4
|
102 | 18 | equemene | |
103 | 18 | equemene | # Curves is True to print the curves
|
104 | 18 | equemene | Curves=False
|
105 | 18 | equemene | |
106 | 18 | equemene | try:
|
107 | 18 | equemene | opts, args = getopt.getopt(sys.argv[1:],"hcj:b:z:i:s:e:p:u:",["coupling=","magneticfield=","size=","iterations=","tempstart=","tempend=","tempstep=","units"]) |
108 | 18 | equemene | except getopt.GetoptError:
|
109 | 98 | equemene | print '%s -j <Coupling Factor> -b <Magnetic Field> -z <Size of Square Lattice> -i <Iterations> -s <Minimum Temperature> -e <Maximum Temperature> -p <steP Temperature> -u <Units of processing> -c (Print Curves)' % sys.argv[0] |
110 | 18 | equemene | sys.exit(2)
|
111 | 18 | equemene | |
112 | 18 | equemene | for opt, arg in opts: |
113 | 18 | equemene | if opt == '-h': |
114 | 98 | equemene | print '%s -j <Coupling Factor> -b <Magnetic Field> -z <Size of Square Lattice> -i <Iterations> -s <Minimum Temperature> -e <Maximum Temperature> -p <steP Temperature> -u <Units of Processing> -c (Print Curves)' % sys.argv[0] |
115 | 18 | equemene | sys.exit() |
116 | 18 | equemene | elif opt == '-c': |
117 | 18 | equemene | Curves=True
|
118 | 18 | equemene | elif opt in ("-j", "--coupling"): |
119 | 18 | equemene | J = float(arg)
|
120 | 18 | equemene | elif opt in ("-b", "--magneticfield"): |
121 | 18 | equemene | B = float(arg)
|
122 | 18 | equemene | elif opt in ("-s", "--tempmin"): |
123 | 18 | equemene | Tmin = float(arg)
|
124 | 18 | equemene | elif opt in ("-e", "--tempmax"): |
125 | 18 | equemene | Tmax = arg |
126 | 18 | equemene | elif opt in ("-p", "--tempstep"): |
127 | 18 | equemene | Tstep = numpy.uint32(arg) |
128 | 18 | equemene | elif opt in ("-i", "--iterations"): |
129 | 18 | equemene | Iterations = int(arg)
|
130 | 18 | equemene | elif opt in ("-z", "--size"): |
131 | 18 | equemene | Size = int(arg)
|
132 | 98 | equemene | elif opt in ("-u", "--units"): |
133 | 18 | equemene | Procs = int(arg)
|
134 | 18 | equemene | |
135 | 18 | equemene | print "Process Units : %s" % Procs |
136 | 18 | equemene | print "Coupling Factor J : %s" % J |
137 | 18 | equemene | print "Magnetic Field B : %s" % B |
138 | 18 | equemene | print "Size of lattice : %s" % Size |
139 | 18 | equemene | print "Iterations : %s" % Iterations |
140 | 18 | equemene | print "Temperature on start : %s" % Tmin |
141 | 18 | equemene | print "Temperature on end : %s" % Tmax |
142 | 18 | equemene | print "Temperature step : %s" % Tstep |
143 | 18 | equemene | |
144 | 18 | equemene | LAPIMAGE=False
|
145 | 18 | equemene | |
146 | 18 | equemene | sigmaIn=numpy.where(numpy.random.randn(Size,Size)>0,1,-1).astype(numpy.int8) |
147 | 18 | equemene | |
148 | 18 | equemene | ImageOutput(sigmaIn,"Ising2D_Serial_%i_Initial" % (Size))
|
149 | 18 | equemene | |
150 | 18 | equemene | Trange=numpy.arange(Tmin,Tmax+Tstep,Tstep) |
151 | 18 | equemene | |
152 | 18 | equemene | def MetropolisStrip(T): |
153 | 18 | equemene | # Indispensable d'utiliser copy : [:] ne fonctionne pas avec numpy !
|
154 | 18 | equemene | sigma=numpy.copy(sigmaIn) |
155 | 18 | equemene | duration=Metropolis(sigma,J,B,T,Iterations) |
156 | 88 | equemene | ImageOutput(sigma,"Ising2D_MP_%i_%1.1f_Final" % (Size,T))
|
157 | 18 | equemene | print "CPU Time : %f" % (duration) |
158 | 88 | equemene | indice=numpy.where(Trange==T)[0][0] |
159 | 88 | equemene | E,M=Energy(sigma,J,B),Magnetization(sigma,B) |
160 | 18 | equemene | print "Total Energy at Temperature %f : %f" % (T,E) |
161 | 18 | equemene | print "Total Magnetization at Temperature %f : %f" % (T,M) |
162 | 88 | equemene | return([T,E,M])
|
163 | 18 | equemene | |
164 | 18 | equemene | pool=Pool(processes=Procs) |
165 | 18 | equemene | print "Start on %i processors..." % Procs |
166 | 18 | equemene | # Apply MAP to POOL
|
167 | 18 | equemene | # MAP: distribution of usecases T to be applied to MetropolisStrip
|
168 | 18 | equemene | Results=pool.map(MetropolisStrip,Trange) |
169 | 18 | equemene | |
170 | 88 | equemene | E=numpy.array(Results)[:,1]
|
171 | 88 | equemene | M=numpy.array(Results)[:,2]
|
172 | 88 | equemene | |
173 | 18 | equemene | # Save output
|
174 | 18 | equemene | numpy.savez("Ising2D_MP_%i_%.8i" % (Size,Iterations),(Trange,E,M))
|
175 | 88 | equemene | |
176 | 88 | equemene | # Estimate Critical temperature
|
177 | 88 | equemene | print "The critical temperature on %ix%i lattice with J=%f, B=%f is %f " % (Size,Size,J,B,CriticalT(Trange,E)) |
178 | 88 | equemene | |
179 | 92 | equemene | if Curves:
|
180 | 92 | equemene | DisplayCurves(Trange,E,M,J,B) |