Statistiques
| Révision :

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

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)