source: anuga_core/source/anuga_parallel/parallel_meshes.py @ 5287

Last change on this file since 5287 was 5242, checked in by steve, 17 years ago
File size: 10.2 KB
Line 
1"""parallel-meshes -
22D triangular domains for parallel finite-volume computations of
3the advection equation, with extra structures to define the
4sending and receiving communications define in dictionaries
5full_send_dict and ghost_recv_dict
6
7
8Ole Nielsen, Stephen Roberts, Duncan Gray, Christopher Zoppou
9Geoscience Australia, 2005
10
11Modified by Linda Stals, March 2006, to include ghost boundaries
12
13"""
14
15
16import sys
17from Numeric import array, zeros, Float, Int, ones, sum
18
19import pypar
20
21from anuga.config import epsilon
22
23
24
25
26
27def parallel_rectangle(m_g, n_g, len1_g=1.0, len2_g=1.0, origin_g = (0.0, 0.0)):
28
29
30    """Setup a rectangular grid of triangles
31    with m+1 by n+1 grid points
32    and side lengths len1, len2. If side lengths are omitted
33    the mesh defaults to the unit square, divided between all the
34    processors
35
36    len1: x direction (left to right)
37    len2: y direction (bottom to top)
38
39    """
40
41    processor = pypar.rank()
42    numproc   = pypar.size()
43
44    m_low, m_high = pypar.balance(m_g, numproc, processor)
45   
46    n = n_g
47    m_low  = m_low-1
48    m_high = m_high+1
49    m = m_high - m_low
50
51    delta1 = float(len1_g)/m_g
52    delta2 = float(len2_g)/n_g
53
54    len1 = len1_g*float(m)/float(m_g)
55    len2 = len2_g
56    origin = ( origin_g[0]+float(m_low)/float(m_g)*len1_g, origin_g[1] )
57
58    #Calculate number of points
59    Np = (m+1)*(n+1)
60
61    class VIndex:
62
63        def __init__(self, n,m):
64            self.n = n
65            self.m = m
66
67        def __call__(self, i,j):
68            return j+i*(self.n+1)
69
70    class EIndex:
71
72        def __init__(self, n,m):
73            self.n = n
74            self.m = m
75
76        def __call__(self, i,j):
77            return 2*(j+i*self.n)
78
79
80    I = VIndex(n,m)
81    E = EIndex(n,m)
82
83    points = zeros( (Np,2), Float)
84
85    for i in range(m+1):
86        for j in range(n+1):
87
88            points[I(i,j),:] = [i*delta1 + origin[0], j*delta2 + origin[1]]
89
90    #Construct 2 triangles per rectangular element and assign tags to boundary
91    #Calculate number of triangles
92    Nt = 2*m*n
93
94
95    elements = zeros( (Nt,3), Int)
96    boundary = {}
97    Idgl = []
98    Idfl = []
99    Idgr = []
100    Idfr = []
101
102    full_send_dict = {}
103    ghost_recv_dict = {}
104    nt = -1
105    for i in range(m):
106        for j in range(n):
107
108            i1 = I(i,j+1)
109            i2 = I(i,j)
110            i3 = I(i+1,j+1)
111            i4 = I(i+1,j)
112
113            #Lower Element
114            nt = E(i,j)
115            if i == 0:
116                Idgl.append(nt)
117
118            if i == 1:
119                Idfl.append(nt)
120
121            if i == m-2:
122                Idfr.append(nt)
123
124            if i == m-1:
125                Idgr.append(nt)
126
127            if i == m-1:
128                if processor == numproc-1:
129                    boundary[nt, 2] = 'right'
130                else:
131                    boundary[nt, 2] = 'ghost'
132       
133            if j == 0:
134                boundary[nt, 1] = 'bottom'
135            elements[nt,:] = [i4,i3,i2]
136
137            #Upper Element
138            nt = E(i,j)+1
139            if i == 0:
140                Idgl.append(nt)
141
142            if i == 1:
143                Idfl.append(nt)
144
145            if i == m-2:
146                Idfr.append(nt)
147
148            if i == m-1:
149                Idgr.append(nt)
150
151            if i == 0:
152                if processor == 0:
153                    boundary[nt, 2] = 'left'
154                else:
155                    boundary[nt, 2] = 'ghost'
156            if j == n-1:
157                boundary[nt, 1] = 'top'
158            elements[nt,:] = [i1,i2,i3]
159
160    if numproc==1:
161        Idfl.extend(Idfr)
162        Idgr.extend(Idgl)
163        Idfl = array(Idfl,Int)
164        Idgr = array(Idgr,Int)
165        full_send_dict[processor]  = [Idfl, Idfl]
166        ghost_recv_dict[processor] = [Idgr, Idgr]
167    elif numproc == 2:
168        Idfl.extend(Idfr)
169        Idgr.extend(Idgl)
170        Idfl = array(Idfl,Int)
171        Idgr = array(Idgr,Int)
172        full_send_dict[(processor-1)%numproc]  = [Idfl, Idfl]
173        ghost_recv_dict[(processor-1)%numproc] = [Idgr, Idgr]
174    else:
175        Idfl = array(Idfl,Int)
176        Idgl = array(Idgl,Int)
177
178        Idfr = array(Idfr,Int)
179        Idgr = array(Idgr,Int)
180
181        full_send_dict[(processor-1)%numproc]  = [Idfl, Idfl]
182        ghost_recv_dict[(processor-1)%numproc] = [Idgl, Idgl]
183        full_send_dict[(processor+1)%numproc]  = [Idfr, Idfr]
184        ghost_recv_dict[(processor+1)%numproc] = [Idgr, Idgr]
185
186
187
188       
189   
190    return  points, elements, boundary, full_send_dict, ghost_recv_dict
191
192
193
194def rectangular_periodic(m, n, len1=1.0, len2=1.0, origin = (0.0, 0.0)):
195
196
197    """Setup a rectangular grid of triangles
198    with m+1 by n+1 grid points
199    and side lengths len1, len2. If side lengths are omitted
200    the mesh defaults to the unit square.
201
202    len1: x direction (left to right)
203    len2: y direction (bottom to top)
204
205    Return to lists: points and elements suitable for creating a Mesh or
206    FVMesh object, e.g. Mesh(points, elements)
207    """
208
209    delta1 = float(len1)/m
210    delta2 = float(len2)/n
211
212    #Calculate number of points
213    Np = (m+1)*(n+1)
214
215    class VIndex:
216
217        def __init__(self, n,m):
218            self.n = n
219            self.m = m
220
221        def __call__(self, i,j):
222            return j+i*(self.n+1)
223
224    class EIndex:
225
226        def __init__(self, n,m):
227            self.n = n
228            self.m = m
229
230        def __call__(self, i,j):
231            return 2*(j+i*self.n)
232
233
234    I = VIndex(n,m)
235    E = EIndex(n,m)
236
237    points = zeros( (Np,2), Float)
238
239    for i in range(m+1):
240        for j in range(n+1):
241
242            points[I(i,j),:] = [i*delta1 + origin[0], j*delta2 + origin[1]]
243
244    #Construct 2 triangles per rectangular element and assign tags to boundary
245    #Calculate number of triangles
246    Nt = 2*m*n
247
248
249    elements = zeros( (Nt,3), Int)
250    boundary = {}
251    ghosts = {}
252    nt = -1
253    for i in range(m):
254        for j in range(n):
255
256            i1 = I(i,j+1)
257            i2 = I(i,j)
258            i3 = I(i+1,j+1)
259            i4 = I(i+1,j)
260
261            #Lower Element
262            nt = E(i,j)
263            if i == m-1:
264                ghosts[nt] = E(1,j)
265            if i == 0:
266                ghosts[nt] = E(m-2,j)
267
268            if j == n-1:
269                ghosts[nt] = E(i,1)
270
271            if j == 0:
272                ghosts[nt] = E(i,n-2)
273
274            if i == m-1:
275                if processor == numproc-1:
276                    boundary[nt, 2] = 'right'
277                else:
278                    boundary[nt, 2] = 'ghost'
279            if j == 0:
280                boundary[nt, 1] = 'bottom'
281            elements[nt,:] = [i4,i3,i2]
282
283            #Upper Element
284            nt = E(i,j)+1
285            if i == m-1:
286                ghosts[nt] = E(1,j)+1
287            if i == 0:
288                ghosts[nt] = E(m-2,j)+1
289
290            if j == n-1:
291                ghosts[nt] = E(i,1)+1
292
293            if j == 0:
294                ghosts[nt] = E(i,n-2)+1
295
296            if i == 0:
297                if processor == 0:
298                    boundary[nt, 2] = 'left'
299                else:
300                    boundary[nt, 2] = 'ghost'
301            if j == n-1:
302                boundary[nt, 1] = 'top'
303            elements[nt,:] = [i1,i2,i3]
304
305    #bottom left
306    nt = E(0,0)
307    nf = E(m-2,n-2)
308    ghosts[nt]   = nf
309    ghosts[nt+1] = nf+1
310
311    #bottom right
312    nt = E(m-1,0)
313    nf = E(1,n-2)
314    ghosts[nt]   = nf
315    ghosts[nt+1] = nf+1
316
317    #top left
318    nt = E(0,n-1)
319    nf = E(m-2,1)
320    ghosts[nt]   = nf
321    ghosts[nt+1] = nf+1
322
323    #top right
324    nt = E(m-1,n-1)
325    nf = E(1,1)
326    ghosts[nt]   = nf
327    ghosts[nt+1] = nf+1
328
329    return points, elements, boundary, ghosts
330
331def rectangular_periodic_lr(m, n, len1=1.0, len2=1.0, origin = (0.0, 0.0)):
332
333
334    """Setup a rectangular grid of triangles
335    with m+1 by n+1 grid points
336    and side lengths len1, len2. If side lengths are omitted
337    the mesh defaults to the unit square.
338
339    len1: x direction (left to right)
340    len2: y direction (bottom to top)
341
342    Return to lists: points and elements suitable for creating a Mesh or
343    Domain object, e.g. Mesh(points, elements)
344    """
345
346    delta1 = float(len1)/m
347    delta2 = float(len2)/n
348
349    #Calculate number of points
350    Np = (m+1)*(n+1)
351
352    class VIndex:
353
354        def __init__(self, n,m):
355            self.n = n
356            self.m = m
357
358        def __call__(self, i,j):
359            return j+i*(self.n+1)
360
361    class EIndex:
362
363        def __init__(self, n,m):
364            self.n = n
365            self.m = m
366
367        def __call__(self, i,j):
368            return 2*(j+i*self.n)
369
370
371    I = VIndex(n,m)
372    E = EIndex(n,m)
373
374    points = zeros( (Np,2), Float)
375
376    for i in range(m+1):
377        for j in range(n+1):
378
379            points[I(i,j),:] = [i*delta1 + origin[0], j*delta2 + origin[1]]
380
381    #Construct 2 triangles per rectangular element and assign tags to boundary
382    #Calculate number of triangles
383    Nt = 2*m*n
384
385
386    elements = zeros( (Nt,3), Int)
387    boundary = {}
388    ghosts = {}
389    nt = -1
390    for i in range(m):
391        for j in range(n):
392
393            i1 = I(i,j+1)
394            i2 = I(i,j)
395            i3 = I(i+1,j+1)
396            i4 = I(i+1,j)
397
398            #Lower Element
399            nt = E(i,j)
400            if i == m-1:
401                ghosts[nt] = E(1,j)
402            if i == 0:
403                ghosts[nt] = E(m-2,j)
404
405            if i == m-1:
406                if processor == numproc-1:
407                    boundary[nt, 2] = 'right'
408                else:
409                    boundary[nt, 2] = 'ghost'
410            if j == 0:
411                boundary[nt, 1] = 'bottom'
412            elements[nt,:] = [i4,i3,i2]
413
414            #Upper Element
415            nt = E(i,j)+1
416            if i == m-1:
417                ghosts[nt] = E(1,j)+1
418            if i == 0:
419                ghosts[nt] = E(m-2,j)+1
420
421            if i == 0:
422                if processor == 0:
423                    boundary[nt, 2] = 'left'
424                else:
425                    boundary[nt, 2] = 'ghost'
426            if j == n-1:
427                boundary[nt, 1] = 'top'
428            elements[nt,:] = [i1,i2,i3]
429
430
431    return points, elements, boundary, ghosts
Note: See TracBrowser for help on using the repository browser.