source: trunk/anuga_work/development/parallel/build_commun.py @ 8538

Last change on this file since 8538 was 8538, checked in by steve, 12 years ago

added variable ghost_layer_width which is set by the partitioning routine
(distribute) or set to 2

File size: 10.5 KB
Line 
1#########################################################
2#
3# Handle the communication between the host machine
4# (processor 0) and the processors. The host machine is
5# responsible for the doing the initial grid partitioning.
6#
7# The routines given below should be moved to the
8# build_submesh.py and build_local.py file to allow
9# overlapping of  communication and computation.
10# This should be done after more debugging.
11#
12#
13#  Author: Linda Stals, June 2005
14#  Modified: Linda Stals, Nov 2005 (optimise python code)
15#
16#
17#########################################################
18
19
20
21import numpy as num
22from anuga import indent
23
24from numpy import array, zeros
25import logging
26import logging.config
27logger = logging.getLogger('parallel')
28logger.setLevel(logging.WARNING)
29
30try:
31    logging.config.fileConfig('log.ini')
32except:
33    pass
34
35import sys
36
37import pypar
38
39from build_local import build_local_mesh
40
41#########################################################
42#
43# Send the submesh to processor p.
44#
45# *) The order and form is strongly coupled with
46# rec_submesh.
47#
48# -------------------------------------------------------
49#
50# *) All of the information has been sent to processor p.
51#
52#########################################################
53
54def send_submesh(submesh, triangles_per_proc, p):
55
56    myid = pypar.rank()
57    print 'process %d sending submesh to process %d' %(myid, p)
58   
59    # build and send the tagmap for the boundary conditions
60   
61    tagmap = {}
62    counter = 1
63    for b in submesh["full_boundary"][p]:
64         bkey = submesh["full_boundary"][p][b]
65         if not tagmap.has_key(bkey):
66             tagmap[bkey] = counter
67             counter = counter+1
68    for b in submesh["ghost_boundary"][p]:
69         bkey = submesh["ghost_boundary"][p][b]
70         if not tagmap.has_key(bkey):
71             tagmap[bkey] = counter
72             counter = counter+1
73    pypar.send(tagmap, p)
74
75    # send the quantities key information
76   
77    pypar.send(submesh["full_quan"].keys(), p)
78   
79    # send the number of triangles per processor
80
81    pypar.send(triangles_per_proc, p, use_buffer=True)
82
83    # compress full_commun
84
85    flat_full_commun = []
86
87    for c in submesh["full_commun"][p]:
88        for i in range(len(submesh["full_commun"][p][c])):
89            flat_full_commun.append([c,submesh["full_commun"][p][c][i]])
90
91    # send the array sizes so memory can be allocated
92
93    setup_array = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
94    setup_array[0] = len(submesh["full_nodes"][p])
95    setup_array[1] = len(submesh["ghost_nodes"][p])
96    setup_array[2] = len(submesh["full_triangles"][p])
97    setup_array[3] = len(submesh["ghost_triangles"][p])
98    setup_array[4] = len(submesh["full_boundary"][p])
99    setup_array[5] = len(submesh["ghost_boundary"][p])
100    setup_array[6] = len(submesh["ghost_commun"][p])
101    setup_array[7] = len(flat_full_commun)
102
103    pypar.send(setup_array, p)
104   
105    # send the nodes
106   
107    pypar.send(submesh["full_nodes"][p], p, use_buffer=True)
108    pypar.send(submesh["ghost_nodes"][p], p, use_buffer=True)
109
110    # send the triangles
111
112    pypar.send(array(submesh["full_triangles"][p], num.int), p, use_buffer=True)
113    pypar.send(submesh["ghost_triangles"][p], p, use_buffer=True)
114
115    # send the boundary
116
117    bc = []
118    for b in submesh["full_boundary"][p]:
119        bc.append([b[0], b[1], tagmap[submesh["full_boundary"][p][b]]])
120    pypar.send(bc, p, use_buffer=True)
121    bc = []
122    for b in submesh["ghost_boundary"][p]:
123        bc.append([b[0], b[1], tagmap[submesh["ghost_boundary"][p][b]]])
124    pypar.send(bc, p, use_buffer=True)
125
126    # send the communication pattern
127
128    pypar.send(submesh["ghost_commun"][p], p, use_buffer=True)
129    pypar.send(flat_full_commun, p, use_buffer=True)
130
131    # send the quantities
132   
133    for k in submesh["full_quan"]:
134        pypar.send(submesh["full_quan"][k][p], p, use_buffer=True)
135       
136    for k in submesh["ghost_quan"]:
137        pypar.send(submesh["ghost_quan"][k][p], p, use_buffer=True)
138       
139
140#########################################################
141#
142# Receive the submesh from processor p.
143#
144# *) The order and form is strongly coupled with
145# send_submesh.
146#
147# -------------------------------------------------------
148#
149# *) All of the information has been received by the
150# processor p and passed into build_local.
151#
152# *) The information is returned in a form needed by the
153# GA datastructure.
154#
155#########################################################
156
157def rec_submesh_flat(p):
158
159    numproc = pypar.size()
160    myid = pypar.rank()
161
162    submesh_cell = {}
163   
164    print 'P%d: Receiving submesh from P%d' %(myid, p)
165
166    # receive the tagmap for the boundary conditions
167   
168    tagmap = pypar.receive(p)
169    itagmap = {}
170    for t in tagmap:
171        itagmap[tagmap[t]]=t
172
173    # receive the quantities key information
174   
175    qkeys = pypar.receive(p)
176
177    # receive the number of triangles per processor
178
179    triangles_per_proc = []
180    for i in range(numproc):
181        triangles_per_proc.append([0])
182
183    triangles_per_proc = pypar.receive(p, triangles_per_proc)
184
185    # recieve information about the array sizes
186
187    setup_array = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
188    setup_array = pypar.receive(p, setup_array)
189
190    # receive the full nodes
191
192    no_full_nodes = setup_array[0]
193    full_nodes = zeros((no_full_nodes, 3), num.float)
194    submesh_cell["full_nodes"] = pypar.receive(p, full_nodes)
195   
196    # receive the ghost nodes
197
198    no_ghost_nodes = setup_array[1]
199    ghost_nodes = zeros((no_ghost_nodes, 3), num.float)
200    submesh_cell["ghost_nodes"] = pypar.receive(p, ghost_nodes)
201
202   
203    # receive the full triangles
204
205    no_full_triangles = setup_array[2]
206    full_triangles = zeros((no_full_triangles, 3), Int)
207    submesh_cell["full_triangles"] = pypar.receive(p, full_triangles)
208   
209    # receive the ghost triangles
210
211    no_ghost_triangles = setup_array[3]
212    ghost_triangles = zeros((no_ghost_triangles, 4), Int)
213    submesh_cell["ghost_triangles"] = pypar.receive(p, ghost_triangles)
214   
215    # receive the full boundary
216
217    no_full_boundary = setup_array[4]
218    bc = []
219    for i in range(no_full_boundary):
220        bc.append([0.0, 0.0, 0.0])
221    bnd_c = pypar.receive(p, bc)
222
223    submesh_cell["full_boundary"] = {}
224    for b in bnd_c:
225        submesh_cell["full_boundary"][b[0],b[1]]=itagmap[b[2]]
226
227    # receive the ghost boundary
228
229    no_ghost_boundary = setup_array[5]
230    bc = []
231    for i in range(no_ghost_boundary):
232        bc.append([0.0, 0.0, 0.0])
233    bnd_c = pypar.receive(p, bc)
234
235    submesh_cell["ghost_boundary"] = {}
236    for b in bnd_c:
237        submesh_cell["ghost_boundary"][b[0],b[1]]=itagmap[b[2]]
238
239    # receive the ghost communication pattern
240
241    no_ghost_commun = setup_array[6]
242    ghost_commun = zeros((no_ghost_commun, 2), Int)
243    submesh_cell["ghost_commun"] = pypar.receive(p, ghost_commun)
244   
245    # receive the full communication pattern
246
247    no_full_commun = setup_array[7]
248    full_commun = []
249    for i in range(no_full_commun):
250        full_commun.append([0.0, 0.0])
251
252    full_commun = pypar.receive(p, full_commun)
253
254    submesh_cell["full_commun"] = {}
255    for c in full_commun:
256        submesh_cell["full_commun"][c[0]] = []
257    for c in full_commun:
258        submesh_cell["full_commun"][c[0]].append(c[1])
259
260    # receive the quantities
261
262    no_quantities = len(qkeys)
263    new_quan = zeros((no_full_triangles, 3), num.float)
264    submesh_cell["full_quan"]={}
265   
266    for i in range(no_quantities):
267        tmp = pypar.receive(p, new_quan)
268        submesh_cell["full_quan"][qkeys[i]]=zeros((no_full_triangles,3), num.float)
269        submesh_cell["full_quan"][qkeys[i]][:] = tmp[:]
270
271    new_quan = zeros((no_ghost_triangles, 3), num.float)
272    submesh_cell["ghost_quan"]={}
273    for i in range(no_quantities):
274        tmp = pypar.receive(p, new_quan)
275        submesh_cell["ghost_quan"][qkeys[i]]= zeros((no_ghost_triangles,3), num.float)
276        submesh_cell["ghost_quan"][qkeys[i]][:] = tmp[:]
277   
278    return submesh_cell, triangles_per_proc
279
280
281
282#########################################################
283#
284# Receive the submesh from processor p.
285#
286# *) The order and form is strongly coupled with
287# send_submesh.
288#
289# -------------------------------------------------------
290#
291# *) All of the information has been received by the
292# processor p and passed into build_local.
293#
294# *) The information is returned in a form needed by the
295# GA datastructure.
296#
297#########################################################
298
299def rec_submesh(p):
300
301    numproc = pypar.size()
302    myid = pypar.rank()
303
304    [submesh_cell, triangles_per_proc] = rec_submesh_flat(p)
305   
306    # find the full triangles assigned to this processor
307
308    lower_t = 0
309    for i in range(myid):
310        lower_t = lower_t+triangles_per_proc[i]
311    upper_t = lower_t+triangles_per_proc[myid]
312
313    # convert the information into a form needed by the GA
314    # datastructure
315
316    [GAnodes, GAtriangles, boundary, quantities, ghost_rec, full_send] = \
317              build_local_mesh(submesh_cell, lower_t, upper_t, \
318                               numproc)
319   
320    return GAnodes, GAtriangles, boundary, quantities, ghost_rec, full_send
321
322#########################################################
323#
324# Extract the submesh that will belong to the
325# "host processor" (i.e. processor zero)
326#
327#  *) See the documentation for build_submesh
328#
329# -------------------------------------------------------
330#
331#  *) A dictionary containing the full_triangles,
332# full_nodes, full_boundary, ghost_triangles, ghost_nodes,
333# ghost_boundary, ghost_commun and full_commun belonging
334# to processor zero are returned.
335#
336#########################################################
337def extract_hostmesh(submesh, triangles_per_proc):
338
339    submesh_cell = {}
340    submesh_cell["full_nodes"] = submesh["full_nodes"][0]
341    submesh_cell["ghost_nodes"] = submesh["ghost_nodes"][0]
342    submesh_cell["full_triangles"] = submesh["full_triangles"][0]
343    submesh_cell["ghost_triangles"] = submesh["ghost_triangles"][0]
344    submesh_cell["full_boundary"] = submesh["full_boundary"][0]
345    submesh_cell["ghost_boundary"] = submesh["ghost_boundary"][0]
346    submesh_cell["ghost_commun"] = submesh["ghost_commun"][0]
347    submesh_cell["full_commun"] = submesh["full_commun"][0]
348    submesh_cell["full_quan"] ={}
349    submesh_cell["ghost_quan"]={}
350    for k in submesh["full_quan"]:
351        submesh_cell["full_quan"][k] = submesh["full_quan"][k][0]
352        submesh_cell["ghost_quan"][k] = submesh["ghost_quan"][k][0]
353
354    numprocs = pypar.size()
355    points, vertices, boundary, quantities, ghost_recv_dict, full_send_dict = \
356            build_local_mesh(submesh_cell, 0, triangles_per_proc[0], numprocs)
357    return  points, vertices, boundary, quantities, ghost_recv_dict, \
358           full_send_dict
359
360
361
Note: See TracBrowser for help on using the repository browser.