source: inundation/parallel/pmesh_divide.py @ 2090

Last change on this file since 2090 was 2090, checked in by linda, 18 years ago

Removed pypar test files and commented pmesh_divide

File size: 10.6 KB
Line 
1#########################################################
2#
3#
4#  Read in a data file and subdivide the triangle list
5#
6#
7#  This is only intended as a temporary file, once an
8# automatic grid partitioner has been incorporated this
9# file will become redundant.
10#
11#  Authors: Linda Stals and Matthew Hardy, June 2005
12#  Modified: Linda Stals, Nov 2005
13#
14#
15#########################################################
16
17
18from math import floor
19from Numeric import zeros, Float, Int, reshape
20
21#########################################################
22#
23# If the triangles list is reordered, the quantities
24# assigned to the triangles must also be reorded.
25#
26# *) quantities contain the quantites in the old ordering
27# *) proc_sum[i] contains the number of triangles in
28# processor i
29# *) tri_index is a map from the old triangle ordering to
30# the new ordering, where the new number for triangle
31# i is proc_sum[tri_index[i][0]]+tri_index[i][1]
32#
33# -------------------------------------------------------
34#
35# *) The quantaties are returned in the new ordering
36#
37#########################################################
38
39def reorder(quantities, tri_index, proc_sum):
40
41    # find the number triangles
42
43    N = len(tri_index)
44
45    # temporary storage area
46
47    index = zeros(N, Int)
48    q_reord = {}
49
50    # find the new ordering of the triangles
51
52    for i in range(N):
53        bin = tri_index[i][0]
54        bin_off_set = tri_index[i][1]
55        index[i] = proc_sum[bin]+bin_off_set
56
57    # reorder each quantity according to the new ordering
58
59    for k in quantities:
60        q_reord[k] = zeros((N, 3), Float)
61        for i in range(N):
62            q_reord[k][index[i]]=quantities[k].vertex_values[i]
63    del index
64
65    return q_reord
66
67
68#########################################################
69#
70# Do a simple coordinate based division of the grid
71#
72# *) n_x is the number of subdivisions in the x direction
73# *) n_y is the number of subdivisions in the y direction
74#
75# -------------------------------------------------------
76#
77# *)  The nodes, triangles, boundary, and quantities are
78# returned. triangles_per_proc defines the subdivision.
79# The first triangles_per_proc[0] triangles are assigned
80# to processor 0, the next triangles_per_proc[1] are
81# assigned to processor 1 etc. The boundary and quantites
82# are ordered the same way as the triangles
83#
84#########################################################
85
86def pmesh_divide(domain, n_x = 1, n_y = 1):
87
88    # find the bounding box
89   
90    x_coord_min = domain.xy_extent[0]
91    x_coord_max = domain.xy_extent[2]
92    y_coord_min = domain.xy_extent[1]
93    y_coord_max = domain.xy_extent[3]
94
95    # find the size of each sub-box
96
97    x_div = (x_coord_max-x_coord_min)/n_x
98    y_div = (y_coord_max-y_coord_min)/n_y
99
100    # initialise the lists
101   
102    tri_list = []
103    triangles_per_proc = []
104    proc_sum = []
105    for i in range(n_x*n_y):
106        tri_list.append([])
107        triangles_per_proc.append([])
108        proc_sum.append([])
109        tri_list[i] = []
110
111    # subdivide the triangles depending on which sub-box they sit
112    # in (a triangle sits in the sub-box if its first vectex sits
113    # in that sub-box)
114
115    tri_index = {}
116    N = domain.number_of_elements
117    for i in range(N):
118        t = domain.triangles[i]
119
120        x_coord = domain.centroid_coordinates[i][0]
121        bin_x = int(floor((x_coord-x_coord_min)/x_div))
122        if (bin_x == n_x):
123            bin_x = n_x-1
124
125        y_coord = domain.centroid_coordinates[i][1]
126        bin_y = int(floor((y_coord-y_coord_min)/y_div))
127        if (bin_y == n_y):
128            bin_y = n_y-1
129
130        bin = bin_y*n_x + bin_x
131        tri_list[bin].append(t)
132        tri_index[i] = ([bin, len(tri_list[bin])-1])
133
134    # find the number of triangles per processor and order the
135    # triangle list so that all of the triangles belonging to
136    # processor i are listed before those belonging to processor
137    # i+1
138
139    triangles = []
140    for i in range(n_x*n_y):
141        triangles_per_proc[i] = len(tri_list[i])
142        for t in tri_list[i]:
143            triangles.append(t)
144
145    # the boundary labels have to changed in accoradance with the
146    # new triangle ordering, proc_sum and tri_index help with this
147
148    proc_sum[0] = 0
149    for i in range(n_x*n_y-1):
150        proc_sum[i+1]=proc_sum[i]+triangles_per_proc[i]
151
152    # relabel the boundary elements to fit in with the new triangle
153    # ordering
154
155    boundary = {}
156    for b in domain.boundary:
157        t =  tri_index[b[0]]
158        boundary[proc_sum[t[0]]+t[1], b[1]] = domain.boundary[b]
159
160    quantities = reorder(domain.quantities, tri_index, proc_sum)
161
162    # extract the node list
163   
164    nodes = domain.coordinates.copy()
165    ttriangles = zeros((len(triangles), 3), Int)
166    for i in range(len(triangles)):
167        ttriangles[i] = triangles[i]
168       
169    return nodes, ttriangles, boundary, triangles_per_proc, quantities
170
171
172#########################################################
173#
174# Do a coordinate based division of the grid using the
175# centroid coordinate
176#
177# *) n_x is the number of subdivisions in the x direction
178# *) n_y is the number of subdivisions in the y direction
179#
180# -------------------------------------------------------
181#
182# *)  The nodes, triangles, boundary, and quantities are
183# returned. triangles_per_proc defines the subdivision.
184# The first triangles_per_proc[0] triangles are assigned
185# to processor 0, the next triangles_per_proc[1] are
186# assigned to processor 1 etc. The boundary and quantites
187# are ordered the same way as the triangles
188#
189#########################################################
190def pmesh_divide_steve(domain, n_x = 1, n_y = 1):
191   
192    # find the bounding box
193    x_coord_min = domain.xy_extent[0]
194    x_coord_max = domain.xy_extent[2]
195    y_coord_min = domain.xy_extent[1]
196    y_coord_max = domain.xy_extent[3]
197
198
199    # find the size of each sub-box
200
201    x_div = (x_coord_max-x_coord_min)/n_x
202    y_div = (y_coord_max-y_coord_min)/n_y
203
204
205    # initialise the lists
206    tri_list = []
207    triangles_per_proc = []
208    proc_sum = []
209    for i in range(n_x*n_y):
210        tri_list.append([])
211        triangles_per_proc.append([])
212        proc_sum.append([])
213        tri_list[i] = []
214
215    # subdivide the triangles depending on which sub-box they sit
216    # in (a triangle sits in the sub-box if its first vectex sits
217    # in that sub-box)
218
219    tri_index = {}
220    N = domain.number_of_elements
221 
222    #sort by x coordinate of centroid
223    from Numeric import argsort
224    sort_order = argsort(argsort(domain.centroid_coordinates[:,0]))
225
226    x_div = float(N)/n_x
227
228    for i in range(N):
229        t = domain.triangles[i]
230       
231        bin = int(floor(sort_order[i]/x_div))
232        if (bin == n_x):
233            bin = n_x-1
234
235        tri_list[bin].append(t)
236        tri_index[i] = ([bin, len(tri_list[bin])-1])
237
238    #print tri_list
239    #print tri_index
240
241    # find the number of triangles per processor and order the
242    # triangle list so that all of the triangles belonging to
243    # processor i are listed before those belonging to processor
244    # i+1
245
246    triangles = []
247    for i in range(n_x*n_y):
248        triangles_per_proc[i] = len(tri_list[i])
249        for t in tri_list[i]:
250           triangles.append(t)
251       
252
253    # the boundary labels have to changed in accoradance with the
254    # new triangle ordering, proc_sum and tri_index help with this
255
256    proc_sum[0] = 0
257    for i in range(n_x*n_y-1):
258        proc_sum[i+1]=proc_sum[i]+triangles_per_proc[i]
259
260    # relabel the boundary elements to fit in with the new triangle
261    # ordering
262
263    boundary = {}
264    for b in domain.boundary:
265        t =  tri_index[b[0]]
266        boundary[proc_sum[t[0]]+t[1], b[1]] = domain.boundary[b]
267
268    quantities = reorder(domain.quantities, tri_index, proc_sum)
269
270    # extract the node list
271    nodes = domain.coordinates.copy()
272
273
274    # convert the triangle datastructure to be an array typ
275    # this helps with the communication
276
277    ttriangles = zeros((len(triangles), 3), Int)
278    for i in range(len(triangles)):
279        ttriangles[i] = triangles[i]
280       
281    return nodes, ttriangles, boundary, triangles_per_proc, quantities
282
283
284
285
286###
287#
288# Divide the mesh using a call to metis, through pymetis.
289
290from os import sep
291from sys import path
292
293path.append('..' + sep + 'pymetis')
294
295from metis import partMeshNodal
296
297def pmesh_divide_metis(domain, n_procs):
298    # initialise the lists
299    # List, indexed by processor of # triangles.
300    triangles_per_proc = []
301    # List of lists, indexed by processor of vertex numbers
302    tri_list = []
303    # List indexed by processor of cumulative total of triangles allocated.
304    proc_sum = []
305    for i in range(n_procs):
306        tri_list.append([])
307        triangles_per_proc.append(0)
308        proc_sum.append([])
309
310    # Prepare variables for the metis call
311    n_tri = len(domain.triangles)
312    n_vert = len(domain.coordinates)
313    t_list = domain.triangles.copy()
314    t_list = reshape(t_list, (-1,))
315   
316    # The 1 here is for triangular mesh elements.
317    edgecut, epart, npart = partMeshNodal(n_tri, n_vert, t_list, 1, n_procs)
318   
319    # print edgecut
320    # print epart
321    # print npart
322
323    del edgecut
324    del npart
325
326    # Assign triangles to processes, according to what metis told us.
327
328    # tri_index maps triangle number -> processor, new triangle number
329    # (local to the processor)
330    tri_index = {}
331    triangles = []       
332    for i in range(n_tri):
333        triangles_per_proc[epart[i]] = triangles_per_proc[epart[i]] + 1
334        tri_list[epart[i]].append(domain.triangles[i])
335        tri_index[i] = ([epart[i], len(tri_list[epart[i]]) - 1])
336
337    # print tri_list
338    # print triangles_per_proc
339
340    # order the triangle list so that all of the triangles belonging
341    # to processor i are listed before those belonging to processor
342    # i+1
343
344    for i in range(n_procs):
345        for t in tri_list[i]:
346            triangles.append(t)
347           
348    # the boundary labels have to changed in accoradance with the
349    # new triangle ordering, proc_sum and tri_index help with this
350
351    proc_sum[0] = 0
352    for i in range(n_procs - 1):
353        proc_sum[i+1]=proc_sum[i]+triangles_per_proc[i]
354
355    # relabel the boundary elements to fit in with the new triangle
356    # ordering
357
358    boundary = {}
359    for b in domain.boundary:
360        t =  tri_index[b[0]]
361        boundary[proc_sum[t[0]]+t[1], b[1]] = domain.boundary[b]
362
363    quantities = reorder(domain.quantities, tri_index, proc_sum)
364
365    # extract the node list
366    nodes = domain.coordinates.copy()
367
368    # convert the triangle datastructure to be an array type
369    # this helps with the communication
370
371    ttriangles = zeros((len(triangles), 3), Int)
372    for i in range(len(triangles)):
373        ttriangles[i] = triangles[i]
374       
375    return nodes, ttriangles, boundary, triangles_per_proc, quantities
Note: See TracBrowser for help on using the repository browser.