source: branches/numpy/anuga/abstract_2d_finite_volumes/mesh_factory.py @ 7198

Last change on this file since 7198 was 6904, checked in by rwilson, 16 years ago

Finished back-merge from Numeric trunk to numpy branch (and some code the other way).

File size: 22.5 KB
Line 
1"""Library of standard meshes and facilities for reading various
2mesh file formats
3"""
4
5import numpy as num
6
7
8def rectangular_old(m, n, len1=1.0, len2=1.0, origin = (0.0, 0.0)):
9
10    """Setup a rectangular grid of triangles
11    with m+1 by n+1 grid points
12    and side lengths len1, len2. If side lengths are omitted
13    the mesh defaults to the unit square.
14
15    len1: x direction (left to right)
16    len2: y direction (bottom to top)
17
18    Return to lists: points and elements suitable for creating a Mesh or
19    FVMesh object, e.g. Mesh(points, elements)
20    """
21
22    from anuga.config import epsilon
23
24    deltax = float(len1)/m
25    deltay = float(len2)/n
26
27    #Dictionary of vertex objects
28    vertices = {}
29    points = []
30
31    for i in range(m+1):
32        for j in range(n+1):
33            vertices[i,j] = len(points)
34            points.append([i*delta1 + origin[0], j*delta2 + origin[1]])
35
36
37    #Construct 2 triangles per rectangular element and assign tags to boundary
38    elements = []
39    boundary = {}
40    for i in range(m):
41        for j in range(n):
42            v1 = vertices[i,j+1]
43            v2 = vertices[i,j]
44            v3 = vertices[i+1,j+1]
45            v4 = vertices[i+1,j]
46
47            #Update boundary dictionary and create elements
48            if i == m-1:
49                boundary[(len(elements), 2)] = 'right'
50            if j == 0:
51                boundary[(len(elements), 1)] = 'bottom'
52            elements.append([v4,v3,v2]) #Lower element
53
54            if i == 0:
55                boundary[(len(elements), 2)] = 'left'
56            if j == n-1:
57                boundary[(len(elements), 1)] = 'top'
58            elements.append([v1,v2,v3]) #Upper element
59
60    return points, elements, boundary
61
62def rectangular(m, n, len1=1.0, len2=1.0, origin = (0.0, 0.0)):
63
64    """Setup a rectangular grid of triangles
65    with m+1 by n+1 grid points
66    and side lengths len1, len2. If side lengths are omitted
67    the mesh defaults to the unit square.
68
69    len1: x direction (left to right)
70    len2: y direction (bottom to top)
71
72    Return to lists: points and elements suitable for creating a Mesh or
73    FVMesh object, e.g. Mesh(points, elements)
74    """
75
76    from anuga.config import epsilon
77
78    delta1 = float(len1)/m
79    delta2 = float(len2)/n
80
81    #Calculate number of points
82    Np = (m+1)*(n+1)
83
84    class Index:
85
86        def __init__(self, n,m):
87            self.n = n
88            self.m = m
89
90        def __call__(self, i,j):
91            return j+i*(self.n+1)
92
93
94    index = Index(n,m)
95
96    points = num.zeros((Np, 2), num.float)
97
98    for i in range(m+1):
99        for j in range(n+1):
100
101            points[index(i,j),:] = [i*delta1 + origin[0], j*delta2 + origin[1]]
102
103    #Construct 2 triangles per rectangular element and assign tags to boundary
104    #Calculate number of triangles
105    Nt = 2*m*n
106
107
108    elements = num.zeros((Nt, 3), num.int)
109    boundary = {}
110    nt = -1
111    for i in range(m):
112        for j in range(n):
113            nt = nt + 1
114            i1 = index(i,j+1)
115            i2 = index(i,j)
116            i3 = index(i+1,j+1)
117            i4 = index(i+1,j)
118
119
120            #Update boundary dictionary and create elements
121            if i == m-1:
122                boundary[nt, 2] = 'right'
123            if j == 0:
124                boundary[nt, 1] = 'bottom'
125            elements[nt,:] = [i4,i3,i2] #Lower element
126            nt = nt + 1
127
128            if i == 0:
129                boundary[nt, 2] = 'left'
130            if j == n-1:
131                boundary[nt, 1] = 'top'
132            elements[nt,:] = [i1,i2,i3] #Upper element
133
134    return points, elements, boundary
135
136
137def rectangular_cross(m, n, len1=1.0, len2=1.0, origin = (0.0, 0.0)):
138
139    """Setup a rectangular grid of triangles
140    with m+1 by n+1 grid points
141    and side lengths len1, len2. If side lengths are omitted
142    the mesh defaults to the unit square.
143
144    len1: x direction (left to right)
145    len2: y direction (bottom to top)
146
147    Return to lists: points and elements suitable for creating a Mesh or
148    FVMesh object, e.g. Mesh(points, elements)
149    """
150
151    from anuga.config import epsilon
152
153    delta1 = float(len1)/m
154    delta2 = float(len2)/n
155
156    #Dictionary of vertex objects
157    vertices = {}
158    points = []
159
160    for i in range(m+1):
161        for j in range(n+1):
162            vertices[i,j] = len(points)
163            points.append([delta1*i + origin[0], delta2*+ origin[1]])
164
165    # Construct 4 triangles per element
166    elements = []
167    boundary = {}
168    for i in range(m):
169        for j in range(n):
170            v1 = vertices[i,j+1]
171            v2 = vertices[i,j]
172            v3 = vertices[i+1,j+1]
173            v4 = vertices[i+1,j]
174            x = (points[v1][0]+points[v2][0]+points[v3][0]+points[v4][0])*0.25
175            y = (points[v1][1]+points[v2][1]+points[v3][1]+points[v4][1])*0.25
176
177            # Create centre point
178            v5 = len(points)
179            points.append([x, y])
180
181            #Create left triangle
182            if i == 0:
183                boundary[(len(elements), 1)] = 'left'
184            elements.append([v2,v5,v1])
185
186            #Create bottom triangle
187            if j == 0:
188                boundary[(len(elements), 1)] = 'bottom'
189            elements.append([v4,v5,v2])
190
191            #Create right triangle
192            if i == m-1:
193                boundary[(len(elements), 1)] = 'right'
194            elements.append([v3,v5,v4])
195
196            #Create top triangle
197            if j == n-1:
198                boundary[(len(elements), 1)] = 'top'
199            elements.append([v1,v5,v3])
200
201
202    return points, elements, boundary
203
204
205def rectangular_periodic(m_g, n_g, len1_g=1.0, len2_g=1.0, origin_g = (0.0, 0.0)):
206
207
208    """Setup a rectangular grid of triangles
209    with m+1 by n+1 grid points
210    and side lengths len1, len2. If side lengths are omitted
211    the mesh defaults to the unit square, divided between all the
212    processors
213
214    len1: x direction (left to right)
215    len2: y direction (bottom to top)
216
217    """
218
219    processor = 0
220    numproc   = 1
221
222   
223    n = n_g
224    m_low  = -1
225    m_high = m_g +1
226
227    m = m_high - m_low
228
229    delta1 = float(len1_g)/m_g
230    delta2 = float(len2_g)/n_g
231
232    len1 = len1_g*float(m)/float(m_g)
233    len2 = len2_g
234    origin = ( origin_g[0]+float(m_low)/float(m_g)*len1_g, origin_g[1] )
235
236    #Calculate number of points
237    Np = (m+1)*(n+1)
238
239    class VIndex:
240
241        def __init__(self, n,m):
242            self.n = n
243            self.m = m
244
245        def __call__(self, i,j):
246            return j+i*(self.n+1)
247
248    class EIndex:
249
250        def __init__(self, n,m):
251            self.n = n
252            self.m = m
253
254        def __call__(self, i,j):
255            return 2*(j+i*self.n)
256
257
258    I = VIndex(n,m)
259    E = EIndex(n,m)
260
261    points = num.zeros( (Np,2), num.float)
262
263    for i in range(m+1):
264        for j in range(n+1):
265
266            points[I(i,j),:] = [i*delta1 + origin[0], j*delta2 + origin[1]]
267
268    #Construct 2 triangles per rectangular element and assign tags to boundary
269    #Calculate number of triangles
270    Nt = 2*m*n
271
272
273    elements = num.zeros( (Nt,3), num.int)
274    boundary = {}
275    Idgl = []
276    Idfl = []
277    Idgr = []
278    Idfr = []
279
280    full_send_dict = {}
281    ghost_recv_dict = {}
282    nt = -1
283    for i in range(m):
284        for j in range(n):
285
286            i1 = I(i,j+1)
287            i2 = I(i,j)
288            i3 = I(i+1,j+1)
289            i4 = I(i+1,j)
290
291            #Lower Element
292            nt = E(i,j)
293            if i == 0:
294                Idgl.append(nt)
295
296            if i == 1:
297                Idfl.append(nt)
298
299            if i == m-2:
300                Idfr.append(nt)
301
302            if i == m-1:
303                Idgr.append(nt)
304
305            if i == m-1:
306                if processor == numproc-1:
307                    boundary[nt, 2] = 'right'
308                else:
309                    boundary[nt, 2] = 'ghost'
310       
311            if j == 0:
312                boundary[nt, 1] = 'bottom'
313            elements[nt,:] = [i4,i3,i2]
314
315            #Upper Element
316            nt = E(i,j)+1
317            if i == 0:
318                Idgl.append(nt)
319
320            if i == 1:
321                Idfl.append(nt)
322
323            if i == m-2:
324                Idfr.append(nt)
325
326            if i == m-1:
327                Idgr.append(nt)
328
329            if i == 0:
330                if processor == 0:
331                    boundary[nt, 2] = 'left'
332                else:
333                    boundary[nt, 2] = 'ghost'
334            if j == n-1:
335                boundary[nt, 1] = 'top'
336            elements[nt,:] = [i1,i2,i3]
337
338    Idfl.extend(Idfr)
339    Idgr.extend(Idgl)
340
341    Idfl = num.array(Idfl, num.int)
342    Idgr = num.array(Idgr, num.int)
343   
344    full_send_dict[processor]  = [Idfl, Idfl]
345    ghost_recv_dict[processor] = [Idgr, Idgr]
346
347
348    return  points, elements, boundary, full_send_dict, ghost_recv_dict
349
350
351def oblique(m, n, lenx = 1.0, leny = 1.0, theta = 8.95, origin = (0.0, 0.0)):
352    """Setup a oblique grid of triangles
353    with m segments in the x-direction and n segments in the y-direction
354
355    """
356
357    import math
358
359    from anuga.config import epsilon
360
361
362    deltax = lenx/float(m)
363    deltay = leny/float(n)
364    a = 0.75*lenx*math.tan(theta/180.*math.pi)
365    x1 = lenx
366    y1 = 0
367    x2 = lenx
368    y2 = leny
369    x3 = 0.25*lenx
370    y3 = leny
371    x4 = x3
372    y4 = 0
373    a2 = a/(x1-x4)
374    a1 = -a2*x4
375    a4 = ((a1 + a2*x3)/y3-(a1 + a2*x2)/y2)/(x2-x3)
376    a3 = 1. - (a1 + a2*x3)/y3 - a4*x3
377
378    # Dictionary of vertex objects
379    vertices = {}
380    points = []
381
382    for i in range(m+1):
383        x = deltax*i
384        for j in range(n+1):
385            y = deltay*j
386            if x > 0.25*lenx:
387                y = a1 + a2*x + a3*y + a4*x*y
388
389            vertices[i,j] = len(points)
390            points.append([x + origin[0], y + origin[1]])
391
392    # Construct 2 triangles per element
393    elements = []
394    boundary = {}
395    for i in range(m):
396        for j in range(n):
397            v1 = vertices[i,j+1]
398            v2 = vertices[i,j]
399            v3 = vertices[i+1,j+1]
400            v4 = vertices[i+1,j]
401
402            #Update boundary dictionary and create elements
403            if i == m-1:
404                boundary[(len(elements), 2)] = 'right'
405            if j == 0:
406                boundary[(len(elements), 1)] = 'bottom'
407            elements.append([v4,v3,v2]) #Lower
408
409            if i == 0:
410                boundary[(len(elements), 2)] = 'left'
411            if j == n-1:
412                boundary[(len(elements), 1)] = 'top'
413
414            elements.append([v1,v2,v3]) #Upper
415
416    return points, elements, boundary
417
418
419def circular(m, n, radius=1.0, center = (0.0, 0.0)):
420    """Setup a circular grid of triangles with m concentric circles and
421    with n radial segments. If radius is are omitted the mesh defaults to
422    the unit circle radius.
423
424    radius: radius of circle
425
426    #FIXME: The triangles become degenerate for large values of m or n.
427    """
428
429
430
431    from math import pi, cos, sin
432
433    radius = float(radius) #Ensure floating point format
434
435    #Dictionary of vertex objects and list of points
436    vertices = {}
437    points = [[0.0, 0.0]] #Center point
438    vertices[0, 0] = 0
439
440    for i in range(n):
441        theta = 2*i*pi/n
442        x = cos(theta)
443        y = sin(theta)
444        for j in range(1,m+1):
445            delta = j*radius/m
446            vertices[i,j] = len(points)
447            points.append([delta*x, delta*y])
448
449    #Construct 2 triangles per element
450    elements = []
451    for i in range(n):
452        for j in range(1,m):
453
454            i1 = (i + 1) % n  #Wrap around
455
456            v1 = vertices[i,j+1]
457            v2 = vertices[i,j]
458            v3 = vertices[i1,j+1]
459            v4 = vertices[i1,j]
460
461            elements.append([v4,v2,v3]) #Lower
462            elements.append([v1,v3,v2]) #Upper
463
464
465    #Do the center
466    v1 = vertices[0,0]
467    for i in range(n):
468        i1 = (i + 1) % n  #Wrap around
469        v2 = vertices[i,1]
470        v3 = vertices[i1,1]
471
472        elements.append([v1,v2,v3]) #center
473
474    return points, elements
475
476
477def from_polyfile(name):
478    """Read mesh from .poly file, an obj like file format
479    listing first vertex coordinates and then connectivity
480    """
481
482    from anuga.utilities.numerical_tools import anglediff
483    from math import pi
484    import os.path
485    root, ext = os.path.splitext(name)
486
487    if ext == 'poly':
488        filename = name
489    else:
490        filename = name + '.poly'
491
492
493    fid = open(filename)
494
495    points = []    #x, y
496    values = []    #z
497    ##vertex_values = []    #Repeated z
498    triangles = [] #v0, v1, v2
499
500    lines = fid.readlines()
501
502    keyword = lines[0].strip()
503    msg = 'First line in .poly file must contain the keyword: POINTS'
504    assert keyword == 'POINTS', msg
505
506    offending = 0
507    i = 1
508    while keyword == 'POINTS':
509        line = lines[i].strip()
510        i += 1
511
512        if line == 'POLYS':
513            keyword = line
514            break
515
516        fields = line.split(':')
517        assert int(fields[0]) == i-1, 'Point indices not consecutive'
518
519        #Split the three floats
520        xyz = fields[1].split()
521
522        x = float(xyz[0])
523        y = float(xyz[1])
524        z = float(xyz[2])
525
526        points.append([x, y])
527        values.append(z)
528
529
530    k = i
531    while keyword == 'POLYS':
532        line = lines[i].strip()
533        i += 1
534
535        if line == 'END':
536            keyword = line
537            break
538
539
540        fields = line.split(':')
541        assert int(fields[0]) == i-k, 'Poly indices not consecutive'
542
543        #Split the three indices
544        vvv = fields[1].split()
545
546        i0 = int(vvv[0])-1
547        i1 = int(vvv[1])-1
548        i2 = int(vvv[2])-1
549
550        #Check for and exclude degenerate areas
551        x0 = points[i0][0]
552        y0 = points[i0][1]
553        x1 = points[i1][0]
554        y1 = points[i1][1]
555        x2 = points[i2][0]
556        y2 = points[i2][1]
557
558        area = abs((x1*y0-x0*y1)+(x2*y1-x1*y2)+(x0*y2-x2*y0))/2
559        if area > 0:
560
561            #Ensure that points are arranged in counter clock-wise order
562            v0 = [x1-x0, y1-y0]
563            v1 = [x2-x1, y2-y1]
564            v2 = [x0-x2, y0-y2]
565
566            a0 = anglediff(v1, v0)
567            a1 = anglediff(v2, v1)
568            a2 = anglediff(v0, v2)
569
570
571            if a0 < pi and a1 < pi and a2 < pi:
572                #all is well
573                j0 = i0
574                j1 = i1
575                j2 = i2
576            else:
577                #Swap two vertices
578                j0 = i1
579                j1 = i0
580                j2 = i2
581
582            triangles.append([j0, j1, j2])
583            ##vertex_values.append([values[j0], values[j1], values[j2]])
584        else:
585            offending +=1
586
587    print 'Removed %d offending triangles out of %d' %(offending, len(lines))
588    return points, triangles, values
589
590
591
592def strang_mesh(filename):
593    """Read Strang generated mesh.
594    """
595
596    from math import pi
597    from anuga.utilities.numerical_tools import anglediff
598
599
600    fid = open(filename)
601    points = []    # List of x, y coordinates
602    triangles = [] # List of vertex ids as listed in the file
603
604    for line in fid.readlines():
605        fields = line.split()
606        if len(fields) == 2:
607            # we are reading vertex coordinates
608            points.append([float(fields[0]), float(fields[1])])
609        elif len(fields) == 3:
610            # we are reading triangle point id's (format ae+b)
611            triangles.append([int(float(fields[0]))-1,
612                              int(float(fields[1]))-1,
613                              int(float(fields[2]))-1])
614        else:
615            raise 'wrong format in ' + filename
616
617    elements = [] #Final list of elements
618
619    for t in triangles:
620        #Get vertex coordinates
621        v0 = t[0]
622        v1 = t[1]
623        v2 = t[2]
624
625        x0 = points[v0][0]
626        y0 = points[v0][1]
627        x1 = points[v1][0]
628        y1 = points[v1][1]
629        x2 = points[v2][0]
630        y2 = points[v2][1]
631
632        #Check that points are arranged in counter clock-wise order
633        vec0 = [x1-x0, y1-y0]
634        vec1 = [x2-x1, y2-y1]
635        vec2 = [x0-x2, y0-y2]
636
637        a0 = anglediff(vec1, vec0)
638        a1 = anglediff(vec2, vec1)
639        a2 = anglediff(vec0, vec2)
640
641        if a0 < pi and a1 < pi and a2 < pi:
642            elements.append([v0, v1, v2])
643        else:
644            elements.append([v0, v2, v1])
645
646    return points, elements
647
648# #Map from edge number to indices of associated vertices
649# edge_map = ((1,2), (0,2), (0,1))
650
651def contracting_channel(m, n, W_upstream = 1., W_downstream = 0.75,
652                            L_1 = 5.0, L_2 = 2.0, L_3 = 10, origin = (0.0, 0.0)):
653    """Setup a contracting channel grid of triangles
654    with m segments in the x-direction and n segments in the y-direction
655
656    """
657
658    import math
659
660    from anuga.config import epsilon
661
662
663    lenx = L_1 + L_2 + L_3
664    leny = W_upstream
665    deltax = lenx/float(m)
666    deltay = leny/float(n)
667
668    x1 = 0
669    y1 = 0
670    x2 = L_1
671    y2 = 0
672    x3 = L_1 + L_2
673    y3 = (W_upstream - W_downstream)/2
674    x4 = L_1 + L_2 + L_3
675    y4 = y3
676    x5 = x4
677    y5 = y4 + W_downstream
678    x6 = L_1 + L_2
679    y6 = y5
680    x7 = L_1
681    y7 = W_upstream
682    x8 = 0
683    y8 = W_upstream
684    a1 = 0
685    a2 = (W_upstream - W_downstream)/(2*L_2)
686    a3 = 1
687    a4 = (W_downstream - W_upstream)/(L_2*W_upstream)
688
689    # Dictionary of vertex objects
690    vertices = {}
691    points = []
692
693    for i in range(m+1):
694        x = deltax*i
695        for j in range(n+1):
696            y = deltay*j
697            if x > L_1 and x <= (L_1 + L_2):
698                y = a1 + a2*(x - L_1) + a3*y + a4*(x - L_1)*y
699            elif x > L_1 + L_2:
700                y = (W_upstream - W_downstream)/2 + deltay*j*W_downstream/W_upstream
701
702            vertices[i,j] = len(points)
703            points.append([x + origin[0], y + origin[1]])
704
705    # Construct 2 triangles per element
706    elements = []
707    boundary = {}
708    for i in range(m):
709        for j in range(n):
710            v1 = vertices[i,j+1]
711            v2 = vertices[i,j]
712            v3 = vertices[i+1,j+1]
713            v4 = vertices[i+1,j]
714
715            #Update boundary dictionary and create elements
716            if i == m-1:
717                boundary[(len(elements), 2)] = 'right'
718            if j == 0:
719                boundary[(len(elements), 1)] = 'bottom'
720            elements.append([v4,v3,v2]) #Lower
721
722            if i == 0:
723                boundary[(len(elements), 2)] = 'left'
724            if j == n-1:
725                boundary[(len(elements), 1)] = 'top'
726
727            elements.append([v1,v2,v3]) #Upper
728
729    return points, elements, boundary
730
731
732def contracting_channel_cross(m, n, W_upstream = 1., W_downstream = 0.75,
733                              L_1 = 5.0, L_2 = 2.0, L_3 = 10, origin = (0.0, 0.0)):
734    """Setup a contracting channel grid of triangles
735    with m segments in the x-direction and n segments in the y-direction
736
737    """
738
739    import math
740
741    from anuga.config import epsilon
742
743
744    lenx = L_1 + L_2 + L_3
745    leny = W_upstream
746    deltax = lenx/float(m)
747    deltay = leny/float(n)
748
749    x1 = 0
750    y1 = 0
751    x2 = L_1
752    y2 = 0
753    x3 = L_1 + L_2
754    y3 = (W_upstream - W_downstream)/2
755    x4 = L_1 + L_2 + L_3
756    y4 = y3
757    x5 = x4
758    y5 = y4 + W_downstream
759    x6 = L_1 + L_2
760    y6 = y5
761    x7 = L_1
762    y7 = W_upstream
763    x8 = 0
764    y8 = W_upstream
765    a1 = 0
766    a2 = (W_upstream - W_downstream)/(2*L_2)
767    a3 = 1
768    a4 = (W_downstream - W_upstream)/(L_2*W_upstream)
769
770    # Dictionary of vertex objects
771    vertices = {}
772    points = []
773
774    for i in range(m+1):
775        x = deltax*i
776        for j in range(n+1):
777            y = deltay*j
778            if x > L_1 and x <= (L_1 + L_2):
779                y = a1 + a2*(x - L_1) + a3*y + a4*(x - L_1)*y
780            elif x > L_1 + L_2:
781                y = (W_upstream - W_downstream)/2 + deltay*j*W_downstream/W_upstream
782
783            vertices[i,j] = len(points)
784            points.append([x + origin[0], y + origin[1]])
785
786    # Construct 4 triangles per element
787    elements = []
788    boundary = {}
789    for i in range(m):
790        for j in range(n):
791            v1 = vertices[i,j+1]
792            v2 = vertices[i,j]
793            v3 = vertices[i+1,j+1]
794            v4 = vertices[i+1,j]
795            x = (points[v1][0]+points[v2][0]+points[v3][0]+points[v4][0])*0.25
796            y = (points[v1][1]+points[v2][1]+points[v3][1]+points[v4][1])*0.25
797            v5 = len(points)
798            points.append([x, y])
799
800            #Create left triangle
801            if i == 0:
802                boundary[(len(elements), 1)] = 'left'
803            elements.append([v2,v5,v1])
804
805            #Create bottom triangle
806            if j == 0:
807                boundary[(len(elements), 1)] = 'bottom'
808            elements.append([v4,v5,v2])
809
810            #Create right triangle
811            if i == m-1:
812                boundary[(len(elements), 1)] = 'right'
813            elements.append([v3,v5,v4])
814
815            #Create top triangle
816            if j == n-1:
817                boundary[(len(elements), 1)] = 'top'
818            elements.append([v1,v5,v3])
819
820
821    return points, elements, boundary
822
823
824
825
826def oblique_cross(m, n, lenx = 1.0, leny = 1.0, theta = 8.95, origin = (0.0, 0.0)):
827    """Setup a oblique grid of triangles
828    with m segments in the x-direction and n segments in the y-direction
829
830    """
831
832    import math
833
834    from anuga.config import epsilon
835
836
837    deltax = lenx/float(m)
838    deltay = leny/float(n)
839    a = 0.75*lenx*math.tan(theta/180.*math.pi)
840    x1 = lenx
841    y1 = 0
842    x2 = lenx
843    y2 = leny
844    x3 = 0.25*lenx
845    y3 = leny
846    x4 = x3
847    y4 = 0
848    a2 = a/(x1-x4)
849    a1 = -a2*x4
850    a4 = ((a1 + a2*x3)/y3-(a1 + a2*x2)/y2)/(x2-x3)
851    a3 = 1. - (a1 + a2*x3)/y3 - a4*x3
852
853    # Dictionary of vertex objects
854    vertices = {}
855    points = []
856
857    for i in range(m+1):
858        x = deltax*i
859        for j in range(n+1):
860            y = deltay*j
861            if x > 0.25*lenx:
862                y = a1 + a2*x + a3*y + a4*x*y
863
864            vertices[i,j] = len(points)
865            points.append([x + origin[0], y + origin[1]])
866
867    # Construct 4 triangles per element
868    elements = []
869    boundary = {}
870    for i in range(m):
871        for j in range(n):
872            v1 = vertices[i,j+1]
873            v2 = vertices[i,j]
874            v3 = vertices[i+1,j+1]
875            v4 = vertices[i+1,j]
876            x = (points[v1][0]+points[v2][0]+points[v3][0]+points[v4][0])*0.25
877            y = (points[v1][1]+points[v2][1]+points[v3][1]+points[v4][1])*0.25
878            v5 = len(points)
879            points.append([x, y])
880
881            #Update boundary dictionary and create elements
882                        #Create left triangle
883            if i == 0:
884                boundary[(len(elements), 1)] = 'left'
885            elements.append([v2,v5,v1])
886
887            #Create bottom triangle
888            if j == 0:
889                boundary[(len(elements), 1)] = 'bottom'
890            elements.append([v4,v5,v2])
891
892            #Create right triangle
893            if i == m-1:
894                boundary[(len(elements), 1)] = 'right'
895            elements.append([v3,v5,v4])
896
897            #Create top triangle
898            if j == n-1:
899                boundary[(len(elements), 1)] = 'top'
900            elements.append([v1,v5,v3])
901
902
903    return points, elements, boundary
Note: See TracBrowser for help on using the repository browser.