source: inundation/ga/storm_surge/pyvolution/test_domain.py @ 1506

Last change on this file since 1506 was 1158, checked in by duncan, 20 years ago

throw exception if edges are duplicated.

File size: 13.2 KB
Line 
1#!/usr/bin/env python
2
3import unittest
4from math import sqrt
5
6from domain import *
7from config import epsilon
8from Numeric import allclose, array, ones, Float
9
10
11def add_to_verts(tag, elements, domain):
12    if tag == "mound":
13        domain.test = "Mound"
14
15
16def set_bottom_friction(tag, elements, domain):
17    if tag == "bottom":
18        #print 'bottom - indexes',elements
19        domain.set_quantity('friction', 0.09, indexes = elements)
20
21def set_top_friction(tag, elements, domain):
22    if tag == "top":
23        #print 'top - indexes',elements
24        domain.set_quantity('friction', 1., indexes = elements)
25
26
27def set_all_friction(tag, elements, domain):
28    if tag == "all":
29        new_values = domain.get_quantity('friction', indexes = elements) + 10.0
30
31        domain.set_quantity('friction', new_values, indexes = elements)
32
33
34class Test_Domain(unittest.TestCase):
35    def setUp(self):
36        pass
37
38
39    def tearDown(self):
40        pass
41
42
43    def test_simple(self):
44        a = [0.0, 0.0]
45        b = [0.0, 2.0]
46        c = [2.0,0.0]
47        d = [0.0, 4.0]
48        e = [2.0, 2.0]
49        f = [4.0,0.0]
50
51        points = [a, b, c, d, e, f]
52        #bac, bce, ecf, dbe, daf, dae
53        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
54
55        conserved_quantities = ['stage', 'xmomentum', 'ymomentum']
56        other_quantities = ['elevation', 'friction']
57
58        domain = Domain(points, vertices, None,
59                        conserved_quantities, other_quantities)
60        domain.check_integrity()
61
62        for name in conserved_quantities + other_quantities:
63            assert domain.quantities.has_key(name)
64
65
66        assert domain.get_conserved_quantities(0, edge=1) == 0.
67
68
69    def test_conserved_quantities(self):
70
71        a = [0.0, 0.0]
72        b = [0.0, 2.0]
73        c = [2.0,0.0]
74        d = [0.0, 4.0]
75        e = [2.0, 2.0]
76        f = [4.0,0.0]
77
78        points = [a, b, c, d, e, f]
79        #bac, bce, ecf, dbe, daf, dae
80        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
81
82        domain = Domain(points, vertices, boundary=None,
83                        conserved_quantities =\
84                        ['stage', 'xmomentum', 'ymomentum'])
85
86
87        domain.set_quantity('stage', [[1,2,3], [5,5,5],
88                                      [0,0,9], [-6, 3, 3]])
89
90        domain.set_quantity('xmomentum', [[1,2,3], [5,5,5],
91                                          [0,0,9], [-6, 3, 3]])
92
93        domain.check_integrity()
94
95        #Centroids
96        q = domain.get_conserved_quantities(0)
97        assert allclose(q, [2., 2., 0.])
98
99        q = domain.get_conserved_quantities(1)
100        assert allclose(q, [5., 5., 0.])
101
102        q = domain.get_conserved_quantities(2)
103        assert allclose(q, [3., 3., 0.])
104
105        q = domain.get_conserved_quantities(3)
106        assert allclose(q, [0., 0., 0.])
107
108
109        #Edges
110        q = domain.get_conserved_quantities(0, edge=0)
111        assert allclose(q, [2.5, 2.5, 0.])
112        q = domain.get_conserved_quantities(0, edge=1)
113        assert allclose(q, [2., 2., 0.])
114        q = domain.get_conserved_quantities(0, edge=2)
115        assert allclose(q, [1.5, 1.5, 0.])
116
117        for i in range(3):
118            q = domain.get_conserved_quantities(1, edge=i)
119            assert allclose(q, [5, 5, 0.])
120
121
122        q = domain.get_conserved_quantities(2, edge=0)
123        assert allclose(q, [4.5, 4.5, 0.])
124        q = domain.get_conserved_quantities(2, edge=1)
125        assert allclose(q, [4.5, 4.5, 0.])
126        q = domain.get_conserved_quantities(2, edge=2)
127        assert allclose(q, [0., 0., 0.])
128
129
130        q = domain.get_conserved_quantities(3, edge=0)
131        assert allclose(q, [3., 3., 0.])
132        q = domain.get_conserved_quantities(3, edge=1)
133        assert allclose(q, [-1.5, -1.5, 0.])
134        q = domain.get_conserved_quantities(3, edge=2)
135        assert allclose(q, [-1.5, -1.5, 0.])
136
137
138    def test_boundary_indices(self):
139
140        from config import default_boundary_tag
141
142
143        a = [0.0, 0.5]
144        b = [0.0, 0.0]
145        c = [0.5, 0.5]
146
147        points = [a, b, c]
148        vertices = [ [0,1,2] ]
149        domain = Domain(points, vertices)
150
151        domain.set_boundary( {default_boundary_tag: Dirichlet_boundary([5,2,1])} )
152
153
154        domain.check_integrity()
155
156        assert allclose(domain.neighbours, [[-1,-2,-3]])
157
158
159
160    def test_boundary_conditions(self):
161
162        a = [0.0, 0.0]
163        b = [0.0, 2.0]
164        c = [2.0,0.0]
165        d = [0.0, 4.0]
166        e = [2.0, 2.0]
167        f = [4.0,0.0]
168
169        points = [a, b, c, d, e, f]
170        #bac, bce, ecf, dbe
171        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
172        boundary = { (0, 0): 'First',
173                     (0, 2): 'First',
174                     (2, 0): 'Second',
175                     (2, 1): 'Second',
176                     (3, 1): 'Second',
177                     (3, 2): 'Second'}
178
179
180        domain = Domain(points, vertices, boundary,
181                        conserved_quantities =\
182                        ['stage', 'xmomentum', 'ymomentum'])
183        domain.check_integrity()
184
185
186
187        domain.set_quantity('stage', [[1,2,3], [5,5,5],
188                                      [0,0,9], [-6, 3, 3]])
189
190
191        domain.set_boundary( {'First': Dirichlet_boundary([5,2,1]),
192                              'Second': Transmissive_boundary(domain)} )
193
194        domain.update_boundary()
195
196        assert domain.quantities['stage'].boundary_values[0] == 5. #Dirichlet
197        assert domain.quantities['stage'].boundary_values[1] == 5. #Dirichlet
198        assert domain.quantities['stage'].boundary_values[2] ==\
199               domain.get_conserved_quantities(2, edge=0)[0] #Transmissive (4.5)
200        assert domain.quantities['stage'].boundary_values[3] ==\
201               domain.get_conserved_quantities(2, edge=1)[0] #Transmissive (4.5)
202        assert domain.quantities['stage'].boundary_values[4] ==\
203               domain.get_conserved_quantities(3, edge=1)[0] #Transmissive (-1.5)
204        assert domain.quantities['stage'].boundary_values[5] ==\
205               domain.get_conserved_quantities(3, edge=2)[0] #Transmissive (-1.5)
206
207        #Check enumeration
208        for k, ((vol_id, edge_id), _) in enumerate(domain.boundary_objects):
209            assert domain.neighbours[vol_id, edge_id] == -k-1
210
211
212
213
214    def test_distribute_first_order(self):
215        """Domain implements a default first order gradient limiter
216        """
217
218        a = [0.0, 0.0]
219        b = [0.0, 2.0]
220        c = [2.0,0.0]
221        d = [0.0, 4.0]
222        e = [2.0, 2.0]
223        f = [4.0,0.0]
224
225        points = [a, b, c, d, e, f]
226        #bac, bce, ecf, dbe
227        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
228        boundary = { (0, 0): 'Third',
229                     (0, 2): 'First',
230                     (2, 0): 'Second',
231                     (2, 1): 'Second',
232                     (3, 1): 'Second',
233                     (3, 2): 'Third'}
234
235
236        domain = Domain(points, vertices, boundary,
237                        conserved_quantities =\
238                        ['stage', 'xmomentum', 'ymomentum'])
239        domain.check_integrity()
240
241
242        domain.set_quantity('stage', [[1,2,3], [5,5,5],
243                                      [0,0,9], [-6, 3, 3]])
244
245        assert allclose( domain.quantities['stage'].centroid_values,
246                         [2,5,3,0] )
247
248        domain.set_quantity('xmomentum', [[1,1,1], [2,2,2],
249                                          [3,3,3], [4, 4, 4]])
250
251        domain.set_quantity('ymomentum', [[10,10,10], [20,20,20],
252                                          [30,30,30], [40, 40, 40]])
253
254
255        domain.distribute_to_vertices_and_edges()
256
257        #First order extrapolation
258        assert allclose( domain.quantities['stage'].vertex_values,
259                         [[ 2.,  2.,  2.],
260                          [ 5.,  5.,  5.],
261                          [ 3.,  3.,  3.],
262                          [ 0.,  0.,  0.]])
263
264
265
266
267    def test_update_conserved_quantities(self):
268        a = [0.0, 0.0]
269        b = [0.0, 2.0]
270        c = [2.0,0.0]
271        d = [0.0, 4.0]
272        e = [2.0, 2.0]
273        f = [4.0,0.0]
274
275        points = [a, b, c, d, e, f]
276        #bac, bce, ecf, dbe
277        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
278        boundary = { (0, 0): 'Third',
279                     (0, 2): 'First',
280                     (2, 0): 'Second',
281                     (2, 1): 'Second',
282                     (3, 1): 'Second',
283                     (3, 2): 'Third'}
284
285
286        domain = Domain(points, vertices, boundary,
287                        conserved_quantities =\
288                        ['stage', 'xmomentum', 'ymomentum'])
289        domain.check_integrity()
290
291
292        domain.set_quantity('stage', [1,2,3,4], 'centroids')
293        domain.set_quantity('xmomentum', [1,2,3,4], 'centroids')
294        domain.set_quantity('ymomentum', [1,2,3,4], 'centroids')
295
296
297        #Assign some values to update vectors
298        #Set explicit_update
299
300        for name in domain.conserved_quantities:
301            domain.quantities[name].explicit_update = array([4.,3.,2.,1.])
302            domain.quantities[name].semi_implicit_update = array([1.,1.,1.,1.])
303
304
305        #Update with given timestep (assuming no other forcing terms)
306        domain.timestep = 0.1
307        domain.update_conserved_quantities()
308
309        sem = array([1.,1.,1.,1.])/array([1, 2, 3, 4])
310        denom = ones(4, Float)-domain.timestep*sem
311
312        x = array([1, 2, 3, 4]) + array( [.4,.3,.2,.1] )
313        x /= denom
314
315        for name in domain.conserved_quantities:
316            assert allclose(domain.quantities[name].centroid_values, x)
317
318
319    def test_set_region(self):
320        """Set quantities for sub region
321        """
322
323        a = [0.0, 0.0]
324        b = [0.0, 2.0]
325        c = [2.0,0.0]
326        d = [0.0, 4.0]
327        e = [2.0, 2.0]
328        f = [4.0,0.0]
329
330        points = [a, b, c, d, e, f]
331        #bac, bce, ecf, dbe
332        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
333        boundary = { (0, 0): 'Third',
334                     (0, 2): 'First',
335                     (2, 0): 'Second',
336                     (2, 1): 'Second',
337                     (3, 1): 'Second',
338                     (3, 2): 'Third'}
339
340        domain = Domain(points, vertices, boundary,
341                        conserved_quantities =\
342                        ['stage', 'xmomentum', 'ymomentum'])
343        domain.check_integrity()
344
345        domain.set_quantity('stage', [[1,2,3], [5,5,5],
346                                      [0,0,9], [-6, 3, 3]])
347
348        assert allclose( domain.quantities['stage'].centroid_values,
349                         [2,5,3,0] )
350
351        domain.set_quantity('xmomentum', [[1,1,1], [2,2,2],
352                                          [3,3,3], [4, 4, 4]])
353
354        domain.set_quantity('ymomentum', [[10,10,10], [20,20,20],
355                                          [30,30,30], [40, 40, 40]])
356
357
358        domain.distribute_to_vertices_and_edges()
359
360        #First order extrapolation
361        assert allclose( domain.quantities['stage'].vertex_values,
362                         [[ 2.,  2.,  2.],
363                          [ 5.,  5.,  5.],
364                          [ 3.,  3.,  3.],
365                          [ 0.,  0.,  0.]])
366
367        domain.build_tagged_elements_dictionary({'mound':[0,1]})
368        domain.set_region([add_to_verts])
369
370        self.failUnless(domain.test == "Mound",
371                        'set region failed')
372
373
374
375    def test_region_tags(self):
376        """
377        get values based on triangle lists.
378        """
379        from mesh_factory import rectangular
380        from shallow_water import Domain
381        from Numeric import zeros, Float
382
383        #Create basic mesh
384        points, vertices, boundary = rectangular(1, 3)
385
386        #Create shallow water domain
387        domain = Domain(points, vertices, boundary)
388        domain.build_tagged_elements_dictionary({'bottom':[0,1],
389                                                 'top':[4,5],
390                                                 'all':[0,1,2,3,4,5]})
391
392
393        #Set friction
394        manning = 0.07
395        domain.set_quantity('friction', manning)
396
397        domain.set_region([set_bottom_friction, set_top_friction])
398        #print domain.quantities['friction'].get_values()
399        assert allclose(domain.quantities['friction'].get_values(),\
400                        [[ 0.09,  0.09,  0.09],
401                         [ 0.09,  0.09,  0.09],
402                         [ 0.07,  0.07,  0.07],
403                         [ 0.07,  0.07,  0.07],
404                         [ 1.0,  1.0,  1.0],
405                         [ 1.0,  1.0,  1.0]])
406
407        domain.set_region([set_all_friction])
408        #print domain.quantities['friction'].get_values()
409        assert allclose(domain.quantities['friction'].get_values(),
410                        [[ 10.09, 10.09, 10.09],
411                         [ 10.09, 10.09, 10.09],
412                         [ 10.07, 10.07, 10.07],
413                         [ 10.07, 10.07, 10.07],
414                         [ 11.0,  11.0,  11.0],
415                         [ 11.0,  11.0,  11.0]])
416
417
418#-------------------------------------------------------------
419if __name__ == "__main__":
420    suite = unittest.makeSuite(Test_Domain,'test')
421    runner = unittest.TextTestRunner()
422    runner.run(suite)
Note: See TracBrowser for help on using the repository browser.