source: inundation/parallel/parallel_meshes.py @ 3034

Last change on this file since 3034 was 2625, checked in by linda, 19 years ago

Added ghost boundary layers

File size: 10.4 KB
Line 
1import sys
2from os import sep
3sys.path.append('..'+sep+'pyvolution')
4
5"""parallel-meshes -
62D triangular domains for parallel finite-volume computations of
7the advection equation, with extra structures to define the
8sending and receiving communications define in dictionaries
9full_send_dict and ghost_recv_dict
10
11
12Ole Nielsen, Stephen Roberts, Duncan Gray, Christopher Zoppou
13Geoscience Australia, 2005
14
15Modified by Linda Stals, March 2006, to include ghost boundaries
16
17"""
18
19#from parallel_advection import *
20
21import pypar
22from Numeric import array
23
24def parallel_rectangle(m_g, n_g, len1_g=1.0, len2_g=1.0, origin_g = (0.0, 0.0)):
25
26
27    """Setup a rectangular grid of triangles
28    with m+1 by n+1 grid points
29    and side lengths len1, len2. If side lengths are omitted
30    the mesh defaults to the unit square, divided between all the
31    processors
32
33    len1: x direction (left to right)
34    len2: y direction (bottom to top)
35
36    """
37
38    from config import epsilon
39    from Numeric import zeros, Float, Int
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
59    #Calculate number of points
60    Np = (m+1)*(n+1)
61
62    class VIndex:
63
64        def __init__(self, n,m):
65            self.n = n
66            self.m = m
67
68        def __call__(self, i,j):
69            return j+i*(self.n+1)
70
71    class EIndex:
72
73        def __init__(self, n,m):
74            self.n = n
75            self.m = m
76
77        def __call__(self, i,j):
78            return 2*(j+i*self.n)
79
80
81    I = VIndex(n,m)
82    E = EIndex(n,m)
83
84    points = zeros( (Np,2), Float)
85
86    for i in range(m+1):
87        for j in range(n+1):
88
89            points[I(i,j),:] = [i*delta1 + origin[0], j*delta2 + origin[1]]
90
91    #Construct 2 triangles per rectangular element and assign tags to boundary
92    #Calculate number of triangles
93    Nt = 2*m*n
94
95
96    elements = zeros( (Nt,3), Int)
97    boundary = {}
98    Idgl = []
99    Idfl = []
100    Idgr = []
101    Idfr = []
102
103    full_send_dict = {}
104    ghost_recv_dict = {}
105    nt = -1
106    for i in range(m):
107        for j in range(n):
108
109            i1 = I(i,j+1)
110            i2 = I(i,j)
111            i3 = I(i+1,j+1)
112            i4 = I(i+1,j)
113
114            #Lower Element
115            nt = E(i,j)
116            if i == 0:
117                Idgl.append(nt)
118
119            if i == 1:
120                Idfl.append(nt)
121
122            if i == m-2:
123                Idfr.append(nt)
124
125            if i == m-1:
126                Idgr.append(nt)
127
128            if i == m-1:
129                if processor == numproc-1:
130                    boundary[nt, 2] = 'right'
131                else:
132                    boundary[nt, 2] = 'ghost'
133       
134            if j == 0:
135                boundary[nt, 1] = 'bottom'
136            elements[nt,:] = [i4,i3,i2]
137
138            #Upper Element
139            nt = E(i,j)+1
140            if i == 0:
141                Idgl.append(nt)
142
143            if i == 1:
144                Idfl.append(nt)
145
146            if i == m-2:
147                Idfr.append(nt)
148
149            if i == m-1:
150                Idgr.append(nt)
151
152            if i == 0:
153                if processor == 0:
154                    boundary[nt, 2] = 'left'
155                else:
156                    boundary[nt, 2] = 'ghost'
157            if j == n-1:
158                boundary[nt, 1] = 'top'
159            elements[nt,:] = [i1,i2,i3]
160
161    if numproc==1:
162        Idfl.extend(Idfr)
163        Idgr.extend(Idgl)
164        Idfl = array(Idfl,Int)
165        Idgr = array(Idgr,Int)
166        full_send_dict[processor]  = [Idfl, Idfl]
167        ghost_recv_dict[processor] = [Idgr, Idgr]
168    elif numproc == 2:
169        Idfl.extend(Idfr)
170        Idgr.extend(Idgl)
171        Idfl = array(Idfl,Int)
172        Idgr = array(Idgr,Int)
173        full_send_dict[(processor-1)%numproc]  = [Idfl, Idfl]
174        ghost_recv_dict[(processor-1)%numproc] = [Idgr, Idgr]
175    else:
176        Idfl = array(Idfl,Int)
177        Idgl = array(Idgl,Int)
178
179        Idfr = array(Idfr,Int)
180        Idgr = array(Idgr,Int)
181
182        full_send_dict[(processor-1)%numproc]  = [Idfl, Idfl]
183        ghost_recv_dict[(processor-1)%numproc] = [Idgl, Idgl]
184        full_send_dict[(processor+1)%numproc]  = [Idfr, Idfr]
185        ghost_recv_dict[(processor+1)%numproc] = [Idgr, Idgr]
186
187    return  points, elements, boundary, full_send_dict, ghost_recv_dict
188
189
190
191def rectangular_periodic(m, n, len1=1.0, len2=1.0, origin = (0.0, 0.0)):
192
193
194    """Setup a rectangular grid of triangles
195    with m+1 by n+1 grid points
196    and side lengths len1, len2. If side lengths are omitted
197    the mesh defaults to the unit square.
198
199    len1: x direction (left to right)
200    len2: y direction (bottom to top)
201
202    Return to lists: points and elements suitable for creating a Mesh or
203    FVMesh object, e.g. Mesh(points, elements)
204    """
205
206    from config import epsilon
207    from Numeric import zeros, Float, Int
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    from config import epsilon
347    from Numeric import zeros, Float, Int
348
349    delta1 = float(len1)/m
350    delta2 = float(len2)/n
351
352    #Calculate number of points
353    Np = (m+1)*(n+1)
354
355    class VIndex:
356
357        def __init__(self, n,m):
358            self.n = n
359            self.m = m
360
361        def __call__(self, i,j):
362            return j+i*(self.n+1)
363
364    class EIndex:
365
366        def __init__(self, n,m):
367            self.n = n
368            self.m = m
369
370        def __call__(self, i,j):
371            return 2*(j+i*self.n)
372
373
374    I = VIndex(n,m)
375    E = EIndex(n,m)
376
377    points = zeros( (Np,2), Float)
378
379    for i in range(m+1):
380        for j in range(n+1):
381
382            points[I(i,j),:] = [i*delta1 + origin[0], j*delta2 + origin[1]]
383
384    #Construct 2 triangles per rectangular element and assign tags to boundary
385    #Calculate number of triangles
386    Nt = 2*m*n
387
388
389    elements = zeros( (Nt,3), Int)
390    boundary = {}
391    ghosts = {}
392    nt = -1
393    for i in range(m):
394        for j in range(n):
395
396            i1 = I(i,j+1)
397            i2 = I(i,j)
398            i3 = I(i+1,j+1)
399            i4 = I(i+1,j)
400
401            #Lower Element
402            nt = E(i,j)
403            if i == m-1:
404                ghosts[nt] = E(1,j)
405            if i == 0:
406                ghosts[nt] = E(m-2,j)
407
408            if i == m-1:
409                if processor == numproc-1:
410                    boundary[nt, 2] = 'right'
411                else:
412                    boundary[nt, 2] = 'ghost'
413            if j == 0:
414                boundary[nt, 1] = 'bottom'
415            elements[nt,:] = [i4,i3,i2]
416
417            #Upper Element
418            nt = E(i,j)+1
419            if i == m-1:
420                ghosts[nt] = E(1,j)+1
421            if i == 0:
422                ghosts[nt] = E(m-2,j)+1
423
424            if i == 0:
425                if processor == 0:
426                    boundary[nt, 2] = 'left'
427                else:
428                    boundary[nt, 2] = 'ghost'
429            if j == n-1:
430                boundary[nt, 1] = 'top'
431            elements[nt,:] = [i1,i2,i3]
432
433
434    return points, elements, boundary, ghosts
Note: See TracBrowser for help on using the repository browser.