Statistiques
| Révision :

root / Ising / MPI / Ising2D-MPI.py @ 98

Historique | Voir | Annoter | Télécharger (7,03 ko)

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