source: trunk/anuga_work/shallow_water_balanced_steve/test_swb_balance.py @ 8335

Last change on this file since 8335 was 8175, checked in by steve, 14 years ago

Working on balanced scheme

File size: 13.4 KB
Line 
1#!/usr/bin/env python
2
3import unittest, os
4import os.path
5from math import pi, sqrt
6import tempfile
7
8from anuga.config import g, epsilon
9from anuga.config import netcdf_mode_r, netcdf_mode_w, netcdf_mode_a
10from anuga.utilities.numerical_tools import mean
11from anuga.geometry.polygon import is_inside_polygon
12from anuga.coordinate_transforms.geo_reference import Geo_reference
13from anuga.abstract_2d_finite_volumes.quantity import Quantity
14from anuga.geospatial_data.geospatial_data import Geospatial_data
15from anuga.abstract_2d_finite_volumes.mesh_factory import rectangular_cross
16
17from anuga.utilities.system_tools import get_pathname_from_package
18from swb_domain import *
19
20import numpy as num
21
22# Get gateway to C implementation of flux function for direct testing
23from shallow_water_ext import flux_function_central as flux_function
24
25
26
27
28class Test_swb_clean(unittest.TestCase):
29    def setUp(self):
30        pass
31
32    def tearDown(self):
33        pass
34
35
36    def test_balance_deep_and_shallow(self):
37        """Test that balanced limiters preserve conserved quantites.
38        This test is using old depth based balanced limiters
39        """
40
41        import copy
42
43        a = [0.0, 0.0]
44        b = [0.0, 2.0]
45        c = [2.0, 0.0]
46        d = [0.0, 4.0]
47        e = [2.0, 2.0]
48        f = [4.0, 0.0]
49
50        points = [a, b, c, d, e, f]
51        #             bac,     bce,     ecf,     dbe
52        elements = [[1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
53
54        domain = Domain(points, elements)
55        domain.check_integrity()
56
57        # Create a deliberate overshoot
58        domain.set_quantity('stage', [[3,0,3], [2,2,6], [5,3,8], [8,3,5]])
59        domain.set_quantity('elevation', 0)    # Flat bed
60        stage = domain.quantities['stage']
61
62        ref_centroid_values = copy.copy(stage.centroid_values[:])    # Copy
63
64        # Limit
65        domain.distribute_to_vertices_and_edges()
66
67        # Assert that quantities are conserved
68        for k in range(len(domain)):
69            assert num.allclose(ref_centroid_values[k],
70                                num.sum(stage.vertex_values[k,:])/3)
71
72        # Now try with a non-flat bed - closely hugging initial stage in places
73        domain.set_quantity('stage', [[3,0,3], [2,2,6], [5,3,8], [8,3,5]])
74        domain.set_quantity('elevation', [[0,0,0],
75                                          [1.8,1.9,5.9],
76                                          [4.6,0,0],
77                                          [0,2,4]])
78        stage = domain.quantities['stage']
79        #elevation = domain.quantities['elevation']
80        #height = domain.quantities['height']
81
82        ref_centroid_values = copy.copy(stage.centroid_values[:])    # Copy
83        ref_vertex_values = copy.copy(stage.vertex_values[:])        # Copy
84
85        # Limit
86        domain.distribute_to_vertices_and_edges()
87
88        # Assert that all vertex quantities have changed
89        for k in range(len(domain)):
90            assert not num.allclose(ref_vertex_values[k,:],
91                                    stage.vertex_values[k,:])
92        # and assert that quantities are still conserved
93        for k in range(len(domain)):
94            assert num.allclose(ref_centroid_values[k],
95                                num.sum(stage.vertex_values[k,:])/3)
96
97        # Check actual results
98
99        #print stage.vertex_values
100
101        assert num.allclose(stage.vertex_values,
102                            [[ 2.         , 2.         , 2.        ],
103                             [ 2.22222222 , 2.22222222 , 5.55555556],
104                             [ 5.33333333 , 5.33333333 , 5.33333333],
105                             [ 5.33333333 , 5.33333333 , 5.33333333]])
106
107
108    def test_balance_deep_and_shallow_tight_SL(self):
109        """Test that balanced limiters preserve conserved quantites.
110        This test is using Tight Slope Limiters
111        """
112
113        import copy
114
115        a = [0.0, 0.0]
116        b = [0.0, 2.0]
117        c = [2.0, 0.0]
118        d = [0.0, 4.0]
119        e = [2.0, 2.0]
120        f = [4.0, 0.0]
121
122        points = [a, b, c, d, e, f]
123        #             bac,     bce,     ecf,     dbe
124        elements = [[1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
125
126        domain = Domain(points, elements)
127        domain.check_integrity()
128
129        # Create a deliberate overshoot
130        domain.set_quantity('stage', [[3,0,3], [2,2,6], [5,3,8], [8,3,5]])
131        domain.set_quantity('elevation', 0)    # Flat bed
132        stage = domain.quantities['stage']
133
134        ref_centroid_values = copy.copy(stage.centroid_values[:])    # Copy
135
136        # Limit
137        domain.tight_slope_limiters = 1
138        domain.distribute_to_vertices_and_edges()
139
140        # Assert that quantities are conserved
141        for k in range(len(domain)):
142            assert num.allclose (ref_centroid_values[k],
143                                 num.sum(stage.vertex_values[k,:])/3)
144
145        # Now try with a non-flat bed - closely hugging initial stage in places
146        # This will create alphas in the range [0, 0.478260, 1]
147        domain.set_quantity('stage', [[3,0,3], [2,2,6], [5,3,8], [8,3,5]])
148        domain.set_quantity('elevation', [[0,0,0],
149                                          [1.8,1.9,5.9],
150                                          [4.6,0,0],
151                                          [0,2,4]])
152        stage = domain.quantities['stage']
153
154        ref_centroid_values = copy.copy(stage.centroid_values[:])    # Copy
155        ref_vertex_values = copy.copy(stage.vertex_values[:])        # Copy
156
157        # Limit
158        domain.tight_slope_limiters = 1
159        domain.distribute_to_vertices_and_edges()
160
161        # Assert that all vertex quantities have changed
162        for k in range(len(domain)):
163            assert not num.allclose(ref_vertex_values[k,:],
164                                    stage.vertex_values[k,:])
165        # and assert that quantities are still conserved
166        for k in range(len(domain)):
167            assert num.allclose(ref_centroid_values[k],
168                                num.sum(stage.vertex_values[k,:])/3)
169
170    def test_balance_deep_and_shallow_Froude(self):
171        """Test that balanced limiters preserve conserved quantites -
172        and also that excessive Froude numbers are dealt with.
173        This test is using tight slope limiters.
174        """
175
176        import copy
177
178        a = [0.0, 0.0]
179        b = [0.0, 2.0]
180        c = [2.0, 0.0]
181        d = [0.0, 4.0]
182        e = [2.0, 2.0]
183        f = [4.0, 0.0]
184
185        points = [a, b, c, d, e, f]
186        #             bac,     bce,     ecf,     dbe
187        elements = [[1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
188
189        domain = Domain(points, elements)
190        domain.check_integrity()
191        domain.tight_slope_limiters = True
192        domain.use_centroid_velocities = True
193
194        # Create non-flat bed - closely hugging initial stage in places
195        # This will create alphas in the range [0, 0.478260, 1]
196        domain.set_quantity('stage', [[3,0,3], [2,2,6], [5,3,8], [8,3,5]])
197        domain.set_quantity('elevation', [[0,0,0],
198                                          [1.8,1.999,5.999],
199                                          [4.6,0,0],
200                                          [0,2,4]])
201
202        # Create small momenta, that nonetheless will generate large speeds
203        # due to shallow depth at isolated vertices
204        domain.set_quantity('xmomentum', -0.0058)
205        domain.set_quantity('ymomentum', 0.0890)
206
207        stage = domain.quantities['stage']
208        elevation = domain.quantities['elevation']
209        xmomentum = domain.quantities['xmomentum']
210        ymomentum = domain.quantities['ymomentum']
211
212        # Setup triangle #1 to mimick real Froude explosion observed
213        # in the Onslow example 13 Nov 2007.
214        stage.vertex_values[1,:] = [1.6385, 1.6361, 1.2953]
215        elevation.vertex_values[1,:] = [1.6375, 1.6336, 0.4647]
216        xmomentum.vertex_values[1,:] = [-0.0058, -0.0050, -0.0066]
217        ymomentum.vertex_values[1,:] = [0.0890, 0.0890, 0.0890]
218
219        xmomentum.interpolate()
220        ymomentum.interpolate()
221        stage.interpolate()
222        elevation.interpolate()
223
224        # Verify interpolation
225        assert num.allclose(stage.centroid_values[1], 1.5233)
226        assert num.allclose(elevation.centroid_values[1], 1.2452667)
227        assert num.allclose(xmomentum.centroid_values[1], -0.0058)
228        assert num.allclose(ymomentum.centroid_values[1], 0.089)
229
230        # Derived quantities
231        depth = stage-elevation
232        u = xmomentum/depth
233        v = ymomentum/depth
234
235        denom = (depth*g)**0.5
236        Fx = u/denom
237        Fy = v/denom
238
239        # Verify against Onslow example (14 Nov 2007)
240        assert num.allclose(depth.centroid_values[1], 0.278033)
241        assert num.allclose(u.centroid_values[1], -0.0208608)
242        assert num.allclose(v.centroid_values[1], 0.3201055)
243
244        assert num.allclose(denom.centroid_values[1],
245                            num.sqrt(depth.centroid_values[1]*g))
246
247        assert num.allclose(u.centroid_values[1]/denom.centroid_values[1],
248                            -0.012637746977)
249        assert num.allclose(Fx.centroid_values[1],
250                            u.centroid_values[1]/denom.centroid_values[1])
251
252        # Check that Froude numbers are small at centroids.
253        assert num.allclose(Fx.centroid_values[1], -0.012637746977)
254        assert num.allclose(Fy.centroid_values[1], 0.193924048435)
255
256        # But Froude numbers are huge at some vertices and edges
257        assert num.allclose(Fx.vertex_values[1,:], [-5.85888475e+01,
258                                                    -1.27775313e+01,
259                                                    -2.78511420e-03])
260
261        assert num.allclose(Fx.edge_values[1,:], [-6.89150773e-03,
262                                                  -7.38672488e-03,
263                                                  -2.35626238e+01])
264
265        assert num.allclose(Fy.vertex_values[1,:], [8.99035764e+02,
266                                                    2.27440057e+02,
267                                                    3.75568430e-02])
268
269        assert num.allclose(Fy.edge_values[1,:], [1.05748998e-01,
270                                                  1.06035244e-01,
271                                                  3.88346947e+02])
272
273
274        # The task is now to arrange the limiters such that Froude numbers
275        # remain under control whil at the same time obeying the conservation
276        # laws.
277        ref_centroid_values = copy.copy(stage.centroid_values[:])    # Copy
278        ref_vertex_values = copy.copy(stage.vertex_values[:])        # Copy
279
280        # Limit (and invoke balance_deep_and_shallow)
281        domain.tight_slope_limiters = 1
282        domain.distribute_to_vertices_and_edges()
283
284        # Redo derived quantities
285        depth = stage - elevation
286        u = xmomentum/depth
287        v = ymomentum/depth
288
289        # Assert that all vertex velocities stay within one
290        # order of magnitude of centroid velocities.
291        assert num.alltrue(num.absolute(u.vertex_values[1,:]) <=
292                           num.absolute(u.centroid_values[1])*10)
293        assert num.alltrue(num.absolute(v.vertex_values[1,:]) <=
294                           num.absolute(v.centroid_values[1])*10)
295
296        denom = (depth*g)**0.5
297        Fx = u/denom
298        Fy = v/denom
299
300        # Assert that Froude numbers are less than max value (TBA)
301        # at vertices, edges and centroids.
302        from anuga.config import maximum_froude_number
303
304        assert num.alltrue(num.absolute(Fx.vertex_values[1,:]) <
305                           maximum_froude_number)
306        assert num.alltrue(num.absolute(Fy.vertex_values[1,:]) <
307                           maximum_froude_number)
308
309        # Assert that all vertex quantities have changed
310        for k in range(len(domain)):
311            assert not num.allclose(ref_vertex_values[k,:],
312                                    stage.vertex_values[k,:])
313
314        # Assert that quantities are still conserved
315        for k in range(len(domain)):
316            assert num.allclose(ref_centroid_values[k],
317                                num.sum(stage.vertex_values[k,:])/3)
318
319        return
320
321        qwidth = 12
322        for k in [1]:    # range(len(domain)):
323            print 'Triangle %d (C, V, E)' % k
324
325            print ('stage'.ljust(qwidth), stage.centroid_values[k],
326                   stage.vertex_values[k,:], stage.edge_values[k,:])
327            print ('elevation'.ljust(qwidth), elevation.centroid_values[k],
328                   elevation.vertex_values[k,:], elevation.edge_values[k,:])
329            print ('depth'.ljust(qwidth), depth.centroid_values[k],
330                   depth.vertex_values[k,:], depth.edge_values[k,:])
331            print ('xmomentum'.ljust(qwidth), xmomentum.centroid_values[k],
332                   xmomentum.vertex_values[k,:], xmomentum.edge_values[k,:])
333            print ('ymomentum'.ljust(qwidth), ymomentum.centroid_values[k],
334                   ymomentum.vertex_values[k,:], ymomentum.edge_values[k,:])
335            print ('u'.ljust(qwidth),u.centroid_values[k],
336                   u.vertex_values[k,:], u.edge_values[k,:])
337            print ('v'.ljust(qwidth), v.centroid_values[k],
338                   v.vertex_values[k,:], v.edge_values[k,:])
339            print ('Fx'.ljust(qwidth), Fx.centroid_values[k],
340                   Fx.vertex_values[k,:], Fx.edge_values[k,:])
341            print ('Fy'.ljust(qwidth), Fy.centroid_values[k],
342                   Fy.vertex_values[k,:], Fy.edge_values[k,:])
343
344
345#################################################################################
346
347if __name__ == "__main__":
348    suite = unittest.makeSuite(Test_swb_clean, 'test')
349    runner = unittest.TextTestRunner(verbosity=1)
350    runner.run(suite)
Note: See TracBrowser for help on using the repository browser.