-
Notifications
You must be signed in to change notification settings - Fork 0
/
random_walk_1d.py
175 lines (154 loc) · 6.42 KB
/
random_walk_1d.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
from mpi4py import MPI
import numpy as np
from random_walk_funcs import *
world = MPI.COMM_WORLD
rank = world.Get_rank()
nProcs = world.Get_size()
class Particle:
pID = None
pX = 0
def __init__(self,pID=None,pX=0):
self.pID = pID
self.pX = pX
def __repr__(self):
return "ID: %s; Location: %s" % (self.pID, self.pX)
# Defining domains for each processor
total_domain_length = 100
if total_domain_length%nProcs != 0:
print "Domain not evenly divisible, please change!"
exit(1)
local_domain_length = total_domain_length/nProcs
domain_start = (rank%nProcs) * local_domain_length
# Definiting initial particle size for each processor
total_no_of_particles = 100
if total_no_of_particles%nProcs != 0:
print "Particles not evenly divisible, please change!"
exit(1)
local_no_of_particles = np.array([total_no_of_particles/nProcs],dtype='i')
if (rank == 0):
particles_in_each_proc = np.zeros(nProcs,dtype='i')
list_of_locations = domain_initialisation(local_no_of_particles,local_domain_length,domain_start)
particleList = []
for id in range(local_no_of_particles):
part_id = rank*local_no_of_particles + id
particleList.append(Particle(part_id,list_of_locations[id]))
# for i in range(local_no_of_particles):
# print(particleList[i],rank,i)
# defining some communication protocols
def sendParticle(particle,to_id,send_id):
world.send(particle,dest=to_id,tag=send_id)
def recvParticle(from_id,recv_id):
particle = world.recv(source=from_id,tag=recv_id)
return particle
def deleteParticle(particle_ID,particleList):
search_index = -1
for id,particle in enumerate(particleList):
if particle.pID == particle_ID:
search_index = id
break
particleList.pop(search_index)
return particleList
def send_left(particlesLeft,step):
left_neighbour = (rank-1)%nProcs
# First send the number of particles present in the list
# Left send and right receive will have series 20000+iter_no*100
# length is communicated in channel 99
no_of_left_particles = np.array([len(particlesLeft)],dtype='i')
if no_of_left_particles >= 98:
print("Find better tag system!")
exit(1)
world.Send([no_of_left_particles,MPI.INT],dest=left_neighbour,tag=(20000+(step*100)+99))
for i in range(no_of_left_particles):
sendParticle(particlesLeft[i],left_neighbour,(20000+(step*100)+i))
def receive_right(particles,step):
right_neighbour = (rank+1)%nProcs
# First receive the number of particles
no_of_right_particles = np.array([0],dtype='i')
world.Recv(no_of_right_particles,source=right_neighbour,tag=(20000+(step*100)+99))
recv_particle = Particle()
for i in range(no_of_right_particles):
recv_particle = recvParticle(right_neighbour,(20000+(step*100)+i))
particles.append(recv_particle)
return particles
def send_right(particlesRight,step):
right_neighbour = (rank+1)%nProcs
# First send the number of particles present in the list
# Left send and right receive will have series 30000+iter_no*100
# length is communicated in channel 99
no_of_right_particles = np.array([len(particlesRight)],dtype='i')
if no_of_right_particles >= 98:
print("Find better tag system!")
exit(1)
world.Send([no_of_right_particles,MPI.INT],dest=right_neighbour,tag=(30000+(step*100)+99))
for i in range(no_of_right_particles):
sendParticle(particlesRight[i],right_neighbour,(30000+(step*100)+i))
def receive_left(particles,step):
left_neighbour = (rank-1)%nProcs
# First receive the number of particles
no_of_left_particles = np.array([0],dtype='i')
world.Recv(no_of_left_particles,source=left_neighbour,tag=(30000+(step*100)+99))
recv_particle = Particle()
for i in range(no_of_left_particles):
recv_particle = recvParticle(left_neighbour,(30000+(step*100)+i))
particles.append(recv_particle)
return particles
def communicate_to_master(step):
# Let this channel be 10000+(step*100)+rank
if (rank != 0):
world.Send(local_no_of_particles,dest=0,tag=(10000+(step*100)+rank))
else:
particles_in_each_proc[0] = local_no_of_particles
for proc_id in range(1,nProcs):
recv_no = np.array([0],dtype='i')
world.Recv(recv_no,source=proc_id,tag=((10000+(step*100)+proc_id)))
particles_in_each_proc[proc_id] = recv_no
# starting random walk
def get_new_location():
upper_limit = np.floor(local_domain_length/2)
lower_limit = np.floor(-1*local_domain_length/2)
return np.floor(np.random.rand(1)*(upper_limit-lower_limit))+lower_limit
def check_new_location(location):
if location < domain_start:
return -1
elif location >= domain_start+local_domain_length:
return 1
else:
return 0
total_no_of_iterations = 1000
for iter_no in range(total_no_of_iterations):
particlesLeft = []
particlesRight = []
for particle in particleList:
particle.pX = get_new_location()
if check_new_location(particle.pX) > 0:
particlesRight.append(particle)
elif check_new_location(particle.pX) < 0:
particlesLeft.append(particle)
# For this tag system, basic assumptions are: the number of processors doesn't exceed 99, the number of particles do not exceed 98
# Left send and right receive will have series 20000+iter_no*100
# Right send and right receive will have 30000+iter_no*100
send_left(particlesLeft,iter_no)
# send_right(particlesRight,iter_no)
# receive_left(particleList,iter_no)
particleList = receive_right(particleList,iter_no)
for i in range(len(particlesLeft)):
particleList = deleteParticle(particlesLeft[i].pID,particleList)
for i in range(len(particlesRight)):
particleList = deleteParticle(particlesRight[i].pID,particleList)
# print("Length of particleList after iteration",iter_no,"in processor",rank,"is",local_no_of_particles)
# Let this channel be 10000+(step*100)+rank
local_no_of_particles = np.array([len(particleList)],dtype='i')
communicate_to_master(iter_no)
# if (rank==0):
# print iter_no,particles_in_each_proc,sum(particles_in_each_proc)
# print "Done",rank
# if (rank==0):
# part0 = Particle(0,5)
# print("before",rank,part0)
# sendParticle(part0,1,100)
# print("after",rank,part0)
# else:
# part1 = Particle()
# print("before",rank,part1)
# part1 = recvParticle(0,100)
# print("after",rank,part1)