source: anuga_core/source/anuga/shallow_water/test_shallow_water_domain.py @ 5736

Last change on this file since 5736 was 5736, checked in by ole, 15 years ago

Implemented run-time version of get_energy_through_cross_section and tested it.

File size: 216.9 KB
Line 
1#!/usr/bin/env python
2
3import unittest, os
4from math import sqrt, pi
5import tempfile
6
7from anuga.config import g, epsilon
8from Numeric import allclose, alltrue, array, zeros, ones, Float, take
9from anuga.utilities.numerical_tools import mean
10from anuga.utilities.polygon import is_inside_polygon
11from anuga.coordinate_transforms.geo_reference import Geo_reference
12from anuga.abstract_2d_finite_volumes.quantity import Quantity
13from anuga.geospatial_data.geospatial_data import Geospatial_data
14
15from shallow_water_domain import *
16
17# Get gateway to C implementation of flux function for direct testing
18from shallow_water_ext import flux_function_central as flux_function
19
20# For test_fitting_using_shallow_water_domain example
21def linear_function(point):
22    point = array(point)
23    return point[:,0]+point[:,1]
24
25class Weir:
26    """Set a bathymetry for weir with a hole and a downstream gutter
27    x,y are assumed to be in the unit square
28    """
29
30    def __init__(self, stage):
31        self.inflow_stage = stage
32
33    def __call__(self, x, y):
34        from Numeric import zeros, Float
35
36        N = len(x)
37        assert N == len(y)
38
39        z = zeros(N, Float)
40        for i in range(N):
41            z[i] = -x[i]/2  #General slope
42
43            #Flattish bit to the left
44            if x[i] < 0.3:
45                z[i] = -x[i]/10
46
47            #Weir
48            if x[i] >= 0.3 and x[i] < 0.4:
49                z[i] = -x[i]+0.9
50
51            #Dip
52            x0 = 0.6
53            #depth = -1.3
54            depth = -1.0
55            #plateaux = -0.9
56            plateaux = -0.6
57            if y[i] < 0.7:
58                if x[i] > x0 and x[i] < 0.9:
59                    z[i] = depth
60
61                #RHS plateaux
62                if x[i] >= 0.9:
63                    z[i] = plateaux
64
65
66            elif y[i] >= 0.7 and y[i] < 1.5:
67                #Restrict and deepen
68                if x[i] >= x0 and x[i] < 0.8:
69                    z[i] = depth-(y[i]/3-0.3)
70                    #z[i] = depth-y[i]/5
71                    #z[i] = depth
72                elif x[i] >= 0.8:
73                    #RHS plateaux
74                    z[i] = plateaux
75
76            elif y[i] >= 1.5:
77                if x[i] >= x0 and x[i] < 0.8 + (y[i]-1.5)/1.2:
78                    #Widen up and stay at constant depth
79                    z[i] = depth-1.5/5
80                elif x[i] >= 0.8 + (y[i]-1.5)/1.2:
81                    #RHS plateaux
82                    z[i] = plateaux
83
84
85            #Hole in weir (slightly higher than inflow condition)
86            if x[i] >= 0.3 and x[i] < 0.4 and y[i] > 0.2 and y[i] < 0.4:
87                z[i] = -x[i]+self.inflow_stage + 0.02
88
89            #Channel behind weir
90            x0 = 0.5
91            if x[i] >= 0.4 and x[i] < x0 and y[i] > 0.2 and y[i] < 0.4:
92                z[i] = -x[i]+self.inflow_stage + 0.02
93
94            if x[i] >= x0 and x[i] < 0.6 and y[i] > 0.2 and y[i] < 0.4:
95                #Flatten it out towards the end
96                z[i] = -x0+self.inflow_stage + 0.02 + (x0-x[i])/5
97
98            #Hole to the east
99            x0 = 1.1; y0 = 0.35
100            #if x[i] < -0.2 and y < 0.5:
101            if sqrt((2*(x[i]-x0))**2 + (2*(y[i]-y0))**2) < 0.2:
102                z[i] = sqrt(((x[i]-x0))**2 + ((y[i]-y0))**2)-1.0
103
104            #Tiny channel draining hole
105            if x[i] >= 1.14 and x[i] < 1.2 and y[i] >= 0.4 and y[i] < 0.6:
106                z[i] = -0.9 #North south
107
108            if x[i] >= 0.9 and x[i] < 1.18 and y[i] >= 0.58 and y[i] < 0.65:
109                z[i] = -1.0 + (x[i]-0.9)/3 #East west
110
111
112
113            #Stuff not in use
114
115            #Upward slope at inlet to the north west
116            #if x[i] < 0.0: # and y[i] > 0.5:
117            #    #z[i] = -y[i]+0.5  #-x[i]/2
118            #    z[i] = x[i]/4 - y[i]**2 + 0.5
119
120            #Hole to the west
121            #x0 = -0.4; y0 = 0.35 # center
122            #if sqrt((2*(x[i]-x0))**2 + (2*(y[i]-y0))**2) < 0.2:
123            #    z[i] = sqrt(((x[i]-x0))**2 + ((y[i]-y0))**2)-0.2
124
125
126
127
128
129        return z/2
130
131class Weir_simple:
132    """Set a bathymetry for weir with a hole and a downstream gutter
133    x,y are assumed to be in the unit square
134    """
135
136    def __init__(self, stage):
137        self.inflow_stage = stage
138
139    def __call__(self, x, y):
140        from Numeric import zeros, Float
141
142        N = len(x)
143        assert N == len(y)
144
145        z = zeros(N, Float)
146        for i in range(N):
147            z[i] = -x[i]  #General slope
148
149            #Flat bit to the left
150            if x[i] < 0.3:
151                z[i] = -x[i]/10  #General slope
152
153            #Weir
154            if x[i] > 0.3 and x[i] < 0.4:
155                z[i] = -x[i]+0.9
156
157            #Dip
158            if x[i] > 0.6 and x[i] < 0.9:
159                z[i] = -x[i]-0.5  #-y[i]/5
160
161            #Hole in weir (slightly higher than inflow condition)
162            if x[i] > 0.3 and x[i] < 0.4 and y[i] > 0.2 and y[i] < 0.4:
163                z[i] = -x[i]+self.inflow_stage + 0.05
164
165
166        return z/2
167
168
169
170
171#Variable windfield implemented using functions
172def speed(t,x,y):
173    """Large speeds halfway between center and edges
174    Low speeds at center and edges
175    """
176
177    from math import exp, cos, pi
178
179    x = array(x)
180    y = array(y)
181
182    N = len(x)
183    s = 0*#New array
184
185    for k in range(N):
186
187        r = sqrt(x[k]**2 + y[k]**2)
188
189        factor = exp( -(r-0.15)**2 )
190
191        s[k] = 4000 * factor * (cos(t*2*pi/150) + 2)
192
193    return s
194
195
196def scalar_func(t,x,y):
197    """Function that returns a scalar.
198    Used to test error message when Numeric array is expected
199    """
200
201    return 17.7
202
203
204def angle(t,x,y):
205    """Rotating field
206    """
207    from math import atan, pi
208
209    x = array(x)
210    y = array(y)
211
212    N = len(x)
213    a = 0*#New array
214
215    for k in range(N):
216        r = sqrt(x[k]**2 + y[k]**2)
217
218        angle = atan(y[k]/x[k])
219
220        if x[k] < 0:
221            angle+=pi #atan in ]-pi/2; pi/2[
222
223        #Take normal direction
224        angle -= pi/2
225
226        #Ensure positive radians
227        if angle < 0:
228            angle += 2*pi
229
230        a[k] = angle/pi*180
231
232    return a
233
234
235class Test_Shallow_Water(unittest.TestCase):
236    def setUp(self):
237        pass
238
239    def tearDown(self):
240        pass
241
242    def test_rotate(self):
243        normal = array([0.0,-1.0])
244
245        q = array([1.0,2.0,3.0])
246
247        r = rotate(q, normal, direction = 1)
248        assert r[0] == 1
249        assert r[1] == -3
250        assert r[2] == 2
251
252        w = rotate(r, normal, direction = -1)
253        assert allclose(w, q)
254
255        #Check error check
256        try:
257            rotate(r, array([1,1,1]) )
258        except:
259            pass
260        else:
261            raise 'Should have raised an exception'
262
263
264    # Individual flux tests
265    def test_flux_zero_case(self):
266        ql = zeros( 3, Float )
267        qr = zeros( 3, Float )
268        normal = zeros( 2, Float )
269        edgeflux = zeros( 3, Float )
270        zl = zr = 0.
271        H0 = 0.0
272       
273        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux, epsilon, g, H0)
274
275        assert allclose(edgeflux, [0,0,0])
276        assert max_speed == 0.
277
278    def test_flux_constants(self):
279        w = 2.0
280
281        normal = array([1.,0])
282        ql = array([w, 0, 0])
283        qr = array([w, 0, 0])
284        edgeflux = zeros(3, Float)       
285        zl = zr = 0.
286        h = w - (zl+zr)/2
287        H0 = 0.0
288
289        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux, epsilon, g, H0)       
290        assert allclose(edgeflux, [0., 0.5*g*h**2, 0.])
291        assert max_speed == sqrt(g*h)
292
293    #def test_flux_slope(self):
294    #    #FIXME: TODO
295    #    w = 2.0
296    #
297    #    normal = array([1.,0])
298    #    ql = array([w, 0, 0])
299    #    qr = array([w, 0, 0])
300    #    zl = zr = 0.
301    #    h = w - (zl+zr)/2
302    #
303    #    flux, max_speed = flux_function(normal, ql, qr, zl, zr)
304    #
305    #    assert allclose(flux, [0., 0.5*g*h**2, 0.])
306    #    assert max_speed == sqrt(g*h)
307
308
309    def test_flux1(self):
310        #Use data from previous version of abstract_2d_finite_volumes
311        normal = array([1.,0])
312        ql = array([-0.2, 2, 3])
313        qr = array([-0.2, 2, 3])
314        zl = zr = -0.5
315        edgeflux = zeros(3, Float)               
316
317        H0 = 0.0
318
319        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux, epsilon, g, H0)       
320
321        assert allclose(edgeflux, [2.,13.77433333, 20.])
322        assert allclose(max_speed, 8.38130948661)
323
324
325    def test_flux2(self):
326        #Use data from previous version of abstract_2d_finite_volumes
327        normal = array([0., -1.])
328        ql = array([-0.075, 2, 3])
329        qr = array([-0.075, 2, 3])
330        zl = zr = -0.375
331
332        edgeflux = zeros(3, Float)               
333        H0 = 0.0
334        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux, epsilon, g, H0)       
335
336        assert allclose(edgeflux, [-3.,-20.0, -30.441])
337        assert allclose(max_speed, 11.7146428199)
338
339    def test_flux3(self):
340        #Use data from previous version of abstract_2d_finite_volumes
341        normal = array([-sqrt(2)/2, sqrt(2)/2])
342        ql = array([-0.075, 2, 3])
343        qr = array([-0.075, 2, 3])
344        zl = zr = -0.375
345
346        edgeflux = zeros(3, Float)               
347        H0 = 0.0
348        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux, epsilon, g, H0)       
349
350        assert allclose(edgeflux, [sqrt(2)/2, 4.40221112, 7.3829019])
351        assert allclose(max_speed, 4.0716654239)
352
353    def test_flux4(self):
354        #Use data from previous version of abstract_2d_finite_volumes
355        normal = array([-sqrt(2)/2, sqrt(2)/2])
356        ql = array([-0.34319278, 0.10254161, 0.07273855])
357        qr = array([-0.30683287, 0.1071986, 0.05930515])
358        zl = zr = -0.375
359
360        edgeflux = zeros(3, Float)               
361        H0 = 0.0
362        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux, epsilon, g, H0)               
363
364        assert allclose(edgeflux, [-0.04072676, -0.07096636, -0.01604364])
365        assert allclose(max_speed, 1.31414103233)
366
367    def test_flux_computation(self):   
368        """test_flux_computation - test flux calculation (actual C implementation)
369        This one tests the constant case where only the pressure term contributes to each edge and cancels out
370        once the total flux has been summed up.
371        """
372               
373        a = [0.0, 0.0]
374        b = [0.0, 2.0]
375        c = [2.0,0.0]
376        d = [0.0, 4.0]
377        e = [2.0, 2.0]
378        f = [4.0,0.0]
379
380        points = [a, b, c, d, e, f]
381        #bac, bce, ecf, dbe, daf, dae
382        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
383
384        domain = Domain(points, vertices)
385        domain.check_integrity()
386
387        # The constant case             
388        domain.set_quantity('elevation', -1)
389        domain.set_quantity('stage', 1) 
390       
391        domain.compute_fluxes()
392        assert allclose(domain.get_quantity('stage').explicit_update[1], 0) # Central triangle
393       
394
395        # The more general case                 
396        def surface(x,y):
397            return -x/2                   
398       
399        domain.set_quantity('elevation', -10)
400        domain.set_quantity('stage', surface)   
401        domain.set_quantity('xmomentum', 1)             
402       
403        domain.compute_fluxes()
404       
405        #print domain.get_quantity('stage').explicit_update
406        # FIXME (Ole): TODO the general case
407        #assert allclose(domain.get_quantity('stage').explicit_update[1], ........??)
408               
409       
410               
411    def test_sw_domain_simple(self):
412        a = [0.0, 0.0]
413        b = [0.0, 2.0]
414        c = [2.0,0.0]
415        d = [0.0, 4.0]
416        e = [2.0, 2.0]
417        f = [4.0,0.0]
418
419        points = [a, b, c, d, e, f]
420        #bac, bce, ecf, dbe, daf, dae
421        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
422
423
424        #from anuga.abstract_2d_finite_volumes.domain import Domain as Generic_domain
425        #msg = 'The class %s is not a subclass of the generic domain class %s'\
426        #      %(DomainClass, Domain)
427        #assert issubclass(DomainClass, Domain), msg
428
429        domain = Domain(points, vertices)
430        domain.check_integrity()
431
432        for name in ['stage', 'xmomentum', 'ymomentum',
433                     'elevation', 'friction']:
434            assert domain.quantities.has_key(name)
435
436
437        assert domain.get_conserved_quantities(0, edge=1) == 0.
438
439
440    def test_boundary_conditions(self):
441
442        a = [0.0, 0.0]
443        b = [0.0, 2.0]
444        c = [2.0,0.0]
445        d = [0.0, 4.0]
446        e = [2.0, 2.0]
447        f = [4.0,0.0]
448
449        points = [a, b, c, d, e, f]
450        #bac, bce, ecf, dbe
451        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
452        boundary = { (0, 0): 'Third',
453                     (0, 2): 'First',
454                     (2, 0): 'Second',
455                     (2, 1): 'Second',
456                     (3, 1): 'Second',
457                     (3, 2): 'Third'}
458
459
460        domain = Domain(points, vertices, boundary)
461        domain.check_integrity()
462
463
464        domain.set_quantity('stage', [[1,2,3], [5,5,5],
465                                      [0,0,9], [-6, 3, 3]])
466
467        domain.set_quantity('xmomentum', [[1,1,1], [2,2,2],
468                                          [3,3,3], [4, 4, 4]])
469
470        domain.set_quantity('ymomentum', [[10,10,10], [20,20,20],
471                                          [30,30,30], [40, 40, 40]])
472
473
474        D = Dirichlet_boundary([5,2,1])
475        T = Transmissive_boundary(domain)
476        R = Reflective_boundary(domain)
477        domain.set_boundary( {'First': D, 'Second': T, 'Third': R})
478
479        domain.update_boundary()
480
481        #Stage
482        assert domain.quantities['stage'].boundary_values[0] == 2.5
483        assert domain.quantities['stage'].boundary_values[0] ==\
484               domain.get_conserved_quantities(0, edge=0)[0] #Reflective (2.5)
485        assert domain.quantities['stage'].boundary_values[1] == 5. #Dirichlet
486        assert domain.quantities['stage'].boundary_values[2] ==\
487               domain.get_conserved_quantities(2, edge=0)[0] #Transmissive (4.5)
488        assert domain.quantities['stage'].boundary_values[3] ==\
489               domain.get_conserved_quantities(2, edge=1)[0] #Transmissive (4.5)
490        assert domain.quantities['stage'].boundary_values[4] ==\
491               domain.get_conserved_quantities(3, edge=1)[0] #Transmissive (-1.5)
492        assert domain.quantities['stage'].boundary_values[5] ==\
493               domain.get_conserved_quantities(3, edge=2)[0] #Reflective (-1.5)
494
495        #Xmomentum
496        assert domain.quantities['xmomentum'].boundary_values[0] == 1.0 #Reflective
497        assert domain.quantities['xmomentum'].boundary_values[1] == 2. #Dirichlet
498        assert domain.quantities['xmomentum'].boundary_values[2] ==\
499               domain.get_conserved_quantities(2, edge=0)[1] #Transmissive
500        assert domain.quantities['xmomentum'].boundary_values[3] ==\
501               domain.get_conserved_quantities(2, edge=1)[1] #Transmissive
502        assert domain.quantities['xmomentum'].boundary_values[4] ==\
503               domain.get_conserved_quantities(3, edge=1)[1] #Transmissive
504        assert domain.quantities['xmomentum'].boundary_values[5] == -4.0  #Reflective
505
506        #Ymomentum
507        assert domain.quantities['ymomentum'].boundary_values[0] == -10.0 #Reflective
508        assert domain.quantities['ymomentum'].boundary_values[1] == 1.  #Dirichlet
509        assert domain.quantities['ymomentum'].boundary_values[2] == 30. #Transmissive
510        assert domain.quantities['ymomentum'].boundary_values[3] == 30. #Transmissive
511        assert domain.quantities['ymomentum'].boundary_values[4] == 40. #Transmissive
512        assert domain.quantities['ymomentum'].boundary_values[5] == 40. #Reflective
513
514
515    def test_boundary_conditionsII(self):
516
517        a = [0.0, 0.0]
518        b = [0.0, 2.0]
519        c = [2.0,0.0]
520        d = [0.0, 4.0]
521        e = [2.0, 2.0]
522        f = [4.0,0.0]
523
524        points = [a, b, c, d, e, f]
525        #bac, bce, ecf, dbe
526        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
527        boundary = { (0, 0): 'Third',
528                     (0, 2): 'First',
529                     (2, 0): 'Second',
530                     (2, 1): 'Second',
531                     (3, 1): 'Second',
532                     (3, 2): 'Third',
533                     (0, 1): 'Internal'}
534
535
536        domain = Domain(points, vertices, boundary)
537        domain.check_integrity()
538
539
540        domain.set_quantity('stage', [[1,2,3], [5,5,5],
541                                      [0,0,9], [-6, 3, 3]])
542
543        domain.set_quantity('xmomentum', [[1,1,1], [2,2,2],
544                                          [3,3,3], [4, 4, 4]])
545
546        domain.set_quantity('ymomentum', [[10,10,10], [20,20,20],
547                                          [30,30,30], [40, 40, 40]])
548
549
550        D = Dirichlet_boundary([5,2,1])
551        T = Transmissive_boundary(domain)
552        R = Reflective_boundary(domain)
553        domain.set_boundary( {'First': D, 'Second': T,
554                              'Third': R, 'Internal': None})
555
556        domain.update_boundary()
557        domain.check_integrity()
558
559
560    def test_compute_fluxes0(self):
561        # Do a full triangle and check that fluxes cancel out for
562        # the constant stage case
563
564        a = [0.0, 0.0]
565        b = [0.0, 2.0]
566        c = [2.0,0.0]
567        d = [0.0, 4.0]
568        e = [2.0, 2.0]
569        f = [4.0,0.0]
570
571        points = [a, b, c, d, e, f]
572        #bac, bce, ecf, dbe
573        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
574
575        domain = Domain(points, vertices)
576        domain.set_quantity('stage', [[2,2,2], [2,2,2],
577                                      [2,2,2], [2,2,2]])
578        domain.check_integrity()
579
580        assert allclose(domain.neighbours, [[-1,1,-1], [2,3,0], [-1,-1,1],[1,-1,-1]])
581        assert allclose(domain.neighbour_edges, [[-1,2,-1], [2,0,1], [-1,-1,0],[1,-1,-1]])
582
583        zl=zr=0. # Assume flat bed
584
585        edgeflux = zeros(3, Float)       
586        edgeflux0 = zeros(3, Float)
587        edgeflux1 = zeros(3, Float)
588        edgeflux2 = zeros(3, Float)                               
589        H0 = 0.0       
590
591        # Flux across right edge of volume 1
592        normal = domain.get_normal(1,0)
593        ql = domain.get_conserved_quantities(vol_id=1, edge=0)
594        qr = domain.get_conserved_quantities(vol_id=2, edge=2)
595        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux0, epsilon, g, H0)                       
596
597        # Check that flux seen from other triangles is inverse
598        tmp = qr; qr=ql; ql=tmp
599        normal = domain.get_normal(2,2)
600        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux, epsilon, g, H0)                               
601
602        assert allclose(edgeflux0 + edgeflux, 0.)
603
604        # Flux across upper edge of volume 1
605        normal = domain.get_normal(1,1)
606        ql = domain.get_conserved_quantities(vol_id=1, edge=1)
607        qr = domain.get_conserved_quantities(vol_id=3, edge=0)
608        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux1, epsilon, g, H0)                                       
609
610        # Check that flux seen from other triangles is inverse
611        tmp = qr; qr=ql; ql=tmp
612        normal = domain.get_normal(3,0)
613        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux, epsilon, g, H0)                                               
614
615        assert allclose(edgeflux1 + edgeflux, 0.)       
616       
617
618        # Flux across lower left hypotenuse of volume 1
619        normal = domain.get_normal(1,2)
620        ql = domain.get_conserved_quantities(vol_id=1, edge=2)
621        qr = domain.get_conserved_quantities(vol_id=0, edge=1)
622        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux2, epsilon, g, H0)                                                               
623
624        # Check that flux seen from other triangles is inverse
625        tmp = qr; qr=ql; ql=tmp
626        normal = domain.get_normal(0,1)
627        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux, epsilon, g, H0)                                                       
628        assert allclose(edgeflux2 + edgeflux, 0.)
629
630
631        # Scale by edgelengths, add up anc check that total flux is zero
632        e0 = domain.edgelengths[1, 0]
633        e1 = domain.edgelengths[1, 1]
634        e2 = domain.edgelengths[1, 2]
635
636        assert allclose(e0*edgeflux0+e1*edgeflux1+e2*edgeflux2, 0.)
637
638        # Now check that compute_flux yields zeros as well
639        domain.compute_fluxes()
640
641        for name in ['stage', 'xmomentum', 'ymomentum']:
642            #print name, domain.quantities[name].explicit_update
643            assert allclose(domain.quantities[name].explicit_update[1], 0)
644
645
646
647    def test_compute_fluxes1(self):
648        #Use values from previous version
649
650        a = [0.0, 0.0]
651        b = [0.0, 2.0]
652        c = [2.0,0.0]
653        d = [0.0, 4.0]
654        e = [2.0, 2.0]
655        f = [4.0,0.0]
656
657        points = [a, b, c, d, e, f]
658        #bac, bce, ecf, dbe
659        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
660
661        domain = Domain(points, vertices)
662        val0 = 2.+2.0/3
663        val1 = 4.+4.0/3
664        val2 = 8.+2.0/3
665        val3 = 2.+8.0/3
666
667        domain.set_quantity('stage', [[val0, val0, val0], [val1, val1, val1],
668                                      [val2, val2, val2], [val3, val3, val3]])
669        domain.check_integrity()
670
671        zl=zr=0. #Assume flat bed
672
673        edgeflux = zeros(3, Float)       
674        edgeflux0 = zeros(3, Float)
675        edgeflux1 = zeros(3, Float)
676        edgeflux2 = zeros(3, Float)                               
677        H0 = 0.0       
678       
679
680        # Flux across right edge of volume 1
681        normal = domain.get_normal(1,0) #Get normal 0 of triangle 1
682        assert allclose(normal, [1, 0])
683       
684        ql = domain.get_conserved_quantities(vol_id=1, edge=0)
685        assert allclose(ql, [val1, 0, 0])
686       
687        qr = domain.get_conserved_quantities(vol_id=2, edge=2)
688        assert allclose(qr, [val2, 0, 0])
689
690        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux0, epsilon, g, H0)                                                       
691
692        # Flux across edge in the east direction (as per normal vector)
693        assert allclose(edgeflux0, [-15.3598804, 253.71111111, 0.])
694        assert allclose(max_speed, 9.21592824046)
695
696
697        #Flux across edge in the west direction (opposite sign for xmomentum)
698        normal_opposite = domain.get_normal(2,2) #Get normal 2 of triangle 2
699        assert allclose(normal_opposite, [-1, 0])
700
701        max_speed = flux_function(normal_opposite, ql, qr, zl, zr, edgeflux, epsilon, g, H0)                                             
702        #flux_opposite, max_speed = flux_function([-1, 0], ql, qr, zl, zr)
703        assert allclose(edgeflux, [-15.3598804, -253.71111111, 0.])
704       
705
706        #Flux across upper edge of volume 1
707        normal = domain.get_normal(1,1)
708        ql = domain.get_conserved_quantities(vol_id=1, edge=1)
709        qr = domain.get_conserved_quantities(vol_id=3, edge=0)
710        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux1, epsilon, g, H0)                                                               
711
712        assert allclose(edgeflux1, [2.4098563, 0., 123.04444444])
713        assert allclose(max_speed, 7.22956891292)
714
715        #Flux across lower left hypotenuse of volume 1
716        normal = domain.get_normal(1,2)
717        ql = domain.get_conserved_quantities(vol_id=1, edge=2)
718        qr = domain.get_conserved_quantities(vol_id=0, edge=1)
719        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux2, epsilon, g, H0)       
720
721        assert allclose(edgeflux2, [9.63942522, -61.59685738, -61.59685738])
722        assert allclose(max_speed, 7.22956891292)
723
724        #Scale, add up and check that compute_fluxes is correct for vol 1
725        e0 = domain.edgelengths[1, 0]
726        e1 = domain.edgelengths[1, 1]
727        e2 = domain.edgelengths[1, 2]
728
729        total_flux = -(e0*edgeflux0+e1*edgeflux1+e2*edgeflux2)/domain.areas[1]
730        assert allclose(total_flux, [-0.68218178, -166.6, -35.93333333])
731
732
733        domain.compute_fluxes()
734
735        #assert allclose(total_flux, domain.explicit_update[1,:])
736        for i, name in enumerate(['stage', 'xmomentum', 'ymomentum']):
737            assert allclose(total_flux[i],
738                            domain.quantities[name].explicit_update[1])
739
740        #assert allclose(domain.explicit_update, [
741        #    [0., -69.68888889, -69.68888889],
742        #    [-0.68218178, -166.6, -35.93333333],
743        #    [-111.77316251, 69.68888889, 0.],
744        #    [-35.68522449, 0., 69.68888889]])
745
746        assert allclose(domain.quantities['stage'].explicit_update,
747                        [0., -0.68218178, -111.77316251, -35.68522449])
748        assert allclose(domain.quantities['xmomentum'].explicit_update,
749                        [-69.68888889, -166.6, 69.68888889, 0])
750        assert allclose(domain.quantities['ymomentum'].explicit_update,
751                        [-69.68888889, -35.93333333, 0., 69.68888889])
752
753
754        #assert allclose(domain.quantities[name].explicit_update
755
756
757
758
759
760    def test_compute_fluxes2(self):
761        #Random values, incl momentum
762
763        a = [0.0, 0.0]
764        b = [0.0, 2.0]
765        c = [2.0,0.0]
766        d = [0.0, 4.0]
767        e = [2.0, 2.0]
768        f = [4.0,0.0]
769
770        points = [a, b, c, d, e, f]
771        #bac, bce, ecf, dbe
772        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
773
774        domain = Domain(points, vertices)
775        val0 = 2.+2.0/3
776        val1 = 4.+4.0/3
777        val2 = 8.+2.0/3
778        val3 = 2.+8.0/3
779
780        zl=zr=0 #Assume flat zero bed
781        edgeflux = zeros(3, Float)       
782        edgeflux0 = zeros(3, Float)
783        edgeflux1 = zeros(3, Float)
784        edgeflux2 = zeros(3, Float)                               
785        H0 = 0.0       
786       
787
788        domain.set_quantity('elevation', zl*ones( (4,3) ))
789
790
791        domain.set_quantity('stage', [[val0, val0-1, val0-2],
792                                      [val1, val1+1, val1],
793                                      [val2, val2-2, val2],
794                                      [val3-0.5, val3, val3]])
795
796        domain.set_quantity('xmomentum',
797                            [[1, 2, 3], [3, 4, 5],
798                             [1, -1, 0], [0, -2, 2]])
799
800        domain.set_quantity('ymomentum',
801                            [[1, -1, 0], [0, -3, 2],
802                             [0, 1, 0], [-1, 2, 2]])
803
804
805        domain.check_integrity()
806
807
808
809        #Flux across right edge of volume 1
810        normal = domain.get_normal(1,0)
811        ql = domain.get_conserved_quantities(vol_id=1, edge=0)
812        qr = domain.get_conserved_quantities(vol_id=2, edge=2)
813        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux0, epsilon, g, H0)               
814
815        #Flux across upper edge of volume 1
816        normal = domain.get_normal(1,1)
817        ql = domain.get_conserved_quantities(vol_id=1, edge=1)
818        qr = domain.get_conserved_quantities(vol_id=3, edge=0)
819        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux1, epsilon, g, H0)                       
820
821        #Flux across lower left hypotenuse of volume 1
822        normal = domain.get_normal(1,2)
823        ql = domain.get_conserved_quantities(vol_id=1, edge=2)
824        qr = domain.get_conserved_quantities(vol_id=0, edge=1)
825        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux2, epsilon, g, H0)               
826
827        #Scale, add up and check that compute_fluxes is correct for vol 1
828        e0 = domain.edgelengths[1, 0]
829        e1 = domain.edgelengths[1, 1]
830        e2 = domain.edgelengths[1, 2]
831
832        total_flux = -(e0*edgeflux0+e1*edgeflux1+e2*edgeflux2)/domain.areas[1]
833
834
835        domain.compute_fluxes()
836        for i, name in enumerate(['stage', 'xmomentum', 'ymomentum']):
837            assert allclose(total_flux[i],
838                            domain.quantities[name].explicit_update[1])
839        #assert allclose(total_flux, domain.explicit_update[1,:])
840
841
842    # FIXME (Ole): Need test like this for fluxes in very shallow water.   
843    def test_compute_fluxes3(self):
844        #Random values, incl momentum
845
846        a = [0.0, 0.0]
847        b = [0.0, 2.0]
848        c = [2.0,0.0]
849        d = [0.0, 4.0]
850        e = [2.0, 2.0]
851        f = [4.0,0.0]
852
853        points = [a, b, c, d, e, f]
854        #bac, bce, ecf, dbe
855        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
856
857        domain = Domain(points, vertices)
858        val0 = 2.+2.0/3
859        val1 = 4.+4.0/3
860        val2 = 8.+2.0/3
861        val3 = 2.+8.0/3
862
863        zl=zr=-3.75 #Assume constant bed (must be less than stage)
864        domain.set_quantity('elevation', zl*ones( (4,3) ))
865
866
867        edgeflux = zeros(3, Float)       
868        edgeflux0 = zeros(3, Float)
869        edgeflux1 = zeros(3, Float)
870        edgeflux2 = zeros(3, Float)                               
871        H0 = 0.0       
872       
873
874
875        domain.set_quantity('stage', [[val0, val0-1, val0-2],
876                                      [val1, val1+1, val1],
877                                      [val2, val2-2, val2],
878                                      [val3-0.5, val3, val3]])
879
880        domain.set_quantity('xmomentum',
881                            [[1, 2, 3], [3, 4, 5],
882                             [1, -1, 0], [0, -2, 2]])
883
884        domain.set_quantity('ymomentum',
885                            [[1, -1, 0], [0, -3, 2],
886                             [0, 1, 0], [-1, 2, 2]])
887
888
889        domain.check_integrity()
890
891
892
893        #Flux across right edge of volume 1
894        normal = domain.get_normal(1,0)
895        ql = domain.get_conserved_quantities(vol_id=1, edge=0)
896        qr = domain.get_conserved_quantities(vol_id=2, edge=2)
897        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux0, epsilon, g, H0)
898
899        #Flux across upper edge of volume 1
900        normal = domain.get_normal(1,1)
901        ql = domain.get_conserved_quantities(vol_id=1, edge=1)
902        qr = domain.get_conserved_quantities(vol_id=3, edge=0)
903        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux1, epsilon, g, H0)       
904
905        #Flux across lower left hypotenuse of volume 1
906        normal = domain.get_normal(1,2)
907        ql = domain.get_conserved_quantities(vol_id=1, edge=2)
908        qr = domain.get_conserved_quantities(vol_id=0, edge=1)
909        max_speed = flux_function(normal, ql, qr, zl, zr, edgeflux2, epsilon, g, H0)       
910
911        #Scale, add up and check that compute_fluxes is correct for vol 1
912        e0 = domain.edgelengths[1, 0]
913        e1 = domain.edgelengths[1, 1]
914        e2 = domain.edgelengths[1, 2]
915
916        total_flux = -(e0*edgeflux0+e1*edgeflux1+e2*edgeflux2)/domain.areas[1]
917
918        domain.compute_fluxes()
919        for i, name in enumerate(['stage', 'xmomentum', 'ymomentum']):
920            assert allclose(total_flux[i],
921                            domain.quantities[name].explicit_update[1])
922
923
924
925    def xtest_catching_negative_heights(self):
926
927        #OBSOLETE
928       
929        a = [0.0, 0.0]
930        b = [0.0, 2.0]
931        c = [2.0,0.0]
932        d = [0.0, 4.0]
933        e = [2.0, 2.0]
934        f = [4.0,0.0]
935
936        points = [a, b, c, d, e, f]
937        #bac, bce, ecf, dbe
938        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
939
940        domain = Domain(points, vertices)
941        val0 = 2.+2.0/3
942        val1 = 4.+4.0/3
943        val2 = 8.+2.0/3
944        val3 = 2.+8.0/3
945
946        zl=zr=4  #Too large
947        domain.set_quantity('elevation', zl*ones( (4,3) ))
948        domain.set_quantity('stage', [[val0, val0-1, val0-2],
949                                      [val1, val1+1, val1],
950                                      [val2, val2-2, val2],
951                                      [val3-0.5, val3, val3]])
952
953        #Should fail
954        try:
955            domain.check_integrity()
956        except:
957            pass
958
959
960
961    def test_get_wet_elements(self):
962
963        a = [0.0, 0.0]
964        b = [0.0, 2.0]
965        c = [2.0,0.0]
966        d = [0.0, 4.0]
967        e = [2.0, 2.0]
968        f = [4.0,0.0]
969
970        points = [a, b, c, d, e, f]
971        #bac, bce, ecf, dbe
972        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
973
974        domain = Domain(points, vertices)
975        val0 = 2.+2.0/3
976        val1 = 4.+4.0/3
977        val2 = 8.+2.0/3
978        val3 = 2.+8.0/3
979
980        zl=zr=5
981        domain.set_quantity('elevation', zl*ones( (4,3) ))
982        domain.set_quantity('stage', [[val0, val0-1, val0-2],
983                                      [val1, val1+1, val1],
984                                      [val2, val2-2, val2],
985                                      [val3-0.5, val3, val3]])
986
987
988
989        #print domain.get_quantity('elevation').get_values(location='centroids')
990        #print domain.get_quantity('stage').get_values(location='centroids')       
991        domain.check_integrity()
992
993        indices = domain.get_wet_elements()
994        assert allclose(indices, [1,2])
995
996        indices = domain.get_wet_elements(indices=[0,1,3])
997        assert allclose(indices, [1])
998       
999
1000
1001    def test_get_maximum_inundation_1(self):
1002
1003        a = [0.0, 0.0]
1004        b = [0.0, 2.0]
1005        c = [2.0,0.0]
1006        d = [0.0, 4.0]
1007        e = [2.0, 2.0]
1008        f = [4.0,0.0]
1009
1010        points = [a, b, c, d, e, f]
1011        #bac, bce, ecf, dbe
1012        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
1013
1014        domain = Domain(points, vertices)
1015
1016        domain.set_quantity('elevation', lambda x, y: x+2*y) #2 4 4 6
1017        domain.set_quantity('stage', 3)
1018
1019        domain.check_integrity()
1020
1021        indices = domain.get_wet_elements()
1022        assert allclose(indices, [0])
1023
1024        q = domain.get_maximum_inundation_elevation()
1025        assert allclose(q, domain.get_quantity('elevation').get_values(location='centroids')[0])
1026
1027        x, y = domain.get_maximum_inundation_location()
1028        assert allclose([x, y], domain.get_centroid_coordinates()[0])
1029
1030
1031    def test_get_maximum_inundation_2(self):
1032        """test_get_maximum_inundation_2(self)
1033
1034        Test multiple wet cells with same elevation
1035        """
1036       
1037        a = [0.0, 0.0]
1038        b = [0.0, 2.0]
1039        c = [2.0,0.0]
1040        d = [0.0, 4.0]
1041        e = [2.0, 2.0]
1042        f = [4.0,0.0]
1043
1044        points = [a, b, c, d, e, f]
1045        #bac, bce, ecf, dbe
1046        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
1047
1048        domain = Domain(points, vertices)
1049
1050        domain.set_quantity('elevation', lambda x, y: x+2*y) #2 4 4 6
1051        domain.set_quantity('stage', 4.1)
1052
1053        domain.check_integrity()
1054
1055        indices = domain.get_wet_elements()
1056        assert allclose(indices, [0,1,2])
1057
1058        q = domain.get_maximum_inundation_elevation()
1059        assert allclose(q, 4)       
1060
1061        x, y = domain.get_maximum_inundation_location()
1062        assert allclose([x, y], domain.get_centroid_coordinates()[1])       
1063       
1064
1065    def test_get_maximum_inundation_3(self):
1066        """test_get_maximum_inundation_3(self)
1067
1068        Test of real runup example:
1069        """
1070
1071        from anuga.abstract_2d_finite_volumes.mesh_factory import rectangular_cross
1072
1073        initial_runup_height = -0.4
1074        final_runup_height = -0.3
1075
1076
1077        #--------------------------------------------------------------
1078        # Setup computational domain
1079        #--------------------------------------------------------------
1080        N = 5
1081        points, vertices, boundary = rectangular_cross(N, N) 
1082        domain = Domain(points, vertices, boundary)
1083        domain.set_maximum_allowed_speed(1.0)       
1084
1085        #--------------------------------------------------------------
1086        # Setup initial conditions
1087        #--------------------------------------------------------------
1088        def topography(x,y):
1089            return -x/2                             # linear bed slope
1090           
1091
1092        domain.set_quantity('elevation', topography)       # Use function for elevation
1093        domain.set_quantity('friction', 0.)                # Zero friction
1094        domain.set_quantity('stage', initial_runup_height) # Constant negative initial stage
1095
1096
1097        #--------------------------------------------------------------
1098        # Setup boundary conditions
1099        #--------------------------------------------------------------
1100        Br = Reflective_boundary(domain)              # Reflective wall
1101        Bd = Dirichlet_boundary([final_runup_height,  # Constant inflow
1102                                 0,
1103                                 0])
1104
1105        # All reflective to begin with (still water)
1106        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
1107
1108
1109        #--------------------------------------------------------------
1110        # Test initial inundation height
1111        #--------------------------------------------------------------
1112
1113        indices = domain.get_wet_elements()
1114        z = domain.get_quantity('elevation').\
1115            get_values(location='centroids', indices=indices)
1116        assert alltrue(z<initial_runup_height)
1117
1118        q = domain.get_maximum_inundation_elevation()
1119        assert allclose(q, initial_runup_height, rtol = 1.0/N) # First order accuracy
1120
1121        x, y = domain.get_maximum_inundation_location()
1122
1123        qref = domain.get_quantity('elevation').get_values(interpolation_points = [[x, y]])
1124        assert allclose(q, qref)
1125
1126
1127        wet_elements = domain.get_wet_elements()
1128        wet_elevations = domain.get_quantity('elevation').get_values(location='centroids',
1129                                                                     indices=wet_elements)
1130        assert alltrue(wet_elevations<initial_runup_height)
1131        assert allclose(wet_elevations, z)       
1132
1133
1134        #print domain.get_quantity('elevation').get_maximum_value(indices=wet_elements)
1135        #print domain.get_quantity('elevation').get_maximum_location(indices=wet_elements)
1136        #print domain.get_quantity('elevation').get_maximum_index(indices=wet_elements)
1137
1138       
1139        #--------------------------------------------------------------
1140        # Let triangles adjust
1141        #--------------------------------------------------------------
1142        for t in domain.evolve(yieldstep = 0.1, finaltime = 1.0):
1143            pass
1144
1145
1146        #--------------------------------------------------------------
1147        # Test inundation height again
1148        #--------------------------------------------------------------
1149
1150        indices = domain.get_wet_elements()
1151        z = domain.get_quantity('elevation').\
1152            get_values(location='centroids', indices=indices)
1153
1154        assert alltrue(z<initial_runup_height)
1155
1156        q = domain.get_maximum_inundation_elevation()
1157        assert allclose(q, initial_runup_height, rtol = 1.0/N) # First order accuracy
1158       
1159        x, y = domain.get_maximum_inundation_location()
1160        qref = domain.get_quantity('elevation').get_values(interpolation_points = [[x, y]])
1161        assert allclose(q, qref)       
1162
1163
1164        #--------------------------------------------------------------
1165        # Update boundary to allow inflow
1166        #--------------------------------------------------------------
1167        domain.set_boundary({'right': Bd})
1168
1169       
1170        #--------------------------------------------------------------
1171        # Evolve system through time
1172        #--------------------------------------------------------------
1173        for t in domain.evolve(yieldstep = 0.1, finaltime = 3.0):
1174            #print domain.timestepping_statistics(track_speeds=True)
1175            #domain.write_time()
1176            pass
1177   
1178        #--------------------------------------------------------------
1179        # Test inundation height again
1180        #--------------------------------------------------------------
1181
1182        indices = domain.get_wet_elements()
1183        z = domain.get_quantity('elevation').\
1184            get_values(location='centroids', indices=indices)
1185
1186        assert alltrue(z<final_runup_height)
1187
1188        q = domain.get_maximum_inundation_elevation()
1189        assert allclose(q, final_runup_height, rtol = 1.0/N) # First order accuracy
1190
1191        x, y = domain.get_maximum_inundation_location()
1192        qref = domain.get_quantity('elevation').get_values(interpolation_points = [[x, y]])
1193        assert allclose(q, qref)       
1194
1195
1196        wet_elements = domain.get_wet_elements()
1197        wet_elevations = domain.get_quantity('elevation').get_values(location='centroids',
1198                                                                     indices=wet_elements)
1199        assert alltrue(wet_elevations<final_runup_height)
1200        assert allclose(wet_elevations, z)       
1201       
1202
1203
1204    def test_get_maximum_inundation_from_sww(self):
1205        """test_get_maximum_inundation_from_sww(self)
1206
1207        Test of get_maximum_inundation_elevation()
1208        and get_maximum_inundation_location() from data_manager.py
1209       
1210        This is based on test_get_maximum_inundation_3(self) but works with the
1211        stored results instead of with the internal data structure.
1212
1213        This test uses the underlying get_maximum_inundation_data for tests
1214        """
1215
1216        from anuga.abstract_2d_finite_volumes.mesh_factory import rectangular_cross
1217        from data_manager import get_maximum_inundation_elevation
1218        from data_manager import get_maximum_inundation_location
1219        from data_manager import get_maximum_inundation_data
1220       
1221
1222        initial_runup_height = -0.4
1223        final_runup_height = -0.3
1224
1225
1226        #--------------------------------------------------------------
1227        # Setup computational domain
1228        #--------------------------------------------------------------
1229        N = 10
1230        points, vertices, boundary = rectangular_cross(N, N) 
1231        domain = Domain(points, vertices, boundary)
1232        domain.set_name('runup_test')
1233        domain.set_maximum_allowed_speed(1.0)
1234
1235        domain.tight_slope_limiters = 0 # FIXME: This works better with old limiters so far
1236
1237        #--------------------------------------------------------------
1238        # Setup initial conditions
1239        #--------------------------------------------------------------
1240        def topography(x,y):
1241            return -x/2                             # linear bed slope
1242           
1243
1244        domain.set_quantity('elevation', topography)       # Use function for elevation
1245        domain.set_quantity('friction', 0.)                # Zero friction
1246        domain.set_quantity('stage', initial_runup_height) # Constant negative initial stage
1247
1248
1249        #--------------------------------------------------------------
1250        # Setup boundary conditions
1251        #--------------------------------------------------------------
1252        Br = Reflective_boundary(domain)              # Reflective wall
1253        Bd = Dirichlet_boundary([final_runup_height,  # Constant inflow
1254                                 0,
1255                                 0])
1256
1257        # All reflective to begin with (still water)
1258        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
1259
1260
1261        #--------------------------------------------------------------
1262        # Test initial inundation height
1263        #--------------------------------------------------------------
1264
1265        indices = domain.get_wet_elements()
1266        z = domain.get_quantity('elevation').\
1267            get_values(location='centroids', indices=indices)
1268        assert alltrue(z<initial_runup_height)
1269
1270        q_ref = domain.get_maximum_inundation_elevation()
1271        assert allclose(q_ref, initial_runup_height, rtol = 1.0/N) # First order accuracy
1272
1273       
1274        #--------------------------------------------------------------
1275        # Let triangles adjust
1276        #--------------------------------------------------------------
1277        for t in domain.evolve(yieldstep = 0.1, finaltime = 1.0):
1278            pass
1279
1280
1281        #--------------------------------------------------------------
1282        # Test inundation height again
1283        #--------------------------------------------------------------
1284       
1285        q_ref = domain.get_maximum_inundation_elevation()
1286        q = get_maximum_inundation_elevation('runup_test.sww')
1287        msg = 'We got %f, should have been %f' %(q, q_ref)
1288        assert allclose(q, q_ref, rtol=1.0/N), msg
1289
1290
1291        q = get_maximum_inundation_elevation('runup_test.sww')
1292        msg = 'We got %f, should have been %f' %(q, initial_runup_height)
1293        assert allclose(q, initial_runup_height, rtol = 1.0/N), msg
1294
1295
1296        # Test error condition if time interval is out
1297        try:
1298            q = get_maximum_inundation_elevation('runup_test.sww',
1299                                                 time_interval=[2.0, 3.0])
1300        except ValueError:
1301            pass
1302        else:
1303            msg = 'should have caught wrong time interval'
1304            raise Exception, msg
1305
1306        # Check correct time interval
1307        q, loc = get_maximum_inundation_data('runup_test.sww',
1308                                             time_interval=[0.0, 3.0])       
1309        msg = 'We got %f, should have been %f' %(q, initial_runup_height)
1310        assert allclose(q, initial_runup_height, rtol = 1.0/N), msg
1311        assert allclose(-loc[0]/2, q) # From topography formula         
1312       
1313
1314        #--------------------------------------------------------------
1315        # Update boundary to allow inflow
1316        #--------------------------------------------------------------
1317        domain.set_boundary({'right': Bd})
1318
1319       
1320        #--------------------------------------------------------------
1321        # Evolve system through time
1322        #--------------------------------------------------------------
1323        q_max = None
1324        for t in domain.evolve(yieldstep = 0.1, finaltime = 3.0,
1325                               skip_initial_step = True): 
1326            q = domain.get_maximum_inundation_elevation()
1327            if q > q_max: q_max = q
1328
1329   
1330        #--------------------------------------------------------------
1331        # Test inundation height again
1332        #--------------------------------------------------------------
1333
1334        indices = domain.get_wet_elements()
1335        z = domain.get_quantity('elevation').\
1336            get_values(location='centroids', indices=indices)
1337
1338        assert alltrue(z<final_runup_height)
1339
1340        q = domain.get_maximum_inundation_elevation()
1341        assert allclose(q, final_runup_height, rtol = 1.0/N) # First order accuracy
1342
1343        q, loc = get_maximum_inundation_data('runup_test.sww', time_interval=[3.0, 3.0])
1344        msg = 'We got %f, should have been %f' %(q, final_runup_height)
1345        assert allclose(q, final_runup_height, rtol=1.0/N), msg
1346        #print 'loc', loc, q       
1347        assert allclose(-loc[0]/2, q) # From topography formula         
1348
1349        q = get_maximum_inundation_elevation('runup_test.sww')
1350        loc = get_maximum_inundation_location('runup_test.sww')       
1351        msg = 'We got %f, should have been %f' %(q, q_max)
1352        assert allclose(q, q_max, rtol=1.0/N), msg
1353        #print 'loc', loc, q
1354        assert allclose(-loc[0]/2, q) # From topography formula
1355
1356       
1357
1358        q = get_maximum_inundation_elevation('runup_test.sww', time_interval=[0, 3])
1359        msg = 'We got %f, should have been %f' %(q, q_max)
1360        assert allclose(q, q_max, rtol=1.0/N), msg
1361
1362
1363        # Check polygon mode
1364        polygon = [[0.3, 0.0], [0.9, 0.0], [0.9, 1.0], [0.3, 1.0]] # Runup region
1365        q = get_maximum_inundation_elevation('runup_test.sww',
1366                                             polygon = polygon,
1367                                             time_interval=[0, 3])
1368        msg = 'We got %f, should have been %f' %(q, q_max)
1369        assert allclose(q, q_max, rtol=1.0/N), msg
1370
1371       
1372        polygon = [[0.9, 0.0], [1.0, 0.0], [1.0, 1.0], [0.9, 1.0]] # Offshore region
1373        q, loc = get_maximum_inundation_data('runup_test.sww',
1374                                             polygon = polygon,
1375                                             time_interval=[0, 3])
1376        msg = 'We got %f, should have been %f' %(q, -0.475)
1377        assert allclose(q, -0.475, rtol=1.0/N), msg
1378        assert is_inside_polygon(loc, polygon)
1379        assert allclose(-loc[0]/2, q) # From topography formula         
1380
1381
1382        polygon = [[0.0, 0.0], [0.4, 0.0], [0.4, 1.0], [0.0, 1.0]] # Dry region
1383        q, loc = get_maximum_inundation_data('runup_test.sww',
1384                                             polygon = polygon,
1385                                             time_interval=[0, 3])
1386        msg = 'We got %s, should have been None' %(q)
1387        assert q is None, msg
1388        msg = 'We got %s, should have been None' %(loc)
1389        assert loc is None, msg       
1390
1391        # Check what happens if no time point is within interval
1392        try:
1393            q = get_maximum_inundation_elevation('runup_test.sww', time_interval=[2.75, 2.75])
1394        except AssertionError:
1395            pass
1396        else:
1397            msg = 'Time interval should have raised an exception'
1398            raise msg
1399
1400        # Cleanup
1401        try:
1402            os.remove(domain.get_name() + '.' + domain.format)
1403        except:
1404            pass
1405            #FIXME(Ole): Windows won't allow removal of this
1406           
1407       
1408       
1409    def test_get_flow_through_cross_section_with_geo(self):
1410        """test_get_flow_through_cross_section(self):
1411
1412        Test that the total flow through a cross section can be
1413        correctly obtained at run-time from the ANUGA domain.
1414       
1415        This test creates a flat bed with a known flow through it and tests
1416        that the function correctly returns the expected flow.
1417
1418        The specifics are
1419        e = -1 m
1420        u = 2 m/s
1421        h = 2 m
1422        w = 3 m (width of channel)
1423
1424        q = u*h*w = 12 m^3/s
1425
1426
1427        This run tries it with georeferencing and with elevation = -1
1428       
1429        """
1430
1431        import time, os
1432        from Numeric import array, zeros, allclose, Float, concatenate
1433        from Scientific.IO.NetCDF import NetCDFFile
1434
1435        # Setup
1436        from mesh_factory import rectangular
1437
1438        # Create basic mesh (20m x 3m)
1439        width = 3
1440        length = 20
1441        t_end = 1
1442        points, vertices, boundary = rectangular(length, width,
1443                                                 length, width)
1444
1445        # Create shallow water domain
1446        domain = Domain(points, vertices, boundary,
1447                        geo_reference=Geo_reference(56,308500,6189000))
1448
1449        domain.default_order = 2
1450        domain.set_quantities_to_be_stored(None)
1451
1452
1453        e = -1.0
1454        w = 1.0
1455        h = w-e
1456        u = 2.0
1457        uh = u*h
1458
1459        Br = Reflective_boundary(domain)     # Side walls
1460        Bd = Dirichlet_boundary([w, uh, 0])  # 2 m/s across the 3 m inlet:
1461
1462
1463        # Initial conditions
1464        domain.set_quantity('elevation', e)
1465        domain.set_quantity('stage', w)
1466        domain.set_quantity('xmomentum', uh)
1467        domain.set_boundary( {'left': Bd, 'right': Bd, 'top': Br, 'bottom': Br})
1468       
1469       
1470        # Interpolation points down the middle
1471        I = [[0, width/2.],
1472             [length/2., width/2.],
1473             [length, width/2.]]
1474        interpolation_points = domain.geo_reference.get_absolute(I)       
1475       
1476        # Shortcuts to quantites
1477        stage = domain.get_quantity('stage')       
1478        xmomentum = domain.get_quantity('xmomentum')       
1479        ymomentum = domain.get_quantity('ymomentum')               
1480
1481        for t in domain.evolve(yieldstep=0.1, finaltime = t_end):
1482            # Check that quantities are they should be in the interior
1483
1484            w_t = stage.get_values(interpolation_points)           
1485            uh_t = xmomentum.get_values(interpolation_points)
1486            vh_t = ymomentum.get_values(interpolation_points)           
1487           
1488            assert allclose(w_t, w)
1489            assert allclose(uh_t, uh)           
1490            assert allclose(vh_t, 0.0)                       
1491           
1492           
1493            # Check flows through the middle
1494            for i in range(5):
1495                x = length/2. + i*0.23674563 # Arbitrary
1496                cross_section = [[x, 0], [x, width]]
1497
1498                cross_section = domain.geo_reference.get_absolute(cross_section)           
1499                Q = domain.get_flow_through_cross_section(cross_section,
1500                                                          verbose=False)
1501
1502                assert allclose(Q, uh*width)
1503
1504
1505       
1506    def test_get_energy_through_cross_section_with_geo(self):
1507        """test_get_energy_through_cross_section(self):
1508
1509        Test that the total and specific energy through a cross section can be
1510        correctly obtained at run-time from the ANUGA domain.
1511       
1512        This test creates a flat bed with a known flow through it and tests
1513        that the function correctly returns the expected energies.
1514
1515        The specifics are
1516        e = -1 m
1517        u = 2 m/s
1518        h = 2 m
1519        w = 3 m (width of channel)
1520
1521        q = u*h*w = 12 m^3/s
1522
1523
1524        This run tries it with georeferencing and with elevation = -1
1525       
1526        """
1527
1528        import time, os
1529        from Numeric import array, zeros, allclose, Float, concatenate
1530        from Scientific.IO.NetCDF import NetCDFFile
1531
1532        # Setup
1533        from mesh_factory import rectangular
1534
1535        # Create basic mesh (20m x 3m)
1536        width = 3
1537        length = 20
1538        t_end = 1
1539        points, vertices, boundary = rectangular(length, width,
1540                                                 length, width)
1541
1542        # Create shallow water domain
1543        domain = Domain(points, vertices, boundary,
1544                        geo_reference=Geo_reference(56,308500,6189000))
1545
1546        domain.default_order = 2
1547        domain.set_quantities_to_be_stored(None)
1548
1549
1550        e = -1.0
1551        w = 1.0
1552        h = w-e
1553        u = 2.0
1554        uh = u*h
1555
1556        Br = Reflective_boundary(domain)     # Side walls
1557        Bd = Dirichlet_boundary([w, uh, 0])  # 2 m/s across the 3 m inlet:
1558
1559
1560        # Initial conditions
1561        domain.set_quantity('elevation', e)
1562        domain.set_quantity('stage', w)
1563        domain.set_quantity('xmomentum', uh)
1564        domain.set_boundary( {'left': Bd, 'right': Bd, 'top': Br, 'bottom': Br})
1565       
1566       
1567        # Interpolation points down the middle
1568        I = [[0, width/2.],
1569             [length/2., width/2.],
1570             [length, width/2.]]
1571        interpolation_points = domain.geo_reference.get_absolute(I)       
1572       
1573        # Shortcuts to quantites
1574        stage = domain.get_quantity('stage')       
1575        xmomentum = domain.get_quantity('xmomentum')       
1576        ymomentum = domain.get_quantity('ymomentum')               
1577
1578        for t in domain.evolve(yieldstep=0.1, finaltime = t_end):
1579            # Check that quantities are they should be in the interior
1580
1581            w_t = stage.get_values(interpolation_points)           
1582            uh_t = xmomentum.get_values(interpolation_points)
1583            vh_t = ymomentum.get_values(interpolation_points)           
1584           
1585            assert allclose(w_t, w)
1586            assert allclose(uh_t, uh)           
1587            assert allclose(vh_t, 0.0)                       
1588           
1589           
1590            # Check energies through the middle
1591            for i in range(5):
1592                x = length/2. + i*0.23674563 # Arbitrary
1593                cross_section = [[x, 0], [x, width]]
1594
1595                cross_section = domain.geo_reference.get_absolute(cross_section)   
1596                Es = domain.get_energy_through_cross_section(cross_section,
1597                                                             kind='specific',
1598                                                             verbose=False)
1599                                                     
1600                assert allclose(Es, h + 0.5*u*u/g)
1601           
1602                Et = domain.get_energy_through_cross_section(cross_section,
1603                                                             kind='total',
1604                                                             verbose=False)
1605                assert allclose(Et, w + 0.5*u*u/g)           
1606
1607           
1608       
1609       
1610
1611    def test_another_runup_example(self):
1612        """test_another_runup_example
1613
1614        Test runup example where actual timeseries at interpolated
1615        points are tested.
1616        """
1617
1618        #-----------------------------------------------------------------
1619        # Import necessary modules
1620        #-----------------------------------------------------------------
1621
1622        from anuga.pmesh.mesh_interface import create_mesh_from_regions
1623        from anuga.abstract_2d_finite_volumes.mesh_factory import rectangular_cross
1624        from anuga.shallow_water import Domain
1625        from anuga.shallow_water import Reflective_boundary
1626        from anuga.shallow_water import Dirichlet_boundary
1627
1628
1629        #-----------------------------------------------------------------
1630        # Setup computational domain
1631        #-----------------------------------------------------------------
1632        points, vertices, boundary = rectangular_cross(10, 10) # Basic mesh
1633        domain = Domain(points, vertices, boundary) # Create domain
1634        domain.set_quantities_to_be_stored(None)
1635        domain.set_maximum_allowed_speed(100) #FIXME (Ole): try to remove this
1636       
1637        # FIXME (Ole): Need tests where this is commented out
1638        domain.tight_slope_limiters = 0 # Backwards compatibility (14/4/7)
1639        domain.H0 = 0 # Backwards compatibility (6/2/7)
1640        domain.use_centroid_velocities = 0 # Backwards compatibility (7/5/8)
1641       
1642
1643        #-----------------------------------------------------------------
1644        # Setup initial conditions
1645        #-----------------------------------------------------------------
1646
1647        def topography(x,y): 
1648            return -x/2                              # linear bed slope
1649
1650        domain.set_quantity('elevation', topography) 
1651        domain.set_quantity('friction', 0.0)         
1652        domain.set_quantity('stage', expression='elevation')           
1653
1654
1655        #----------------------------------------------------------------
1656        # Setup boundary conditions
1657        #----------------------------------------------------------------
1658
1659        Br = Reflective_boundary(domain)      # Solid reflective wall
1660        Bd = Dirichlet_boundary([-0.2,0.,0.]) # Constant boundary values
1661        domain.set_boundary({'left': Br, 'right': Bd, 'top': Br, 'bottom': Br})
1662
1663
1664        #----------------------------------------------------------------
1665        # Evolve system through time
1666        #----------------------------------------------------------------
1667
1668        interpolation_points = [[0.4,0.5], [0.6,0.5], [0.8,0.5], [0.9,0.5]]
1669        gauge_values = []
1670        for _ in interpolation_points:
1671            gauge_values.append([])
1672
1673        time = []
1674        for t in domain.evolve(yieldstep = 0.1, finaltime = 5.0):
1675            # Record time series at known points
1676            time.append(domain.get_time())
1677           
1678            stage = domain.get_quantity('stage')
1679            w = stage.get_values(interpolation_points=interpolation_points)
1680           
1681            for i, _ in enumerate(interpolation_points):
1682                gauge_values[i].append(w[i])
1683
1684
1685        #print
1686        #print time
1687        #print
1688        #for i, (x,y) in enumerate(interpolation_points):
1689        #    print i, gauge_values[i]
1690        #    print
1691
1692        #Reference (nautilus 26/6/2008)
1693       
1694        G0 = [-0.20000000000000001, -0.20000000000000001, -0.19920600846161715, -0.19153647344085376, -0.19127622768281194, -0.1770671909675095, -0.16739412133181927, -0.16196038919122191, -0.15621633053131384, -0.15130021599977705, -0.13930978857215484, -0.19349274358263582, -0.19975307598803765, -0.19999897143103357, -0.1999999995532111, -0.19999999999949952, -0.19999999999949952, -0.19999999999949952, -0.19997270012494556, -0.19925805948554556, -0.19934513778450533, -0.19966484196394893, -0.1997352860102084, -0.19968260481750394, -0.19980280797303882, -0.19998804881822749, -0.19999999778075916, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167, -0.19999999999966167]
1695
1696        G1 = [-0.29999999999999993, -0.29999588068034899, -0.29250047332330331, -0.28335081844518584, -0.26142206997410805, -0.22656028856329835, -0.21224087216745585, -0.19934324109114465, -0.1889857939783175, -0.18146311603911383, -0.17401078727434263, -0.15419361061257214, -0.16225060576782063, -0.19010941396999181, -0.20901161407004412, -0.21670683975774699, -0.21771386270738891, -0.21481284465869752, -0.21063120869004387, -0.20669243364582401, -0.20320707386714859, -0.19984087691926442, -0.19725417448019505, -0.19633783049069981, -0.19650494599999785, -0.19708316838336942, -0.19779309449413818, -0.19853070294429562, -0.19917342167307153, -0.19964814677795845, -0.19991627610824922, -0.20013162970144974, -0.20029864969405509, -0.20036259676501131, -0.20030682824965193, -0.20016105135750167, -0.19997664501985918, -0.19980185871568762, -0.19966836175417696, -0.19958856744312226, -0.19955954696194517, -0.19956950051110917, -0.19960377086336181, -0.19964885299433241, -0.19969427478531132, -0.19973301547655564, -0.19976121574277764, -0.19977765285688653, -0.19978315117522441, -0.19977994634841739, -0.19977101394878494]
1697       
1698        G2 = [-0.40000000000000002, -0.39077401254732241, -0.33350466136630474, -0.29771023004255281, -0.27605439066140897, -0.25986156218997497, -0.24502185018573647, -0.231792624329521, -0.21981564668803993, -0.20870707082936543, -0.19877739883776599, -0.18980922837977957, -0.17308011674005838, -0.16306400164013773, -0.17798470933304333, -0.1929554075869116, -0.20236705191987037, -0.20695767560655007, -0.20841025876092567, -0.20792102174869989, -0.20655350005579293, -0.20492002526259828, -0.20310627026780645, -0.20105983335287836, -0.19937394565794653, -0.19853917506699659, -0.19836389977624452, -0.19850305023602796, -0.19877764028836831, -0.19910928131034669, -0.19943705712418805, -0.19970344172958865, -0.19991076989870474, -0.20010020127747646, -0.20025937787100062, -0.20035087292905965, -0.20035829921463297, -0.20029606557316171, -0.20019606915365515, -0.20009096093399206, -0.20000371608204368, -0.19994495432920584, -0.19991535665176338, -0.19990981826533513, -0.19992106419898723, -0.19994189853516578, -0.19996624091229293, -0.19998946016985167, -0.20000842303470234, -0.20002144460718174, -0.20002815561337187]
1699       
1700        G3 = [-0.45000000000000001, -0.37631169657400332, -0.33000044342859486, -0.30586045469008522, -0.28843572253009941, -0.27215308978603808, -0.25712951540331219, -0.2431608296216613, -0.23032023651386374, -0.2184546873456619, -0.20735123704254332, -0.19740397194806389, -0.1859829564064375, -0.16675980728362105, -0.16951575032846536, -0.1832860872609344, -0.19485758939241243, -0.20231368291811427, -0.20625610376074754, -0.20758116241495619, -0.20721445402086161, -0.20603406830353785, -0.20450262808396991, -0.2026769581185151, -0.2007401212066364, -0.19931160535777592, -0.19863606301128725, -0.19848511940572691, -0.19860091042948352, -0.19885490669377764, -0.19916542732701112, -0.19946678238611959, -0.19971209594104697, -0.19991912886512292, -0.2001058430788881, -0.20024959409472989, -0.20032160254609382, -0.20031583165752354, -0.20025051539293123, -0.2001556115816068, -0.20005952955420872, -0.1999814429561611, -0.19992977821558131, -0.19990457708664208, -0.19990104785490476, -0.19991257153954825, -0.19993258231880562, -0.19995548502882532, -0.19997700760919687, -0.19999429663503748, -0.20000588800248761]
1701       
1702        #FIXME (DSG):This is a hack so the anuga install, not precompiled
1703        # works on DSG's win2000, python 2.3
1704        #The problem is the gauge_values[X] are 52 long, not 51.
1705        #
1706        # This was probably fixed by Stephen in changeset:3804
1707        #if len(gauge_values[0]) == 52: gauge_values[0].pop()
1708        #if len(gauge_values[1]) == 52: gauge_values[1].pop()
1709        #if len(gauge_values[2]) == 52: gauge_values[2].pop()
1710        #if len(gauge_values[3]) == 52: gauge_values[3].pop()
1711
1712##         print len(G0), len(gauge_values[0])
1713##         print len(G1), len(gauge_values[1])
1714       
1715        #print gauge_values[3]
1716        #print G0[:4]
1717        #print array(gauge_values[0])-array(G0)
1718       
1719       
1720        assert allclose(gauge_values[0], G0)
1721        assert allclose(gauge_values[1], G1)
1722        assert allclose(gauge_values[2], G2)
1723        assert allclose(gauge_values[3], G3)       
1724
1725
1726
1727
1728
1729
1730
1731    #####################################################
1732
1733    def test_flux_optimisation(self):
1734        """test_flux_optimisation
1735        Test that fluxes are correctly computed using
1736        dry and still cell exclusions
1737        """
1738
1739        from anuga.config import g
1740        import copy
1741
1742        a = [0.0, 0.0]
1743        b = [0.0, 2.0]
1744        c = [2.0, 0.0]
1745        d = [0.0, 4.0]
1746        e = [2.0, 2.0]
1747        f = [4.0, 0.0]
1748
1749        points = [a, b, c, d, e, f]
1750        #bac, bce, ecf, dbe
1751        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
1752
1753        domain = Domain(points, vertices)
1754
1755        #Set up for a gradient of (3,0) at mid triangle (bce)
1756        def slope(x, y):
1757            return 3*x
1758
1759        h = 0.1
1760        def stage(x,y):
1761            return slope(x,y)+h
1762
1763        domain.set_quantity('elevation', slope)
1764        domain.set_quantity('stage', stage)
1765
1766        # Allow slope limiters to work (FIXME (Ole): Shouldn't this be automatic in ANUGA?)     
1767        domain.distribute_to_vertices_and_edges()       
1768
1769        initial_stage = copy.copy(domain.quantities['stage'].vertex_values)
1770
1771        domain.set_boundary({'exterior': Reflective_boundary(domain)})
1772
1773
1774        #  Check that update arrays are initialised to zero
1775        assert allclose(domain.get_quantity('stage').explicit_update, 0)
1776        assert allclose(domain.get_quantity('xmomentum').explicit_update, 0)
1777        assert allclose(domain.get_quantity('ymomentum').explicit_update, 0)               
1778
1779
1780        # Get true values
1781        domain.optimise_dry_cells = False
1782        domain.compute_fluxes()
1783        stage_ref = copy.copy(domain.get_quantity('stage').explicit_update)
1784        xmom_ref = copy.copy(domain.get_quantity('xmomentum').explicit_update)
1785        ymom_ref = copy.copy(domain.get_quantity('ymomentum').explicit_update)       
1786
1787        # Try with flux optimisation
1788        domain.optimise_dry_cells = True
1789        domain.compute_fluxes()
1790
1791        assert allclose(stage_ref, domain.get_quantity('stage').explicit_update)
1792        assert allclose(xmom_ref, domain.get_quantity('xmomentum').explicit_update)
1793        assert allclose(ymom_ref, domain.get_quantity('ymomentum').explicit_update)
1794       
1795   
1796       
1797    def test_initial_condition(self):
1798        """test_initial_condition
1799        Test that initial condition is output at time == 0 and that
1800        computed values change as system evolves
1801        """
1802
1803        from anuga.config import g
1804        import copy
1805
1806        a = [0.0, 0.0]
1807        b = [0.0, 2.0]
1808        c = [2.0, 0.0]
1809        d = [0.0, 4.0]
1810        e = [2.0, 2.0]
1811        f = [4.0, 0.0]
1812
1813        points = [a, b, c, d, e, f]
1814        #bac, bce, ecf, dbe
1815        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
1816
1817        domain = Domain(points, vertices)
1818
1819        #Set up for a gradient of (3,0) at mid triangle (bce)
1820        def slope(x, y):
1821            return 3*x
1822
1823        h = 0.1
1824        def stage(x,y):
1825            return slope(x,y)+h
1826
1827        domain.set_quantity('elevation', slope)
1828        domain.set_quantity('stage', stage)
1829
1830        # Allow slope limiters to work (FIXME (Ole): Shouldn't this be automatic in ANUGA?)     
1831        domain.distribute_to_vertices_and_edges()       
1832
1833        initial_stage = copy.copy(domain.quantities['stage'].vertex_values)
1834
1835        domain.set_boundary({'exterior': Reflective_boundary(domain)})
1836
1837        domain.optimise_dry_cells = True
1838        #Evolution
1839        for t in domain.evolve(yieldstep = 0.5, finaltime = 2.0):
1840            stage = domain.quantities['stage'].vertex_values
1841
1842            if t == 0.0:
1843                assert allclose(stage, initial_stage)
1844            else:
1845                assert not allclose(stage, initial_stage)
1846
1847
1848        os.remove(domain.get_name() + '.sww')
1849
1850
1851
1852    #####################################################
1853    def test_gravity(self):
1854        #Assuming no friction
1855
1856        from anuga.config import g
1857
1858        a = [0.0, 0.0]
1859        b = [0.0, 2.0]
1860        c = [2.0, 0.0]
1861        d = [0.0, 4.0]
1862        e = [2.0, 2.0]
1863        f = [4.0, 0.0]
1864
1865        points = [a, b, c, d, e, f]
1866        #bac, bce, ecf, dbe
1867        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
1868
1869        domain = Domain(points, vertices)
1870
1871        #Set up for a gradient of (3,0) at mid triangle (bce)
1872        def slope(x, y):
1873            return 3*x
1874
1875        h = 0.1
1876        def stage(x,y):
1877            return slope(x,y)+h
1878
1879        domain.set_quantity('elevation', slope)
1880        domain.set_quantity('stage', stage)
1881
1882        for name in domain.conserved_quantities:
1883            assert allclose(domain.quantities[name].explicit_update, 0)
1884            assert allclose(domain.quantities[name].semi_implicit_update, 0)
1885
1886        domain.compute_forcing_terms()
1887
1888        assert allclose(domain.quantities['stage'].explicit_update, 0)
1889        assert allclose(domain.quantities['xmomentum'].explicit_update, -g*h*3)
1890        assert allclose(domain.quantities['ymomentum'].explicit_update, 0)
1891
1892
1893    def test_manning_friction(self):
1894        from anuga.config import g
1895
1896        a = [0.0, 0.0]
1897        b = [0.0, 2.0]
1898        c = [2.0, 0.0]
1899        d = [0.0, 4.0]
1900        e = [2.0, 2.0]
1901        f = [4.0, 0.0]
1902
1903        points = [a, b, c, d, e, f]
1904        #bac, bce, ecf, dbe
1905        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
1906
1907        domain = Domain(points, vertices)
1908
1909        #Set up for a gradient of (3,0) at mid triangle (bce)
1910        def slope(x, y):
1911            return 3*x
1912
1913        h = 0.1
1914        def stage(x,y):
1915            return slope(x,y)+h
1916
1917        eta = 0.07
1918        domain.set_quantity('elevation', slope)
1919        domain.set_quantity('stage', stage)
1920        domain.set_quantity('friction', eta)
1921
1922        for name in domain.conserved_quantities:
1923            assert allclose(domain.quantities[name].explicit_update, 0)
1924            assert allclose(domain.quantities[name].semi_implicit_update, 0)
1925
1926        domain.compute_forcing_terms()
1927
1928        assert allclose(domain.quantities['stage'].explicit_update, 0)
1929        assert allclose(domain.quantities['xmomentum'].explicit_update, -g*h*3)
1930        assert allclose(domain.quantities['ymomentum'].explicit_update, 0)
1931
1932        assert allclose(domain.quantities['stage'].semi_implicit_update, 0)
1933        assert allclose(domain.quantities['xmomentum'].semi_implicit_update, 0)
1934        assert allclose(domain.quantities['ymomentum'].semi_implicit_update, 0)
1935
1936        #Create some momentum for friction to work with
1937        domain.set_quantity('xmomentum', 1)
1938        S = -g * eta**2 / h**(7.0/3)
1939
1940        domain.compute_forcing_terms()
1941        assert allclose(domain.quantities['stage'].semi_implicit_update, 0)
1942        assert allclose(domain.quantities['xmomentum'].semi_implicit_update, S)
1943        assert allclose(domain.quantities['ymomentum'].semi_implicit_update, 0)
1944
1945        #A more complex example
1946        domain.quantities['stage'].semi_implicit_update[:] = 0.0
1947        domain.quantities['xmomentum'].semi_implicit_update[:] = 0.0
1948        domain.quantities['ymomentum'].semi_implicit_update[:] = 0.0
1949
1950        domain.set_quantity('xmomentum', 3)
1951        domain.set_quantity('ymomentum', 4)
1952
1953        S = -g * eta**2 * 5 / h**(7.0/3)
1954
1955
1956        domain.compute_forcing_terms()
1957
1958        assert allclose(domain.quantities['stage'].semi_implicit_update, 0)
1959        assert allclose(domain.quantities['xmomentum'].semi_implicit_update, 3*S)
1960        assert allclose(domain.quantities['ymomentum'].semi_implicit_update, 4*S)
1961
1962    def test_constant_wind_stress(self):
1963        from anuga.config import rho_a, rho_w, eta_w
1964        from math import pi, cos, sin
1965
1966        a = [0.0, 0.0]
1967        b = [0.0, 2.0]
1968        c = [2.0, 0.0]
1969        d = [0.0, 4.0]
1970        e = [2.0, 2.0]
1971        f = [4.0, 0.0]
1972
1973        points = [a, b, c, d, e, f]
1974        #bac, bce, ecf, dbe
1975        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
1976
1977
1978        domain = Domain(points, vertices)
1979
1980        #Flat surface with 1m of water
1981        domain.set_quantity('elevation', 0)
1982        domain.set_quantity('stage', 1.0)
1983        domain.set_quantity('friction', 0)
1984
1985        Br = Reflective_boundary(domain)
1986        domain.set_boundary({'exterior': Br})
1987
1988        #Setup only one forcing term, constant wind stress
1989        s = 100
1990        phi = 135
1991        domain.forcing_terms = []
1992        domain.forcing_terms.append( Wind_stress(s, phi) )
1993
1994        domain.compute_forcing_terms()
1995
1996
1997        const = eta_w*rho_a/rho_w
1998
1999        #Convert to radians
2000        phi = phi*pi/180
2001
2002        #Compute velocity vector (u, v)
2003        u = s*cos(phi)
2004        v = s*sin(phi)
2005
2006        #Compute wind stress
2007        S = const * sqrt(u**2 + v**2)
2008
2009        assert allclose(domain.quantities['stage'].explicit_update, 0)
2010        assert allclose(domain.quantities['xmomentum'].explicit_update, S*u)
2011        assert allclose(domain.quantities['ymomentum'].explicit_update, S*v)
2012
2013
2014    def test_variable_wind_stress(self):
2015        from anuga.config import rho_a, rho_w, eta_w
2016        from math import pi, cos, sin
2017
2018        a = [0.0, 0.0]
2019        b = [0.0, 2.0]
2020        c = [2.0, 0.0]
2021        d = [0.0, 4.0]
2022        e = [2.0, 2.0]
2023        f = [4.0, 0.0]
2024
2025        points = [a, b, c, d, e, f]
2026        #bac, bce, ecf, dbe
2027        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2028
2029        domain = Domain(points, vertices)
2030
2031        #Flat surface with 1m of water
2032        domain.set_quantity('elevation', 0)
2033        domain.set_quantity('stage', 1.0)
2034        domain.set_quantity('friction', 0)
2035
2036        Br = Reflective_boundary(domain)
2037        domain.set_boundary({'exterior': Br})
2038
2039
2040        domain.time = 5.54 #Take a random time (not zero)
2041
2042        #Setup only one forcing term, constant wind stress
2043        s = 100
2044        phi = 135
2045        domain.forcing_terms = []
2046        domain.forcing_terms.append( Wind_stress(s = speed, phi = angle) )
2047
2048        domain.compute_forcing_terms()
2049
2050        #Compute reference solution
2051        const = eta_w*rho_a/rho_w
2052
2053        N = len(domain) # number_of_triangles
2054
2055        xc = domain.get_centroid_coordinates()
2056        t = domain.time
2057
2058        x = xc[:,0]
2059        y = xc[:,1]
2060        s_vec = speed(t,x,y)
2061        phi_vec = angle(t,x,y)
2062
2063
2064        for k in range(N):
2065            #Convert to radians
2066            phi = phi_vec[k]*pi/180
2067            s = s_vec[k]
2068
2069            #Compute velocity vector (u, v)
2070            u = s*cos(phi)
2071            v = s*sin(phi)
2072
2073            #Compute wind stress
2074            S = const * sqrt(u**2 + v**2)
2075
2076            assert allclose(domain.quantities['stage'].explicit_update[k], 0)
2077            assert allclose(domain.quantities['xmomentum'].explicit_update[k], S*u)
2078            assert allclose(domain.quantities['ymomentum'].explicit_update[k], S*v)
2079
2080
2081
2082
2083
2084
2085    def test_windfield_from_file(self):
2086        from anuga.config import rho_a, rho_w, eta_w
2087        from math import pi, cos, sin
2088        from anuga.config import time_format
2089        from anuga.abstract_2d_finite_volumes.util import file_function
2090        import time
2091
2092
2093        a = [0.0, 0.0]
2094        b = [0.0, 2.0]
2095        c = [2.0, 0.0]
2096        d = [0.0, 4.0]
2097        e = [2.0, 2.0]
2098        f = [4.0, 0.0]
2099
2100        points = [a, b, c, d, e, f]
2101        #bac, bce, ecf, dbe
2102        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2103
2104        domain = Domain(points, vertices)
2105
2106        #Flat surface with 1m of water
2107        domain.set_quantity('elevation', 0)
2108        domain.set_quantity('stage', 1.0)
2109        domain.set_quantity('friction', 0)
2110
2111        Br = Reflective_boundary(domain)
2112        domain.set_boundary({'exterior': Br})
2113
2114
2115        domain.time = 7 #Take a time that is represented in file (not zero)
2116
2117        #Write wind stress file (ensure that domain.time is covered)
2118        #Take x=1 and y=0
2119        filename = 'test_windstress_from_file'
2120        start = time.mktime(time.strptime('2000', '%Y'))
2121        fid = open(filename + '.txt', 'w')
2122        dt = 1  #One second interval
2123        t = 0.0
2124        while t <= 10.0:
2125            t_string = time.strftime(time_format, time.gmtime(t+start))
2126
2127            fid.write('%s, %f %f\n' %(t_string,
2128                                      speed(t,[1],[0])[0],
2129                                      angle(t,[1],[0])[0]))
2130            t += dt
2131
2132        fid.close()
2133
2134
2135        #Convert ASCII file to NetCDF (Which is what we really like!)
2136        from data_manager import timefile2netcdf       
2137        timefile2netcdf(filename)
2138        os.remove(filename + '.txt')
2139
2140       
2141        #Setup wind stress
2142        F = file_function(filename + '.tms', quantities = ['Attribute0',
2143                                                           'Attribute1'])
2144        os.remove(filename + '.tms')
2145       
2146
2147        #print 'F(5)', F(5)
2148
2149        #print 'F(5,x,y)', F(5,x=zeros(3),y=zeros(3))
2150       
2151        #print dir(F)
2152        #print F.T
2153        #print F.precomputed_values
2154        #
2155        #F = file_function(filename + '.txt')       
2156        #
2157        #print dir(F)
2158        #print F.T       
2159        #print F.Q
2160       
2161        W = Wind_stress(F)
2162
2163        domain.forcing_terms = []
2164        domain.forcing_terms.append(W)
2165
2166        domain.compute_forcing_terms()
2167
2168        #Compute reference solution
2169        const = eta_w*rho_a/rho_w
2170
2171        N = len(domain) # number_of_triangles
2172
2173        t = domain.time
2174
2175        s = speed(t,[1],[0])[0]
2176        phi = angle(t,[1],[0])[0]
2177
2178        #Convert to radians
2179        phi = phi*pi/180
2180
2181
2182        #Compute velocity vector (u, v)
2183        u = s*cos(phi)
2184        v = s*sin(phi)
2185
2186        #Compute wind stress
2187        S = const * sqrt(u**2 + v**2)
2188
2189        for k in range(N):
2190            assert allclose(domain.quantities['stage'].explicit_update[k], 0)
2191            assert allclose(domain.quantities['xmomentum'].explicit_update[k], S*u)
2192            assert allclose(domain.quantities['ymomentum'].explicit_update[k], S*v)
2193
2194
2195    def test_windfield_from_file_seconds(self):
2196        from anuga.config import rho_a, rho_w, eta_w
2197        from math import pi, cos, sin
2198        from anuga.config import time_format
2199        from anuga.abstract_2d_finite_volumes.util import file_function
2200        import time
2201
2202
2203        a = [0.0, 0.0]
2204        b = [0.0, 2.0]
2205        c = [2.0, 0.0]
2206        d = [0.0, 4.0]
2207        e = [2.0, 2.0]
2208        f = [4.0, 0.0]
2209
2210        points = [a, b, c, d, e, f]
2211        #bac, bce, ecf, dbe
2212        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2213
2214        domain = Domain(points, vertices)
2215
2216        #Flat surface with 1m of water
2217        domain.set_quantity('elevation', 0)
2218        domain.set_quantity('stage', 1.0)
2219        domain.set_quantity('friction', 0)
2220
2221        Br = Reflective_boundary(domain)
2222        domain.set_boundary({'exterior': Br})
2223
2224
2225        domain.time = 7 #Take a time that is represented in file (not zero)
2226
2227        #Write wind stress file (ensure that domain.time is covered)
2228        #Take x=1 and y=0
2229        filename = 'test_windstress_from_file'
2230        start = time.mktime(time.strptime('2000', '%Y'))
2231        fid = open(filename + '.txt', 'w')
2232        dt = 0.5 #1  #One second interval
2233        t = 0.0
2234        while t <= 10.0:
2235            fid.write('%s, %f %f\n' %(str(t),
2236                                      speed(t,[1],[0])[0],
2237                                      angle(t,[1],[0])[0]))
2238            t += dt
2239
2240        fid.close()
2241
2242
2243        #Convert ASCII file to NetCDF (Which is what we really like!)
2244        from data_manager import timefile2netcdf       
2245        timefile2netcdf(filename, time_as_seconds=True)
2246        os.remove(filename + '.txt')
2247
2248       
2249        #Setup wind stress
2250        F = file_function(filename + '.tms', quantities = ['Attribute0',
2251                                                           'Attribute1'])
2252        os.remove(filename + '.tms')
2253       
2254
2255        #print 'F(5)', F(5)
2256
2257        #print 'F(5,x,y)', F(5,x=zeros(3),y=zeros(3))
2258       
2259        #print dir(F)
2260        #print F.T
2261        #print F.precomputed_values
2262        #
2263        #F = file_function(filename + '.txt')       
2264        #
2265        #print dir(F)
2266        #print F.T       
2267        #print F.Q
2268       
2269        W = Wind_stress(F)
2270
2271        domain.forcing_terms = []
2272        domain.forcing_terms.append(W)
2273
2274        domain.compute_forcing_terms()
2275
2276        #Compute reference solution
2277        const = eta_w*rho_a/rho_w
2278
2279        N = len(domain) # number_of_triangles
2280
2281        t = domain.time
2282
2283        s = speed(t,[1],[0])[0]
2284        phi = angle(t,[1],[0])[0]
2285
2286        #Convert to radians
2287        phi = phi*pi/180
2288
2289
2290        #Compute velocity vector (u, v)
2291        u = s*cos(phi)
2292        v = s*sin(phi)
2293
2294        #Compute wind stress
2295        S = const * sqrt(u**2 + v**2)
2296
2297        for k in range(N):
2298            assert allclose(domain.quantities['stage'].explicit_update[k], 0)
2299            assert allclose(domain.quantities['xmomentum'].explicit_update[k], S*u)
2300            assert allclose(domain.quantities['ymomentum'].explicit_update[k], S*v)
2301
2302
2303       
2304
2305    def test_wind_stress_error_condition(self):
2306        """Test that windstress reacts properly when forcing functions
2307        are wrong - e.g. returns a scalar
2308        """
2309
2310        from anuga.config import rho_a, rho_w, eta_w
2311        from math import pi, cos, sin
2312
2313        a = [0.0, 0.0]
2314        b = [0.0, 2.0]
2315        c = [2.0, 0.0]
2316        d = [0.0, 4.0]
2317        e = [2.0, 2.0]
2318        f = [4.0, 0.0]
2319
2320        points = [a, b, c, d, e, f]
2321        #bac, bce, ecf, dbe
2322        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2323
2324        domain = Domain(points, vertices)
2325
2326        #Flat surface with 1m of water
2327        domain.set_quantity('elevation', 0)
2328        domain.set_quantity('stage', 1.0)
2329        domain.set_quantity('friction', 0)
2330
2331        Br = Reflective_boundary(domain)
2332        domain.set_boundary({'exterior': Br})
2333
2334
2335        domain.time = 5.54 #Take a random time (not zero)
2336
2337        #Setup only one forcing term, bad func
2338        domain.forcing_terms = []
2339
2340        try:
2341            domain.forcing_terms.append(Wind_stress(s = scalar_func,
2342                                                    phi = angle))
2343        except AssertionError:
2344            pass
2345        else:
2346            msg = 'Should have raised exception'
2347            raise msg
2348
2349
2350        try:
2351            domain.forcing_terms.append(Wind_stress(s = speed,
2352                                                    phi = scalar_func))
2353        except AssertionError:
2354            pass
2355        else:
2356            msg = 'Should have raised exception'
2357            raise msg
2358
2359        try:
2360            domain.forcing_terms.append(Wind_stress(s = speed,
2361                                                    phi = 'xx'))
2362        except:
2363            pass
2364        else:
2365            msg = 'Should have raised exception'
2366            raise msg
2367
2368
2369
2370    def test_rainfall(self):
2371        from math import pi, cos, sin
2372
2373        a = [0.0, 0.0]
2374        b = [0.0, 2.0]
2375        c = [2.0, 0.0]
2376        d = [0.0, 4.0]
2377        e = [2.0, 2.0]
2378        f = [4.0, 0.0]
2379
2380        points = [a, b, c, d, e, f]
2381        #bac, bce, ecf, dbe
2382        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2383
2384
2385        domain = Domain(points, vertices)
2386
2387        #Flat surface with 1m of water
2388        domain.set_quantity('elevation', 0)
2389        domain.set_quantity('stage', 1.0)
2390        domain.set_quantity('friction', 0)
2391
2392        Br = Reflective_boundary(domain)
2393        domain.set_boundary({'exterior': Br})
2394
2395        # Setup only one forcing term, constant rainfall
2396        domain.forcing_terms = []
2397        domain.forcing_terms.append( Rainfall(domain, rate=2.0) )
2398
2399        domain.compute_forcing_terms()
2400        assert allclose(domain.quantities['stage'].explicit_update, 2.0/1000)
2401
2402
2403        # FIXME: Do Time dependent rainfall
2404
2405
2406
2407    def test_rainfall_restricted_by_polygon(self):
2408        from math import pi, cos, sin
2409
2410        a = [0.0, 0.0]
2411        b = [0.0, 2.0]
2412        c = [2.0, 0.0]
2413        d = [0.0, 4.0]
2414        e = [2.0, 2.0]
2415        f = [4.0, 0.0]
2416
2417        points = [a, b, c, d, e, f]
2418        #bac, bce, ecf, dbe
2419        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2420
2421
2422        domain = Domain(points, vertices)
2423
2424        #Flat surface with 1m of water
2425        domain.set_quantity('elevation', 0)
2426        domain.set_quantity('stage', 1.0)
2427        domain.set_quantity('friction', 0)
2428
2429        Br = Reflective_boundary(domain)
2430        domain.set_boundary({'exterior': Br})
2431
2432        # Setup only one forcing term, constant rainfall restricted to a polygon enclosing triangle #1 (bce)
2433        domain.forcing_terms = []
2434        R = Rainfall(domain, rate=2.0, polygon = [[1,1], [2,1], [2,2], [1,2]])
2435
2436        assert allclose(R.exchange_area, 1)
2437       
2438        domain.forcing_terms.append(R)
2439
2440        domain.compute_forcing_terms()
2441        #print domain.quantities['stage'].explicit_update
2442       
2443        assert allclose(domain.quantities['stage'].explicit_update[1], 2.0/1000)
2444        assert allclose(domain.quantities['stage'].explicit_update[0], 0)
2445        assert allclose(domain.quantities['stage'].explicit_update[2:], 0)       
2446       
2447        # FIXME: Do Time dependent rainfall with poly
2448
2449
2450
2451
2452    def test_inflow_using_circle(self):
2453        from math import pi, cos, sin
2454
2455        a = [0.0, 0.0]
2456        b = [0.0, 2.0]
2457        c = [2.0, 0.0]
2458        d = [0.0, 4.0]
2459        e = [2.0, 2.0]
2460        f = [4.0, 0.0]
2461
2462        points = [a, b, c, d, e, f]
2463        #bac, bce, ecf, dbe
2464        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2465
2466
2467        domain = Domain(points, vertices)
2468
2469        # Flat surface with 1m of water
2470        domain.set_quantity('elevation', 0)
2471        domain.set_quantity('stage', 1.0)
2472        domain.set_quantity('friction', 0)
2473
2474        Br = Reflective_boundary(domain)
2475        domain.set_boundary({'exterior': Br})
2476
2477        # Setup only one forcing term, constant inflow of 2 m^3/s on a circle affecting triangles #0 and #1 (bac and bce)
2478        domain.forcing_terms = []
2479        domain.forcing_terms.append( Inflow(domain, rate=2.0, center=(1,1), radius=1) )
2480
2481        domain.compute_forcing_terms()
2482        #print domain.quantities['stage'].explicit_update
2483       
2484        assert allclose(domain.quantities['stage'].explicit_update[1], 2.0/pi)
2485        assert allclose(domain.quantities['stage'].explicit_update[0], 2.0/pi)
2486        assert allclose(domain.quantities['stage'].explicit_update[2:], 0)       
2487
2488
2489    def test_inflow_using_circle_function(self):
2490        from math import pi, cos, sin
2491
2492        a = [0.0, 0.0]
2493        b = [0.0, 2.0]
2494        c = [2.0, 0.0]
2495        d = [0.0, 4.0]
2496        e = [2.0, 2.0]
2497        f = [4.0, 0.0]
2498
2499        points = [a, b, c, d, e, f]
2500        #bac, bce, ecf, dbe
2501        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2502
2503
2504        domain = Domain(points, vertices)
2505
2506        # Flat surface with 1m of water
2507        domain.set_quantity('elevation', 0)
2508        domain.set_quantity('stage', 1.0)
2509        domain.set_quantity('friction', 0)
2510
2511        Br = Reflective_boundary(domain)
2512        domain.set_boundary({'exterior': Br})
2513
2514        # Setup only one forcing term, time dependent inflow of 2 m^3/s on a circle affecting triangles #0 and #1 (bac and bce)
2515        domain.forcing_terms = []
2516        domain.forcing_terms.append( Inflow(domain, rate=lambda t: 2., center=(1,1), radius=1) )
2517
2518        domain.compute_forcing_terms()
2519       
2520        assert allclose(domain.quantities['stage'].explicit_update[1], 2.0/pi)
2521        assert allclose(domain.quantities['stage'].explicit_update[0], 2.0/pi)
2522        assert allclose(domain.quantities['stage'].explicit_update[2:], 0)       
2523       
2524
2525
2526
2527    def test_inflow_catch_too_few_triangles(self):
2528        """test_inflow_catch_too_few_triangles
2529       
2530        Test that exception is thrown if no triangles are covered by the inflow area
2531        """
2532        from math import pi, cos, sin
2533
2534        a = [0.0, 0.0]
2535        b = [0.0, 2.0]
2536        c = [2.0, 0.0]
2537        d = [0.0, 4.0]
2538        e = [2.0, 2.0]
2539        f = [4.0, 0.0]
2540
2541        points = [a, b, c, d, e, f]
2542        #bac, bce, ecf, dbe
2543        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2544
2545
2546        domain = Domain(points, vertices)
2547
2548        # Flat surface with 1m of water
2549        domain.set_quantity('elevation', 0)
2550        domain.set_quantity('stage', 1.0)
2551        domain.set_quantity('friction', 0)
2552
2553        Br = Reflective_boundary(domain)
2554        domain.set_boundary({'exterior': Br})
2555
2556        # Setup only one forcing term, constant inflow of 2 m^3/s on a circle affecting triangles #0 and #1 (bac and bce)
2557
2558        try:
2559            Inflow(domain, rate=2.0, center=(1,1.1), radius=0.01)
2560        except:
2561            pass
2562        else:
2563            msg = 'Should have raised exception'
2564            raise Exception, msg
2565
2566
2567
2568       
2569       
2570
2571    #####################################################
2572    def test_first_order_extrapolator_const_z(self):
2573
2574        a = [0.0, 0.0]
2575        b = [0.0, 2.0]
2576        c = [2.0, 0.0]
2577        d = [0.0, 4.0]
2578        e = [2.0, 2.0]
2579        f = [4.0, 0.0]
2580
2581        points = [a, b, c, d, e, f]
2582        #bac, bce, ecf, dbe
2583        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2584
2585        domain = Domain(points, vertices)
2586        val0 = 2.+2.0/3
2587        val1 = 4.+4.0/3
2588        val2 = 8.+2.0/3
2589        val3 = 2.+8.0/3
2590
2591        zl=zr=-3.75 #Assume constant bed (must be less than stage)
2592        domain.set_quantity('elevation', zl*ones( (4,3) ))
2593        domain.set_quantity('stage', [[val0, val0-1, val0-2],
2594                                      [val1, val1+1, val1],
2595                                      [val2, val2-2, val2],
2596                                      [val3-0.5, val3, val3]])
2597
2598
2599
2600        domain._order_ = 1
2601        domain.distribute_to_vertices_and_edges()
2602
2603        #Check that centroid values were distributed to vertices
2604        C = domain.quantities['stage'].centroid_values
2605        for i in range(3):
2606            assert allclose( domain.quantities['stage'].vertex_values[:,i], C)
2607
2608
2609    def test_first_order_limiter_variable_z(self):
2610        #Check that first order limiter follows bed_slope
2611        from Numeric import alltrue, greater_equal
2612        from anuga.config import epsilon
2613
2614        a = [0.0, 0.0]
2615        b = [0.0, 2.0]
2616        c = [2.0,0.0]
2617        d = [0.0, 4.0]
2618        e = [2.0, 2.0]
2619        f = [4.0,0.0]
2620
2621        points = [a, b, c, d, e, f]
2622        #bac, bce, ecf, dbe
2623        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2624
2625        domain = Domain(points, vertices)
2626        val0 = 2.+2.0/3
2627        val1 = 4.+4.0/3
2628        val2 = 8.+2.0/3
2629        val3 = 2.+8.0/3
2630
2631        domain.set_quantity('elevation', [[0,0,0], [6,0,0],
2632                                          [6,6,6], [6,6,6]])
2633        domain.set_quantity('stage', [[val0, val0, val0],
2634                                      [val1, val1, val1],
2635                                      [val2, val2, val2],
2636                                      [val3, val3, val3]])
2637
2638        E = domain.quantities['elevation'].vertex_values
2639        L = domain.quantities['stage'].vertex_values
2640
2641
2642        #Check that some stages are not above elevation (within eps)
2643        #- so that the limiter has something to work with
2644        assert not alltrue(alltrue(greater_equal(L,E-epsilon)))
2645
2646        domain._order_ = 1
2647        domain.distribute_to_vertices_and_edges()
2648
2649        #Check that all stages are above elevation (within eps)
2650        assert alltrue(alltrue(greater_equal(L,E-epsilon)))
2651
2652
2653    #####################################################
2654    def test_distribute_basic(self):
2655        #Using test data generated by abstract_2d_finite_volumes-2
2656        #Assuming no friction and flat bed (0.0)
2657
2658        a = [0.0, 0.0]
2659        b = [0.0, 2.0]
2660        c = [2.0, 0.0]
2661        d = [0.0, 4.0]
2662        e = [2.0, 2.0]
2663        f = [4.0, 0.0]
2664
2665        points = [a, b, c, d, e, f]
2666        #bac, bce, ecf, dbe
2667        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2668
2669        domain = Domain(points, vertices)
2670
2671        val0 = 2.
2672        val1 = 4.
2673        val2 = 8.
2674        val3 = 2.
2675
2676        domain.set_quantity('stage', [val0, val1, val2, val3],
2677                            location='centroids')
2678        L = domain.quantities['stage'].vertex_values
2679
2680        #First order
2681        domain._order_ = 1
2682        domain.distribute_to_vertices_and_edges()
2683        assert allclose(L[1], val1)
2684
2685        #Second order
2686        domain._order_ = 2
2687        domain.beta_w      = 0.9
2688        domain.beta_w_dry  = 0.9
2689        domain.beta_uh     = 0.9
2690        domain.beta_uh_dry = 0.9
2691        domain.beta_vh     = 0.9
2692        domain.beta_vh_dry = 0.9
2693        domain.distribute_to_vertices_and_edges()
2694        assert allclose(L[1], [2.2, 4.9, 4.9])
2695
2696
2697
2698    def test_distribute_away_from_bed(self):
2699        #Using test data generated by abstract_2d_finite_volumes-2
2700        #Assuming no friction and flat bed (0.0)
2701
2702        a = [0.0, 0.0]
2703        b = [0.0, 2.0]
2704        c = [2.0, 0.0]
2705        d = [0.0, 4.0]
2706        e = [2.0, 2.0]
2707        f = [4.0, 0.0]
2708
2709        points = [a, b, c, d, e, f]
2710        #bac, bce, ecf, dbe
2711        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2712
2713        domain = Domain(points, vertices)
2714        L = domain.quantities['stage'].vertex_values
2715
2716        def stage(x,y):
2717            return x**2
2718
2719        domain.set_quantity('stage', stage, location='centroids')
2720
2721        domain.quantities['stage'].compute_gradients()
2722
2723        a, b = domain.quantities['stage'].get_gradients()
2724               
2725        assert allclose(a[1], 3.33333334)
2726        assert allclose(b[1], 0.0)
2727
2728        domain._order_ = 1
2729        domain.distribute_to_vertices_and_edges()
2730        assert allclose(L[1], 1.77777778)
2731
2732        domain._order_ = 2
2733        domain.beta_w      = 0.9
2734        domain.beta_w_dry  = 0.9
2735        domain.beta_uh     = 0.9
2736        domain.beta_uh_dry = 0.9
2737        domain.beta_vh     = 0.9
2738        domain.beta_vh_dry = 0.9
2739        domain.distribute_to_vertices_and_edges()
2740        assert allclose(L[1], [0.57777777, 2.37777778, 2.37777778])
2741
2742
2743
2744    def test_distribute_away_from_bed1(self):
2745        #Using test data generated by abstract_2d_finite_volumes-2
2746        #Assuming no friction and flat bed (0.0)
2747
2748        a = [0.0, 0.0]
2749        b = [0.0, 2.0]
2750        c = [2.0, 0.0]
2751        d = [0.0, 4.0]
2752        e = [2.0, 2.0]
2753        f = [4.0, 0.0]
2754
2755        points = [a, b, c, d, e, f]
2756        #bac, bce, ecf, dbe
2757        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2758
2759        domain = Domain(points, vertices)
2760        L = domain.quantities['stage'].vertex_values
2761
2762        def stage(x,y):
2763            return x**4+y**2
2764
2765        domain.set_quantity('stage', stage, location='centroids')
2766        #print domain.quantities['stage'].centroid_values
2767
2768        domain.quantities['stage'].compute_gradients()
2769        a, b = domain.quantities['stage'].get_gradients()
2770        assert allclose(a[1], 25.18518519)
2771        assert allclose(b[1], 3.33333333)
2772
2773        domain._order_ = 1
2774        domain.distribute_to_vertices_and_edges()
2775        assert allclose(L[1], 4.9382716)
2776
2777        domain._order_ = 2
2778        domain.beta_w      = 0.9
2779        domain.beta_w_dry  = 0.9
2780        domain.beta_uh     = 0.9
2781        domain.beta_uh_dry = 0.9
2782        domain.beta_vh     = 0.9
2783        domain.beta_vh_dry = 0.9
2784        domain.distribute_to_vertices_and_edges()
2785        assert allclose(L[1], [1.07160494, 6.46058131, 7.28262855])
2786
2787
2788
2789    def test_distribute_near_bed(self):
2790
2791        a = [0.0, 0.0]
2792        b = [0.0, 2.0]
2793        c = [2.0, 0.0]
2794        d = [0.0, 4.0]
2795        e = [2.0, 2.0]
2796        f = [4.0, 0.0]
2797
2798        points = [a, b, c, d, e, f]
2799        #bac, bce, ecf, dbe
2800        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2801
2802        domain = Domain(points, vertices)
2803
2804
2805        #Set up for a gradient of (10,0) at mid triangle (bce)
2806        def slope(x, y):
2807            return 10*x
2808
2809        h = 0.1
2810        def stage(x, y):
2811            return slope(x, y) + h
2812
2813        domain.set_quantity('elevation', slope)
2814        domain.set_quantity('stage', stage, location='centroids')
2815
2816        #print domain.quantities['elevation'].centroid_values
2817        #print domain.quantities['stage'].centroid_values
2818
2819        E = domain.quantities['elevation'].vertex_values
2820        L = domain.quantities['stage'].vertex_values
2821
2822        # Get reference values
2823        volumes = []
2824        for i in range(len(L)):
2825            volumes.append(sum(L[i])/3)
2826            assert allclose(volumes[i], domain.quantities['stage'].centroid_values[i]) 
2827       
2828       
2829        domain._order_ = 1
2830       
2831        domain.tight_slope_limiters = 0
2832        domain.distribute_to_vertices_and_edges()
2833        assert allclose(L[1], [0.1, 20.1, 20.1])
2834        for i in range(len(L)):
2835            assert allclose(volumes[i], sum(L[i])/3)                   
2836       
2837        domain.tight_slope_limiters = 1 # Allow triangle to be flatter (closer to bed)
2838        domain.distribute_to_vertices_and_edges()
2839        assert allclose(L[1], [0.298, 20.001, 20.001])
2840        for i in range(len(L)):
2841            assert allclose(volumes[i], sum(L[i])/3)   
2842
2843        domain._order_ = 2
2844       
2845        domain.tight_slope_limiters = 0
2846        domain.distribute_to_vertices_and_edges()
2847        assert allclose(L[1], [0.1, 20.1, 20.1])       
2848        for i in range(len(L)):
2849            assert allclose(volumes[i], sum(L[i])/3)           
2850       
2851        domain.tight_slope_limiters = 1 # Allow triangle to be flatter (closer to bed)
2852        domain.distribute_to_vertices_and_edges()
2853        assert allclose(L[1], [0.298, 20.001, 20.001])
2854        for i in range(len(L)):
2855            assert allclose(volumes[i], sum(L[i])/3)   
2856       
2857
2858
2859    def test_distribute_near_bed1(self):
2860
2861        a = [0.0, 0.0]
2862        b = [0.0, 2.0]
2863        c = [2.0, 0.0]
2864        d = [0.0, 4.0]
2865        e = [2.0, 2.0]
2866        f = [4.0, 0.0]
2867
2868        points = [a, b, c, d, e, f]
2869        #bac, bce, ecf, dbe
2870        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
2871
2872        domain = Domain(points, vertices)
2873
2874
2875        #Set up for a gradient of (8,2) at mid triangle (bce)
2876        def slope(x, y):
2877            return x**4+y**2
2878
2879        h = 0.1
2880        def stage(x,y):
2881            return slope(x,y)+h
2882
2883        domain.set_quantity('elevation', slope)
2884        domain.set_quantity('stage', stage)
2885
2886        #print domain.quantities['elevation'].centroid_values
2887        #print domain.quantities['stage'].centroid_values
2888
2889        E = domain.quantities['elevation'].vertex_values
2890        L = domain.quantities['stage'].vertex_values
2891
2892        # Get reference values
2893        volumes = []
2894        for i in range(len(L)):
2895            volumes.append(sum(L[i])/3)
2896            assert allclose(volumes[i], domain.quantities['stage'].centroid_values[i]) 
2897       
2898        #print E
2899        domain._order_ = 1
2900       
2901        domain.tight_slope_limiters = 0
2902        domain.distribute_to_vertices_and_edges()
2903        assert allclose(L[1], [4.1, 16.1, 20.1])       
2904        for i in range(len(L)):
2905            assert allclose(volumes[i], sum(L[i])/3)
2906       
2907               
2908        domain.tight_slope_limiters = 1 # Allow triangle to be flatter (closer to bed)
2909        domain.distribute_to_vertices_and_edges()
2910        assert allclose(L[1], [4.2386, 16.0604, 20.001])
2911        for i in range(len(L)):
2912            assert allclose(volumes[i], sum(L[i])/3)   
2913       
2914
2915        domain._order_ = 2
2916       
2917        domain.tight_slope_limiters = 0   
2918        domain.distribute_to_vertices_and_edges()
2919        assert allclose(L[1], [4.1, 16.1, 20.1])
2920        for i in range(len(L)):
2921            assert allclose(volumes[i], sum(L[i])/3)   
2922       
2923        domain.tight_slope_limiters = 1 # Allow triangle to be flatter (closer to bed)
2924        domain.distribute_to_vertices_and_edges()
2925        #print L[1]
2926        assert allclose(L[1], [4.23370103, 16.06529897, 20.001]) or\
2927               allclose(L[1], [4.18944138, 16.10955862, 20.001]) or\
2928               allclose(L[1], [4.19351461, 16.10548539, 20.001]) # old limiters
2929       
2930        for i in range(len(L)):
2931            assert allclose(volumes[i], sum(L[i])/3)
2932
2933
2934    def test_second_order_distribute_real_data(self):
2935        #Using test data generated by abstract_2d_finite_volumes-2
2936        #Assuming no friction and flat bed (0.0)
2937
2938        a = [0.0, 0.0]
2939        b = [0.0, 1.0/5]
2940        c = [0.0, 2.0/5]
2941        d = [1.0/5, 0.0]
2942        e = [1.0/5, 1.0/5]
2943        f = [1.0/5, 2.0/5]
2944        g = [2.0/5, 2.0/5]
2945
2946        points = [a, b, c, d, e, f, g]
2947        #bae, efb, cbf, feg
2948        vertices = [ [1,0,4], [4,5,1], [2,1,5], [5,4,6]]
2949
2950        domain = Domain(points, vertices)
2951
2952        def slope(x, y):
2953            return -x/3
2954
2955        domain.set_quantity('elevation', slope)
2956        domain.set_quantity('stage',
2957                            [0.01298164, 0.00365611,
2958                             0.01440365, -0.0381856437096],
2959                            location='centroids')
2960        domain.set_quantity('xmomentum',
2961                            [0.00670439, 0.01263789,
2962                             0.00647805, 0.0178180740668],
2963                            location='centroids')
2964        domain.set_quantity('ymomentum',
2965                            [-7.23510980e-004, -6.30413883e-005,
2966                             6.30413883e-005, 0.000200907255866],
2967                            location='centroids')
2968
2969        E = domain.quantities['elevation'].vertex_values
2970        L = domain.quantities['stage'].vertex_values
2971        X = domain.quantities['xmomentum'].vertex_values
2972        Y = domain.quantities['ymomentum'].vertex_values
2973
2974        #print E
2975        domain._order_ = 2
2976        domain.beta_w      = 0.9
2977        domain.beta_w_dry  = 0.9
2978        domain.beta_uh     = 0.9
2979        domain.beta_uh_dry = 0.9
2980        domain.beta_vh     = 0.9
2981        domain.beta_vh_dry = 0.9
2982       
2983        # FIXME (Ole): Need tests where this is commented out
2984        domain.tight_slope_limiters = 0 # Backwards compatibility (14/4/7)                 
2985        domain.use_centroid_velocities = 0 # Backwards compatibility (7/5/8)
2986       
2987               
2988        domain.distribute_to_vertices_and_edges()
2989
2990        #print L[1,:]
2991        #print X[1,:]
2992        #print Y[1,:]
2993
2994        assert allclose(L[1,:], [-0.00825735775384,
2995                                 -0.00801881482869,
2996                                 0.0272445025825])
2997        assert allclose(X[1,:], [0.0143507718962,
2998                                 0.0142502147066,
2999                                 0.00931268339717])
3000        assert allclose(Y[1,:], [-0.000117062180693,
3001                                 7.94434448109e-005,
3002                                 -0.000151505429018])
3003
3004
3005
3006    def test_balance_deep_and_shallow(self):
3007        """Test that balanced limiters preserve conserved quantites.
3008        This test is using old depth based balanced limiters
3009        """
3010        import copy
3011
3012        a = [0.0, 0.0]
3013        b = [0.0, 2.0]
3014        c = [2.0, 0.0]
3015        d = [0.0, 4.0]
3016        e = [2.0, 2.0]
3017        f = [4.0, 0.0]
3018
3019        points = [a, b, c, d, e, f]
3020
3021        #bac, bce, ecf, dbe
3022        elements = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
3023
3024        domain = Domain(points, elements)
3025        domain.check_integrity()
3026
3027        #Create a deliberate overshoot
3028        domain.set_quantity('stage', [[3,0,3], [2,2,6], [5,3,8], [8,3,5]])
3029        domain.set_quantity('elevation', 0) #Flat bed
3030        stage = domain.quantities['stage']
3031
3032        ref_centroid_values = copy.copy(stage.centroid_values[:]) #Copy
3033
3034        #Limit
3035        domain.tight_slope_limiters = 0               
3036        domain.distribute_to_vertices_and_edges()
3037
3038        #Assert that quantities are conserved
3039        from Numeric import sum
3040        for k in range(len(domain)):
3041            assert allclose (ref_centroid_values[k],
3042                             sum(stage.vertex_values[k,:])/3)
3043
3044
3045        #Now try with a non-flat bed - closely hugging initial stage in places
3046        #This will create alphas in the range [0, 0.478260, 1]
3047        domain.set_quantity('stage', [[3,0,3], [2,2,6], [5,3,8], [8,3,5]])
3048        domain.set_quantity('elevation', [[0,0,0],
3049                                        [1.8,1.9,5.9],
3050                                        [4.6,0,0],
3051                                        [0,2,4]])
3052        stage = domain.quantities['stage']
3053
3054        ref_centroid_values = copy.copy(stage.centroid_values[:]) #Copy
3055        ref_vertex_values = copy.copy(stage.vertex_values[:]) #Copy
3056
3057        #Limit
3058        domain.tight_slope_limiters = 0       
3059        domain.distribute_to_vertices_and_edges()
3060
3061
3062        #Assert that all vertex quantities have changed
3063        for k in range(len(domain)):
3064            #print ref_vertex_values[k,:], stage.vertex_values[k,:]
3065            assert not allclose (ref_vertex_values[k,:], stage.vertex_values[k,:])
3066        #and assert that quantities are still conserved
3067        from Numeric import sum
3068        for k in range(len(domain)):
3069            assert allclose (ref_centroid_values[k],
3070                             sum(stage.vertex_values[k,:])/3)
3071
3072
3073        # Check actual results
3074        assert allclose (stage.vertex_values,
3075                         [[2,2,2],
3076                          [1.93333333, 2.03333333, 6.03333333],
3077                          [6.93333333, 4.53333333, 4.53333333],
3078                          [5.33333333, 5.33333333, 5.33333333]])
3079
3080
3081    def test_balance_deep_and_shallow_tight_SL(self):
3082        """Test that balanced limiters preserve conserved quantites.
3083        This test is using Tight Slope Limiters
3084        """
3085        import copy
3086
3087        a = [0.0, 0.0]
3088        b = [0.0, 2.0]
3089        c = [2.0, 0.0]
3090        d = [0.0, 4.0]
3091        e = [2.0, 2.0]
3092        f = [4.0, 0.0]
3093
3094        points = [a, b, c, d, e, f]
3095
3096        #bac, bce, ecf, dbe
3097        elements = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
3098
3099        domain = Domain(points, elements)
3100        domain.check_integrity()
3101
3102        #Create a deliberate overshoot
3103        domain.set_quantity('stage', [[3,0,3], [2,2,6], [5,3,8], [8,3,5]])
3104        domain.set_quantity('elevation', 0) #Flat bed
3105        stage = domain.quantities['stage']
3106
3107        ref_centroid_values = copy.copy(stage.centroid_values[:]) #Copy
3108
3109        #Limit
3110        domain.tight_slope_limiters = 1               
3111        domain.distribute_to_vertices_and_edges()
3112
3113        #Assert that quantities are conserved
3114        from Numeric import sum
3115        for k in range(len(domain)):
3116            assert allclose (ref_centroid_values[k],
3117                             sum(stage.vertex_values[k,:])/3)
3118
3119
3120        #Now try with a non-flat bed - closely hugging initial stage in places
3121        #This will create alphas in the range [0, 0.478260, 1]
3122        domain.set_quantity('stage', [[3,0,3], [2,2,6], [5,3,8], [8,3,5]])
3123        domain.set_quantity('elevation', [[0,0,0],
3124                                        [1.8,1.9,5.9],
3125                                        [4.6,0,0],
3126                                        [0,2,4]])
3127        stage = domain.quantities['stage']
3128
3129        ref_centroid_values = copy.copy(stage.centroid_values[:]) #Copy
3130        ref_vertex_values = copy.copy(stage.vertex_values[:]) #Copy
3131
3132        #Limit
3133        domain.tight_slope_limiters = 1       
3134        domain.distribute_to_vertices_and_edges()
3135
3136
3137        #Assert that all vertex quantities have changed
3138        for k in range(len(domain)):
3139            #print ref_vertex_values[k,:], stage.vertex_values[k,:]
3140            assert not allclose (ref_vertex_values[k,:], stage.vertex_values[k,:])
3141        #and assert that quantities are still conserved
3142        from Numeric import sum
3143        for k in range(len(domain)):
3144            assert allclose (ref_centroid_values[k],
3145                             sum(stage.vertex_values[k,:])/3)
3146
3147
3148        #Also check that Python and C version produce the same
3149        # No longer applicable if tight_slope_limiters == 1
3150        #print stage.vertex_values
3151        #assert allclose (stage.vertex_values,
3152        #                 [[2,2,2],
3153        #                  [1.93333333, 2.03333333, 6.03333333],
3154        #                  [6.93333333, 4.53333333, 4.53333333],
3155        #                  [5.33333333, 5.33333333, 5.33333333]])
3156
3157
3158
3159    def test_balance_deep_and_shallow_Froude(self):
3160        """Test that balanced limiters preserve conserved quantites -
3161        and also that excessive Froude numbers are dealt with.
3162        This test is using tight slope limiters.
3163        """
3164        import copy
3165        from Numeric import sqrt, absolute
3166
3167        a = [0.0, 0.0]
3168        b = [0.0, 2.0]
3169        c = [2.0, 0.0]
3170        d = [0.0, 4.0]
3171        e = [2.0, 2.0]
3172        f = [4.0, 0.0]
3173
3174        points = [a, b, c, d, e, f]
3175
3176        # bac, bce, ecf, dbe
3177        elements = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
3178
3179        domain = Domain(points, elements)
3180        domain.check_integrity()
3181        domain.tight_slope_limiters = True
3182        domain.use_centroid_velocities = True               
3183
3184        # Create non-flat bed - closely hugging initial stage in places
3185        # This will create alphas in the range [0, 0.478260, 1]
3186        domain.set_quantity('stage', [[3,0,3], [2,2,6], [5,3,8], [8,3,5]])
3187        domain.set_quantity('elevation', [[0,0,0],
3188                                        [1.8,1.999,5.999],
3189                                        [4.6,0,0],
3190                                        [0,2,4]])
3191
3192        # Create small momenta, that nonetheless will generate large speeds
3193        # due to shallow depth at isolated vertices
3194        domain.set_quantity('xmomentum', -0.0058)
3195        domain.set_quantity('ymomentum', 0.0890)
3196
3197
3198
3199       
3200        stage = domain.quantities['stage']
3201        elevation = domain.quantities['elevation']
3202        xmomentum = domain.quantities['xmomentum']
3203        ymomentum = domain.quantities['ymomentum']       
3204
3205        # Setup triangle #1 to mimick real Froude explosion observed
3206        # in the Onslow example 13 Nov 2007.
3207
3208        stage.vertex_values[1,:] = [1.6385, 1.6361, 1.2953]
3209        elevation.vertex_values[1,:] = [1.6375, 1.6336, 0.4647]       
3210        xmomentum.vertex_values[1,:] = [-0.0058, -0.0050, -0.0066]
3211        ymomentum.vertex_values[1,:] = [0.0890, 0.0890, 0.0890]
3212
3213        xmomentum.interpolate()
3214        ymomentum.interpolate()       
3215        stage.interpolate()       
3216        elevation.interpolate()
3217
3218        # Verify interpolation
3219        assert allclose(stage.centroid_values[1], 1.5233)
3220        assert allclose(elevation.centroid_values[1], 1.2452667)
3221        assert allclose(xmomentum.centroid_values[1], -0.0058)
3222        assert allclose(ymomentum.centroid_values[1], 0.089)
3223
3224        # Derived quantities
3225        depth = stage-elevation
3226        u = xmomentum/depth
3227        v = ymomentum/depth
3228
3229        denom = (depth*g)**0.5 
3230        Fx = u/denom
3231        Fy = v/denom
3232       
3233   
3234        # Verify against Onslow example (14 Nov 2007)
3235        assert allclose(depth.centroid_values[1], 0.278033)
3236        assert allclose(u.centroid_values[1], -0.0208608)
3237        assert allclose(v.centroid_values[1], 0.3201055)
3238
3239        assert allclose(denom.centroid_values[1],
3240                        sqrt(depth.centroid_values[1]*g))
3241
3242        assert allclose(u.centroid_values[1]/denom.centroid_values[1],
3243                        -0.012637746977)
3244        assert allclose(Fx.centroid_values[1],
3245                        u.centroid_values[1]/denom.centroid_values[1])
3246
3247        # Check that Froude numbers are small at centroids.
3248        assert allclose(Fx.centroid_values[1], -0.012637746977)
3249        assert allclose(Fy.centroid_values[1], 0.193924048435)
3250
3251
3252        # But Froude numbers are huge at some vertices and edges
3253        assert allclose(Fx.vertex_values[1,:], [-5.85888475e+01,
3254                                                -1.27775313e+01,
3255                                                -2.78511420e-03])
3256
3257        assert allclose(Fx.edge_values[1,:], [-6.89150773e-03,
3258                                              -7.38672488e-03,
3259                                              -2.35626238e+01])
3260
3261        assert allclose(Fy.vertex_values[1,:], [8.99035764e+02,
3262                                                2.27440057e+02,
3263                                                3.75568430e-02])
3264
3265        assert allclose(Fy.edge_values[1,:], [1.05748998e-01,
3266                                              1.06035244e-01,
3267                                              3.88346947e+02])
3268       
3269       
3270        # The task is now to arrange the limiters such that Froude numbers
3271        # remain under control whil at the same time obeying the conservation
3272        # laws.
3273
3274       
3275        ref_centroid_values = copy.copy(stage.centroid_values[:]) #Copy
3276        ref_vertex_values = copy.copy(stage.vertex_values[:]) #Copy
3277
3278        # Limit (and invoke balance_deep_and_shallow)
3279        domain.tight_slope_limiters = 1
3280        domain.distribute_to_vertices_and_edges()
3281
3282        # Redo derived quantities
3283        depth = stage-elevation
3284        u = xmomentum/depth
3285        v = ymomentum/depth
3286
3287        # Assert that all vertex velocities stay within one
3288        # order of magnitude of centroid velocities.
3289        #print u.vertex_values[1,:]
3290        #print u.centroid_values[1]
3291       
3292        assert alltrue(absolute(u.vertex_values[1,:]) <= absolute(u.centroid_values[1])*10)
3293        assert alltrue(absolute(v.vertex_values[1,:]) <= absolute(v.centroid_values[1])*10) 
3294
3295        denom = (depth*g)**0.5 
3296        Fx = u/denom
3297        Fy = v/denom
3298
3299
3300        # Assert that Froude numbers are less than max value (TBA)
3301        # at vertices, edges and centroids.
3302        from anuga.config import maximum_froude_number
3303        assert alltrue(absolute(Fx.vertex_values[1,:]) < maximum_froude_number)
3304        assert alltrue(absolute(Fy.vertex_values[1,:]) < maximum_froude_number)
3305
3306
3307        # Assert that all vertex quantities have changed
3308        for k in range(len(domain)):
3309            #print ref_vertex_values[k,:], stage.vertex_values[k,:]
3310            assert not allclose (ref_vertex_values[k,:],
3311                                 stage.vertex_values[k,:])
3312           
3313        # Assert that quantities are still conserved
3314        from Numeric import sum
3315        for k in range(len(domain)):
3316            assert allclose (ref_centroid_values[k],
3317                             sum(stage.vertex_values[k,:])/3)
3318
3319
3320       
3321        return
3322   
3323        qwidth = 12
3324        for k in [1]: #range(len(domain)):
3325            print 'Triangle %d (C, V, E)' %k
3326           
3327            print 'stage'.ljust(qwidth), stage.centroid_values[k],\
3328                  stage.vertex_values[k,:], stage.edge_values[k,:]
3329            print 'elevation'.ljust(qwidth), elevation.centroid_values[k],\
3330                  elevation.vertex_values[k,:], elevation.edge_values[k,:]
3331            print 'depth'.ljust(qwidth), depth.centroid_values[k],\
3332                  depth.vertex_values[k,:], depth.edge_values[k,:]
3333            print 'xmomentum'.ljust(qwidth), xmomentum.centroid_values[k],\
3334                  xmomentum.vertex_values[k,:], xmomentum.edge_values[k,:]
3335            print 'ymomentum'.ljust(qwidth), ymomentum.centroid_values[k],\
3336                  ymomentum.vertex_values[k,:], ymomentum.edge_values[k,:]
3337            print 'u'.ljust(qwidth),u.centroid_values[k],\
3338                  u.vertex_values[k,:], u.edge_values[k,:]
3339            print 'v'.ljust(qwidth), v.centroid_values[k],\
3340                  v.vertex_values[k,:], v.edge_values[k,:]
3341            print 'Fx'.ljust(qwidth), Fx.centroid_values[k],\
3342                  Fx.vertex_values[k,:], Fx.edge_values[k,:]
3343            print 'Fy'.ljust(qwidth), Fy.centroid_values[k],\
3344                  Fy.vertex_values[k,:], Fy.edge_values[k,:]
3345           
3346           
3347       
3348
3349
3350
3351    def test_conservation_1(self):
3352        """Test that stage is conserved globally
3353
3354        This one uses a flat bed, reflective bdries and a suitable
3355        initial condition
3356        """
3357        from mesh_factory import rectangular
3358        from Numeric import array
3359
3360        #Create basic mesh
3361        points, vertices, boundary = rectangular(6, 6)
3362
3363        #Create shallow water domain
3364        domain = Domain(points, vertices, boundary)
3365        domain.smooth = False
3366        domain.default_order=2
3367
3368        #IC
3369        def x_slope(x, y):
3370            return x/3
3371
3372        domain.set_quantity('elevation', 0)
3373        domain.set_quantity('friction', 0)
3374        domain.set_quantity('stage', x_slope)
3375
3376        # Boundary conditions (reflective everywhere)
3377        Br = Reflective_boundary(domain)
3378        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
3379
3380        domain.check_integrity()
3381
3382        initial_volume = domain.quantities['stage'].get_integral()
3383        initial_xmom = domain.quantities['xmomentum'].get_integral()
3384
3385        #print initial_xmom
3386
3387        #Evolution
3388        for t in domain.evolve(yieldstep = 0.05, finaltime = 5.0):
3389            volume =  domain.quantities['stage'].get_integral()
3390            assert allclose (volume, initial_volume)
3391
3392            #I don't believe that the total momentum should be the same
3393            #It starts with zero and ends with zero though
3394            #xmom = domain.quantities['xmomentum'].get_integral()
3395            #print xmom
3396            #assert allclose (xmom, initial_xmom)
3397
3398        os.remove(domain.get_name() + '.sww')
3399
3400
3401    def test_conservation_2(self):
3402        """Test that stage is conserved globally
3403
3404        This one uses a slopy bed, reflective bdries and a suitable
3405        initial condition
3406        """
3407        from mesh_factory import rectangular
3408        from Numeric import array
3409
3410        #Create basic mesh
3411        points, vertices, boundary = rectangular(6, 6)
3412
3413        #Create shallow water domain
3414        domain = Domain(points, vertices, boundary)
3415        domain.smooth = False
3416        domain.default_order=2
3417
3418        #IC
3419        def x_slope(x, y):
3420            return x/3
3421
3422        domain.set_quantity('elevation', x_slope)
3423        domain.set_quantity('friction', 0)
3424        domain.set_quantity('stage', 0.4) #Steady
3425
3426        # Boundary conditions (reflective everywhere)
3427        Br = Reflective_boundary(domain)
3428        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
3429
3430        domain.check_integrity()
3431
3432        initial_volume = domain.quantities['stage'].get_integral()
3433        initial_xmom = domain.quantities['xmomentum'].get_integral()
3434
3435        #print initial_xmom
3436
3437        #Evolution
3438        for t in domain.evolve(yieldstep = 0.05, finaltime = 5.0):
3439            volume =  domain.quantities['stage'].get_integral()
3440            assert allclose (volume, initial_volume)
3441
3442            #FIXME: What would we expect from momentum
3443            #xmom = domain.quantities['xmomentum'].get_integral()
3444            #print xmom
3445            #assert allclose (xmom, initial_xmom)
3446
3447        os.remove(domain.get_name() + '.sww')
3448
3449    def test_conservation_3(self):
3450        """Test that stage is conserved globally
3451
3452        This one uses a larger grid, convoluted bed, reflective bdries and a suitable
3453        initial condition
3454        """
3455        from mesh_factory import rectangular
3456        from Numeric import array
3457
3458        #Create basic mesh
3459        points, vertices, boundary = rectangular(2, 1)
3460
3461        #Create shallow water domain
3462        domain = Domain(points, vertices, boundary)
3463        domain.smooth = False
3464        domain.default_order = 2
3465        domain.set_quantities_to_be_stored(['stage', 'xmomentum', 'ymomentum'])
3466
3467        #IC
3468        def x_slope(x, y):
3469            z = 0*x
3470            for i in range(len(x)):
3471                if x[i] < 0.3:
3472                    z[i] = x[i]/3
3473                if 0.3 <= x[i] < 0.5:
3474                    z[i] = -0.5
3475                if 0.5 <= x[i] < 0.7:
3476                    z[i] = 0.39
3477                if 0.7 <= x[i]:
3478                    z[i] = x[i]/3
3479            return z
3480
3481
3482
3483        domain.set_quantity('elevation', x_slope)
3484        domain.set_quantity('friction', 0)
3485        domain.set_quantity('stage', 0.4) #Steady
3486
3487        # Boundary conditions (reflective everywhere)
3488        Br = Reflective_boundary(domain)
3489        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
3490
3491        domain.check_integrity()
3492
3493        initial_volume = domain.quantities['stage'].get_integral()
3494        initial_xmom = domain.quantities['xmomentum'].get_integral()
3495
3496        import copy
3497        ref_centroid_values =\
3498                 copy.copy(domain.quantities['stage'].centroid_values)
3499
3500        #print 'ORG', domain.quantities['stage'].centroid_values
3501        domain.distribute_to_vertices_and_edges()
3502
3503
3504        #print domain.quantities['stage'].centroid_values
3505        assert allclose(domain.quantities['stage'].centroid_values,
3506                        ref_centroid_values)
3507
3508
3509        #Check that initial limiter doesn't violate cons quan
3510        assert allclose(domain.quantities['stage'].get_integral(),
3511                        initial_volume)
3512
3513        #Evolution
3514        for t in domain.evolve(yieldstep = 0.05, finaltime = 10):
3515            volume =  domain.quantities['stage'].get_integral()
3516            #print t, volume, initial_volume
3517            assert allclose (volume, initial_volume)
3518
3519        os.remove(domain.get_name() + '.sww')
3520
3521    def test_conservation_4(self):
3522        """Test that stage is conserved globally
3523
3524        This one uses a larger grid, convoluted bed, reflective bdries and a suitable
3525        initial condition
3526        """
3527        from mesh_factory import rectangular
3528        from Numeric import array
3529
3530        #Create basic mesh
3531        points, vertices, boundary = rectangular(6, 6)
3532
3533        #Create shallow water domain
3534        domain = Domain(points, vertices, boundary)
3535        domain.smooth = False
3536        domain.default_order=2
3537
3538        #IC
3539        def x_slope(x, y):
3540            z = 0*x
3541            for i in range(len(x)):
3542                if x[i] < 0.3:
3543                    z[i] = x[i]/3
3544                if 0.3 <= x[i] < 0.5:
3545                    z[i] = -0.5
3546                if 0.5 <= x[i] < 0.7:
3547                    #z[i] = 0.3 #OK with beta == 0.2
3548                    z[i] = 0.34 #OK with beta == 0.0
3549                    #z[i] = 0.35#Fails after 80 timesteps with an error
3550                                #of the order 1.0e-5
3551                if 0.7 <= x[i]:
3552                    z[i] = x[i]/3
3553            return z
3554
3555
3556
3557        domain.set_quantity('elevation', x_slope)
3558        domain.set_quantity('friction', 0)
3559        domain.set_quantity('stage', 0.4) #Steady
3560
3561        # Boundary conditions (reflective everywhere)
3562        Br = Reflective_boundary(domain)
3563        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
3564
3565        domain.check_integrity()
3566
3567        initial_volume = domain.quantities['stage'].get_integral()
3568        initial_xmom = domain.quantities['xmomentum'].get_integral()
3569
3570        import copy
3571        ref_centroid_values =\
3572                 copy.copy(domain.quantities['stage'].centroid_values)
3573
3574        #Test limiter by itself
3575        domain.distribute_to_vertices_and_edges()
3576
3577        #Check that initial limiter doesn't violate cons quan
3578        assert allclose (domain.quantities['stage'].get_integral(),
3579                         initial_volume)
3580        #NOTE: This would fail if any initial stage was less than the
3581        #corresponding bed elevation - but that is reasonable.
3582
3583
3584        #Evolution
3585        for t in domain.evolve(yieldstep = 0.05, finaltime = 10.0):
3586            volume =  domain.quantities['stage'].get_integral()
3587
3588            #print t, volume, initial_volume
3589
3590            assert allclose (volume, initial_volume)
3591
3592
3593        os.remove(domain.get_name() + '.sww')
3594
3595
3596    def test_conservation_5(self):
3597        """Test that momentum is conserved globally in
3598        steady state scenario
3599
3600        This one uses a slopy bed, dirichlet and reflective bdries
3601        """
3602        from mesh_factory import rectangular
3603        from Numeric import array
3604
3605        # Create basic mesh
3606        points, vertices, boundary = rectangular(6, 6)
3607
3608        # Create shallow water domain
3609        domain = Domain(points, vertices, boundary)
3610        domain.smooth = False
3611        domain.default_order = 2
3612
3613        # IC
3614        def x_slope(x, y):
3615            return x/3
3616
3617        domain.set_quantity('elevation', x_slope)
3618        domain.set_quantity('friction', 0)
3619        domain.set_quantity('stage', 0.4) # Steady
3620
3621        # Boundary conditions (reflective everywhere)
3622        Br = Reflective_boundary(domain)
3623        Bleft = Dirichlet_boundary([0.5,0,0])
3624        Bright = Dirichlet_boundary([0.1,0,0])
3625        domain.set_boundary({'left': Bleft, 'right': Bright,
3626                             'top': Br, 'bottom': Br})
3627
3628        domain.check_integrity()
3629
3630        initial_volume = domain.quantities['stage'].get_integral()
3631        initial_xmom = domain.quantities['xmomentum'].get_integral()
3632
3633
3634        # Evolution
3635        for t in domain.evolve(yieldstep = 0.05, finaltime = 15.0):
3636            stage =  domain.quantities['stage'].get_integral()
3637            xmom = domain.quantities['xmomentum'].get_integral()
3638            ymom = domain.quantities['ymomentum'].get_integral()
3639
3640            if allclose(t, 6):  # Steady state reached
3641                steady_xmom = domain.quantities['xmomentum'].get_integral()
3642                steady_ymom = domain.quantities['ymomentum'].get_integral()
3643                steady_stage = domain.quantities['stage'].get_integral()
3644
3645            if t > 6:
3646                #print '%.2f %14.8f %14.8f' %(t, ymom, steady_ymom)
3647                msg = 'xmom=%.2f, steady_xmom=%.2f' %(xmom, steady_xmom)
3648                assert allclose(xmom, steady_xmom), msg
3649                assert allclose(ymom, steady_ymom)
3650                assert allclose(stage, steady_stage)
3651
3652
3653        os.remove(domain.get_name() + '.sww')
3654
3655
3656
3657
3658
3659    def test_conservation_real(self):
3660        """Test that momentum is conserved globally
3661       
3662        Stephen finally made a test that revealed the problem.
3663        This test failed with code prior to 25 July 2005
3664        """
3665
3666        yieldstep = 0.01
3667        finaltime = 0.05
3668        min_depth = 1.0e-2
3669
3670
3671        import sys
3672        from os import sep; sys.path.append('..'+sep+'abstract_2d_finite_volumes')
3673        from mesh_factory import rectangular
3674
3675
3676        #Create shallow water domain
3677        points, vertices, boundary = rectangular(10, 10, len1=500, len2=500)
3678        domain = Domain(points, vertices, boundary)
3679        domain.smooth = False
3680        domain.default_order = 1
3681        domain.minimum_allowed_height = min_depth
3682
3683        # Set initial condition
3684        class Set_IC:
3685            """Set an initial condition with a constant value, for x0<x<x1
3686            """
3687
3688            def __init__(self, x0=0.25, x1=0.5, h=1.0):
3689                self.x0 = x0
3690                self.x1 = x1
3691                self.= h
3692
3693            def __call__(self, x, y):
3694                return self.h*((x>self.x0)&(x<self.x1))
3695
3696
3697        domain.set_quantity('stage', Set_IC(200.0,300.0,5.0))
3698
3699
3700        #Boundaries
3701        R = Reflective_boundary(domain)
3702        domain.set_boundary( {'left': R, 'right': R, 'top':R, 'bottom': R})
3703
3704        ref = domain.quantities['stage'].get_integral()
3705
3706        # Evolution
3707        for t in domain.evolve(yieldstep = yieldstep, finaltime = finaltime):
3708            pass
3709            #print 'Integral stage = ',\
3710            #      domain.quantities['stage'].get_integral(),\
3711            #      ' Time = ',domain.time
3712
3713
3714        now = domain.quantities['stage'].get_integral()
3715
3716        msg = 'Stage not conserved: was %f, now %f' %(ref, now)
3717        assert allclose(ref, now), msg
3718
3719        os.remove(domain.get_name() + '.sww')
3720
3721    def test_second_order_flat_bed_onestep(self):
3722
3723        from mesh_factory import rectangular
3724        from Numeric import array
3725
3726        #Create basic mesh
3727        points, vertices, boundary = rectangular(6, 6)
3728
3729        #Create shallow water domain
3730        domain = Domain(points, vertices, boundary)
3731        domain.smooth = False
3732        domain.default_order = 2
3733        domain.beta_w      = 0.9
3734        domain.beta_w_dry  = 0.9
3735        domain.beta_uh     = 0.9
3736        domain.beta_uh_dry = 0.9
3737        domain.beta_vh     = 0.9
3738        domain.beta_vh_dry = 0.9
3739        domain.H0 = 0 # Backwards compatibility (6/2/7)       
3740       
3741        # Boundary conditions
3742        Br = Reflective_boundary(domain)
3743        Bd = Dirichlet_boundary([0.1, 0., 0.])
3744        domain.set_boundary({'left': Bd, 'right': Br, 'top': Br, 'bottom': Br})
3745
3746        domain.check_integrity()
3747
3748        # Evolution
3749        for t in domain.evolve(yieldstep = 0.05, finaltime = 0.05):
3750            pass# domain.write_time()
3751
3752        # Data from earlier version of abstract_2d_finite_volumes
3753        assert allclose(domain.min_timestep, 0.0396825396825)
3754        assert allclose(domain.max_timestep, 0.0396825396825)
3755
3756        assert allclose(domain.quantities['stage'].centroid_values[:12],
3757                        [0.00171396, 0.02656103, 0.00241523, 0.02656103,
3758                        0.00241523, 0.02656103, 0.00241523, 0.02656103,
3759                        0.00241523, 0.02656103, 0.00241523, 0.0272623])
3760
3761        domain.distribute_to_vertices_and_edges()
3762
3763        assert allclose(domain.quantities['stage'].vertex_values[:12,0],
3764                        [0.0001714, 0.02656103, 0.00024152,
3765                        0.02656103, 0.00024152, 0.02656103,
3766                        0.00024152, 0.02656103, 0.00024152,
3767                        0.02656103, 0.00024152, 0.0272623])
3768
3769        assert allclose(domain.quantities['stage'].vertex_values[:12,1],
3770                        [0.00315012, 0.02656103, 0.00024152, 0.02656103,
3771                         0.00024152, 0.02656103, 0.00024152, 0.02656103,
3772                         0.00024152, 0.02656103, 0.00040506, 0.0272623])
3773
3774        assert allclose(domain.quantities['stage'].vertex_values[:12,2],
3775                        [0.00182037, 0.02656103, 0.00676264,
3776                         0.02656103, 0.00676264, 0.02656103,
3777                         0.00676264, 0.02656103, 0.00676264,
3778                         0.02656103, 0.0065991, 0.0272623])
3779
3780        assert allclose(domain.quantities['xmomentum'].centroid_values[:12],
3781                        [0.00113961, 0.01302432, 0.00148672,
3782                         0.01302432, 0.00148672, 0.01302432,
3783                         0.00148672, 0.01302432, 0.00148672 ,
3784                         0.01302432, 0.00148672, 0.01337143])
3785
3786        assert allclose(domain.quantities['ymomentum'].centroid_values[:12],
3787                        [-2.91240050e-004 , 1.22721531e-004,
3788                         -1.22721531e-004, 1.22721531e-004 ,
3789                         -1.22721531e-004, 1.22721531e-004,
3790                         -1.22721531e-004 , 1.22721531e-004,
3791                         -1.22721531e-004, 1.22721531e-004,
3792                         -1.22721531e-004, -4.57969873e-005])
3793
3794        os.remove(domain.get_name() + '.sww')
3795
3796
3797    def test_second_order_flat_bed_moresteps(self):
3798
3799        from mesh_factory import rectangular
3800        from Numeric import array
3801
3802        #Create basic mesh
3803        points, vertices, boundary = rectangular(6, 6)
3804
3805        #Create shallow water domain
3806        domain = Domain(points, vertices, boundary)
3807        domain.smooth = False
3808        domain.default_order=2
3809
3810        # Boundary conditions
3811        Br = Reflective_boundary(domain)
3812        Bd = Dirichlet_boundary([0.1, 0., 0.])
3813        domain.set_boundary({'left': Bd, 'right': Br, 'top': Br, 'bottom': Br})
3814
3815        domain.check_integrity()
3816
3817        #Evolution
3818        for t in domain.evolve(yieldstep = 0.05, finaltime = 0.1):
3819            pass
3820
3821        #Data from earlier version of abstract_2d_finite_volumes
3822        #assert allclose(domain.min_timestep, 0.0396825396825)
3823        #assert allclose(domain.max_timestep, 0.0396825396825)
3824        #print domain.quantities['stage'].centroid_values
3825
3826        os.remove(domain.get_name() + '.sww')       
3827
3828
3829    def test_flatbed_first_order(self):
3830        from mesh_factory import rectangular
3831        from Numeric import array
3832
3833        #Create basic mesh
3834        N = 8
3835        points, vertices, boundary = rectangular(N, N)
3836
3837        #Create shallow water domain
3838        domain = Domain(points, vertices, boundary)
3839        domain.smooth = False
3840        domain.default_order=1
3841        domain.H0 = 0 # Backwards compatibility (6/2/7)       
3842
3843        # Boundary conditions
3844        Br = Reflective_boundary(domain)
3845        Bd = Dirichlet_boundary([0.2,0.,0.])
3846
3847        domain.set_boundary({'left': Bd, 'right': Br, 'top': Br, 'bottom': Br})
3848        domain.check_integrity()
3849
3850
3851        #Evolution
3852        for t in domain.evolve(yieldstep = 0.02, finaltime = 0.5):
3853            pass
3854            #domain.write_time()
3855
3856        #FIXME: These numbers were from version before 25/10
3857        #assert allclose(domain.min_timestep, 0.0140413643926)
3858        #assert allclose(domain.max_timestep, 0.0140947355753)
3859
3860        for i in range(3):
3861            #assert allclose(domain.quantities['stage'].edge_values[:4,i],
3862            #                [0.10730244,0.12337617,0.11200126,0.12605666])
3863
3864            assert allclose(domain.quantities['xmomentum'].edge_values[:4,i],
3865                            [0.07610894,0.06901572,0.07284461,0.06819712])
3866
3867            #assert allclose(domain.quantities['ymomentum'].edge_values[:4,i],
3868            #                [-0.0060238, -0.00157404, -0.00309633, -0.0001637])
3869
3870
3871        os.remove(domain.get_name() + '.sww')           
3872
3873    def test_flatbed_second_order(self):
3874        from mesh_factory import rectangular
3875        from Numeric import array
3876
3877        #Create basic mesh
3878        N = 8
3879        points, vertices, boundary = rectangular(N, N)
3880
3881        #Create shallow water domain
3882        domain = Domain(points, vertices, boundary)
3883        domain.smooth = False
3884        domain.default_order=2
3885        domain.beta_w      = 0.9
3886        domain.beta_w_dry  = 0.9
3887        domain.beta_uh     = 0.9
3888        domain.beta_uh_dry = 0.9
3889        domain.beta_vh     = 0.9
3890        domain.beta_vh_dry = 0.9       
3891        #domain.minimum_allowed_height = 0.0 #Makes it like the 'oldstyle' balance
3892        domain.H0 = 0 # Backwards compatibility (6/2/7)
3893        domain.use_centroid_velocities = False # Backwards compatibility (8/5/8)
3894        domain.set_maximum_allowed_speed(1.0)       
3895
3896        # Boundary conditions
3897        Br = Reflective_boundary(domain)
3898        Bd = Dirichlet_boundary([0.2,0.,0.])
3899
3900        domain.set_boundary({'left': Bd, 'right': Br, 'top': Br, 'bottom': Br})
3901        domain.check_integrity()
3902
3903        # Evolution
3904        for t in domain.evolve(yieldstep = 0.01, finaltime = 0.03):
3905            pass
3906
3907        msg = 'min step was %f instead of %f' %(domain.min_timestep,
3908                                                0.0210448446782) 
3909
3910        assert allclose(domain.min_timestep, 0.0210448446782), msg
3911        assert allclose(domain.max_timestep, 0.0210448446782)
3912
3913        #print domain.quantities['stage'].vertex_values[:4,0]
3914        #print domain.quantities['xmomentum'].vertex_values[:4,0]
3915        #print domain.quantities['ymomentum'].vertex_values[:4,0]
3916
3917        #FIXME: These numbers were from version before 25/10
3918        #assert allclose(domain.quantities['stage'].vertex_values[:4,0],
3919        #                [0.00101913,0.05352143,0.00104852,0.05354394])
3920
3921        #FIXME: These numbers were from version before 21/3/6 -
3922        #could be recreated by setting maximum_allowed_speed to 0 maybe
3923        #assert allclose(domain.quantities['xmomentum'].vertex_values[:4,0],
3924        #                [ 0.00064835, 0.03685719, 0.00085073, 0.03687313])
3925       
3926        assert allclose(domain.quantities['xmomentum'].vertex_values[:4,0],
3927                        [ 0.00090581, 0.03685719, 0.00088303, 0.03687313])
3928                       
3929                       
3930
3931        #assert allclose(domain.quantities['xmomentum'].vertex_values[:4,0],
3932        #                [0.00090581,0.03685719,0.00088303,0.03687313])
3933
3934        assert allclose(domain.quantities['ymomentum'].vertex_values[:4,0],
3935                        [-0.00139463,0.0006156,-0.00060364,0.00061827])
3936
3937
3938        os.remove(domain.get_name() + '.sww')
3939
3940       
3941    def test_flatbed_second_order_vmax_0(self):
3942        from mesh_factory import rectangular
3943        from Numeric import array
3944
3945        #Create basic mesh
3946        N = 8
3947        points, vertices, boundary = rectangular(N, N)
3948
3949        #Create shallow water domain
3950        domain = Domain(points, vertices, boundary)
3951        domain.smooth = False
3952        domain.default_order=2
3953        domain.beta_w      = 0.9
3954        domain.beta_w_dry  = 0.9
3955        domain.beta_uh     = 0.9
3956        domain.beta_uh_dry = 0.9
3957        domain.beta_vh     = 0.9
3958        domain.beta_vh_dry = 0.9       
3959        domain.maximum_allowed_speed = 0.0 #Makes it like the 'oldstyle'
3960        domain.H0 = 0 # Backwards compatibility (6/2/7)
3961        domain.use_centroid_velocities = False # Backwards compatibility (8/5/8)       
3962
3963        # Boundary conditions
3964        Br = Reflective_boundary(domain)
3965        Bd = Dirichlet_boundary([0.2,0.,0.])
3966
3967        domain.set_boundary({'left': Bd, 'right': Br, 'top': Br, 'bottom': Br})
3968        domain.check_integrity()
3969
3970        #Evolution
3971        for t in domain.evolve(yieldstep = 0.01, finaltime = 0.03):
3972            pass
3973
3974
3975        assert allclose(domain.min_timestep, 0.0210448446782)
3976        assert allclose(domain.max_timestep, 0.0210448446782)
3977
3978        #FIXME: These numbers were from version before 21/3/6 -
3979        #could be recreated by setting maximum_allowed_speed to 0 maybe
3980        assert allclose(domain.quantities['xmomentum'].vertex_values[:4,0],
3981                        [ 0.00064835, 0.03685719, 0.00085073, 0.03687313]) 
3982       
3983
3984        assert allclose(domain.quantities['ymomentum'].vertex_values[:4,0],
3985                        [-0.00139463,0.0006156,-0.00060364,0.00061827])
3986
3987
3988        os.remove(domain.get_name() + '.sww')
3989
3990       
3991
3992    def test_flatbed_second_order_distribute(self):
3993        #Use real data from anuga.abstract_2d_finite_volumes 2
3994        #painfully setup and extracted.
3995        from mesh_factory import rectangular
3996        from Numeric import array
3997
3998        #Create basic mesh
3999        N = 8
4000        points, vertices, boundary = rectangular(N, N)
4001
4002        #Create shallow water domain
4003        domain = Domain(points, vertices, boundary)
4004        domain.smooth = False
4005        domain.default_order=domain._order_=2
4006        domain.beta_w      = 0.9
4007        domain.beta_w_dry  = 0.9
4008        domain.beta_uh     = 0.9
4009        domain.beta_uh_dry = 0.9
4010        domain.beta_vh     = 0.9
4011        domain.beta_vh_dry = 0.9
4012        domain.H0 = 0 # Backwards compatibility (6/2/7)
4013        domain.use_centroid_velocities = False # Backwards compatibility (8/5/8)       
4014        domain.set_maximum_allowed_speed(1.0)       
4015
4016        # Boundary conditions
4017        Br = Reflective_boundary(domain)
4018        Bd = Dirichlet_boundary([0.2,0.,0.])
4019
4020        domain.set_boundary({'left': Bd, 'right': Br, 'top': Br, 'bottom': Br})
4021        domain.check_integrity()
4022
4023
4024
4025        for V in [False, True]:
4026            if V:
4027                #Set centroids as if system had been evolved
4028                L = zeros(2*N*N, Float)
4029                L[:32] = [7.21205592e-003, 5.35214298e-002, 1.00910824e-002,
4030                          5.35439433e-002, 1.00910824e-002, 5.35439433e-002,
4031                          1.00910824e-002, 5.35439433e-002, 1.00910824e-002,
4032                          5.35439433e-002, 1.00910824e-002, 5.35439433e-002,
4033                          1.00910824e-002, 5.35393928e-002, 1.02344264e-002,
4034                          5.59605058e-002, 0.00000000e+000, 3.31027800e-004,
4035                          0.00000000e+000, 4.37962142e-005, 0.00000000e+000,
4036                          4.37962142e-005, 0.00000000e+000, 4.37962142e-005,
4037                          0.00000000e+000, 4.37962142e-005, 0.00000000e+000,
4038                          4.37962142e-005, 0.00000000e+000, 4.37962142e-005,
4039                          0.00000000e+000, 5.57305948e-005]
4040
4041                X = zeros(2*N*N, Float)
4042                X[:32] = [6.48351607e-003, 3.68571894e-002, 8.50733285e-003,
4043                          3.68731327e-002, 8.50733285e-003, 3.68731327e-002,
4044                          8.50733285e-003, 3.68731327e-002, 8.50733285e-003,
4045                          3.68731327e-002, 8.50733285e-003, 3.68731327e-002,
4046                          8.50733285e-003, 3.68693861e-002, 8.65220973e-003,
4047                          3.85055387e-002, 0.00000000e+000, 2.86060840e-004,
4048                          0.00000000e+000, 3.58905503e-005, 0.00000000e+000,
4049                          3.58905503e-005, 0.00000000e+000, 3.58905503e-005,
4050                          0.00000000e+000, 3.58905503e-005, 0.00000000e+000,
4051                          3.58905503e-005, 0.00000000e+000, 3.58905503e-005,
4052                          0.00000000e+000, 4.57662812e-005]
4053
4054                Y = zeros(2*N*N, Float)
4055                Y[:32]=[-1.39463104e-003, 6.15600298e-004, -6.03637382e-004,
4056                        6.18272251e-004, -6.03637382e-004, 6.18272251e-004,
4057                        -6.03637382e-004, 6.18272251e-004, -6.03637382e-004,
4058                        6.18272251e-004, -6.03637382e-004, 6.18272251e-004,
4059                        -6.03637382e-004, 6.18599320e-004, -6.74622797e-004,
4060                        -1.48934756e-004, 0.00000000e+000, -5.35079969e-005,
4061                        0.00000000e+000, -2.57264987e-005, 0.00000000e+000,
4062                        -2.57264987e-005, 0.00000000e+000, -2.57264987e-005,
4063                        0.00000000e+000, -2.57264987e-005, 0.00000000e+000,
4064                        -2.57264987e-005, 0.00000000e+000, -2.57264987e-005,
4065                        0.00000000e+000, -2.57635178e-005]
4066
4067
4068                domain.set_quantity('stage', L, location='centroids')
4069                domain.set_quantity('xmomentum', X, location='centroids')
4070                domain.set_quantity('ymomentum', Y, location='centroids')
4071
4072                domain.check_integrity()
4073            else:
4074                #Evolution
4075                for t in domain.evolve(yieldstep = 0.01, finaltime = 0.03):
4076                    pass
4077                assert allclose(domain.min_timestep, 0.0210448446782)
4078                assert allclose(domain.max_timestep, 0.0210448446782)
4079
4080
4081            #Centroids were correct but not vertices.
4082            #Hence the check of distribute below.
4083            assert allclose(domain.quantities['stage'].centroid_values[:4],
4084                            [0.00721206,0.05352143,0.01009108,0.05354394])
4085
4086            assert allclose(domain.quantities['xmomentum'].centroid_values[:4],
4087                            [0.00648352,0.03685719,0.00850733,0.03687313])
4088
4089            assert allclose(domain.quantities['ymomentum'].centroid_values[:4],
4090                            [-0.00139463,0.0006156,-0.00060364,0.00061827])
4091
4092            #print 'C17=', domain.quantities['xmomentum'].centroid_values[17]
4093            #print 'C19=', domain.quantities['xmomentum'].centroid_values[19]
4094
4095            #assert allclose(domain.quantities['xmomentum'].centroid_values[17],0.00028606084)
4096            ##print domain.quantities['xmomentum'].centroid_values[17], V
4097            ##print
4098            if not V:
4099                #FIXME: These numbers were from version before 21/3/6 -
4100                #could be recreated by setting maximum_allowed_speed to 0 maybe           
4101               
4102                #assert allclose(domain.quantities['xmomentum'].centroid_values[17], 0.0)               
4103                assert allclose(domain.quantities['xmomentum'].centroid_values[17], 0.000286060839592)                         
4104
4105            else:
4106                assert allclose(domain.quantities['xmomentum'].centroid_values[17], 0.00028606084)
4107
4108            import copy
4109            XX = copy.copy(domain.quantities['xmomentum'].centroid_values)
4110            assert allclose(domain.quantities['xmomentum'].centroid_values, XX)
4111
4112            domain.distribute_to_vertices_and_edges()
4113
4114            #assert allclose(domain.quantities['xmomentum'].centroid_values, XX)
4115
4116            #assert allclose(domain.quantities['xmomentum'].centroid_values[17],
4117            #                0.0)
4118            assert allclose(domain.quantities['xmomentum'].centroid_values[17], 0.000286060839592)                                                 
4119
4120
4121            #FIXME: These numbers were from version before 25/10
4122            #assert allclose(domain.quantities['stage'].vertex_values[:4,0],
4123            #                [0.00101913,0.05352143,0.00104852,0.05354394])
4124
4125            assert allclose(domain.quantities['ymomentum'].vertex_values[:4,0],
4126                            [-0.00139463,0.0006156,-0.00060364,0.00061827])
4127
4128
4129            assert allclose(domain.quantities['xmomentum'].vertex_values[:4,0],
4130                            [0.00090581,0.03685719,0.00088303,0.03687313])
4131
4132
4133            #NB NO longer relvant:
4134
4135            #This was the culprit. First triangles vertex 0 had an
4136            #x-momentum of 0.0064835 instead of 0.00090581 and
4137            #third triangle had 0.00850733 instead of 0.00088303
4138            #print domain.quantities['xmomentum'].vertex_values[:4,0]
4139
4140            #print domain.quantities['xmomentum'].vertex_values[:4,0]
4141            #assert allclose(domain.quantities['xmomentum'].vertex_values[:4,0],
4142            #                [0.00090581,0.03685719,0.00088303,0.03687313])
4143
4144        os.remove(domain.get_name() + '.sww')
4145
4146
4147
4148    def test_bedslope_problem_first_order(self):
4149
4150        from mesh_factory import rectangular
4151        from Numeric import array
4152
4153        #Create basic mesh
4154        points, vertices, boundary = rectangular(6, 6)
4155
4156        #Create shallow water domain
4157        domain = Domain(points, vertices, boundary)
4158        domain.smooth = False
4159        domain.default_order = 1
4160
4161        #Bed-slope and friction
4162        def x_slope(x, y):
4163            return -x/3
4164
4165        domain.set_quantity('elevation', x_slope)
4166
4167        # Boundary conditions
4168        Br = Reflective_boundary(domain)
4169        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
4170
4171        #Initial condition
4172        #domain.set_quantity('stage', Constant_height(x_slope, 0.05))
4173        domain.set_quantity('stage', expression='elevation+0.05')
4174        domain.check_integrity()
4175
4176        #Evolution
4177        for t in domain.evolve(yieldstep = 0.05, finaltime = 0.05):
4178            pass# domain.write_time()
4179
4180        # FIXME (Ole): Need some other assertion here!
4181        #print domain.min_timestep, domain.max_timestep   
4182        #assert allclose(domain.min_timestep, 0.050010003001)
4183        #assert allclose(domain.max_timestep, 0.050010003001)
4184
4185
4186        os.remove(domain.get_name() + '.sww')
4187       
4188    def test_bedslope_problem_first_order_moresteps(self):
4189
4190        from mesh_factory import rectangular
4191        from Numeric import array
4192
4193        #Create basic mesh
4194        points, vertices, boundary = rectangular(6, 6)
4195
4196        #Create shallow water domain
4197        domain = Domain(points, vertices, boundary)
4198        domain.smooth = False
4199        domain.default_order = 1
4200       
4201        # FIXME (Ole): Need tests where these two are commented out
4202        domain.H0 = 0        # Backwards compatibility (6/2/7)       
4203        domain.tight_slope_limiters = 0 # Backwards compatibility (14/4/7)
4204        domain.use_centroid_velocities = 0 # Backwards compatibility (7/5/8)                 
4205
4206        #Bed-slope and friction
4207        def x_slope(x, y):
4208            return -x/3
4209
4210        domain.set_quantity('elevation', x_slope)
4211
4212        # Boundary conditions
4213        Br = Reflective_boundary(domain)
4214        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
4215
4216        #Initial condition
4217        domain.set_quantity('stage', expression='elevation+0.05')
4218        domain.check_integrity()
4219
4220        #Evolution
4221        for t in domain.evolve(yieldstep = 0.05, finaltime = 0.5):
4222            pass# domain.write_time()
4223
4224        #Data from earlier version of abstract_2d_finite_volumes
4225        #print domain.quantities['stage'].centroid_values
4226
4227        assert allclose(domain.quantities['stage'].centroid_values,
4228                        [-0.02998628, -0.01520652, -0.03043492,
4229                        -0.0149132, -0.03004706, -0.01476251,
4230                        -0.0298215, -0.01467976, -0.02988158,
4231                        -0.01474662, -0.03036161, -0.01442995,
4232                        -0.07624583, -0.06297061, -0.07733792,
4233                        -0.06342237, -0.07695439, -0.06289595,
4234                        -0.07635559, -0.0626065, -0.07633628,
4235                        -0.06280072, -0.07739632, -0.06386738,
4236                        -0.12161738, -0.11028239, -0.1223796,
4237                        -0.11095953, -0.12189744, -0.11048616,
4238                        -0.12074535, -0.10987605, -0.12014311,
4239                        -0.10976691, -0.12096859, -0.11087692,
4240                        -0.16868259, -0.15868061, -0.16801135,
4241                        -0.1588003, -0.16674343, -0.15813323,
4242                        -0.16457595, -0.15693826, -0.16281096,
4243                        -0.15585154, -0.16283873, -0.15540068,
4244                        -0.17450362, -0.19919913, -0.18062882,
4245                        -0.19764131, -0.17783111, -0.19407213,
4246                        -0.1736915, -0.19053624, -0.17228678,
4247                        -0.19105634, -0.17920133, -0.1968828,
4248                        -0.14244395, -0.14604641, -0.14473537,
4249                        -0.1506107, -0.14510055, -0.14919522,
4250                        -0.14175896, -0.14560798, -0.13911658,
4251                        -0.14439383, -0.13924047, -0.14829043])
4252
4253        os.remove(domain.get_name() + '.sww')
4254       
4255    def test_bedslope_problem_second_order_one_step(self):
4256
4257        from mesh_factory import rectangular
4258        from Numeric import array
4259
4260        #Create basic mesh
4261        points, vertices, boundary = rectangular(6, 6)
4262
4263        #Create shallow water domain
4264        domain = Domain(points, vertices, boundary)
4265        domain.smooth = False
4266        domain.default_order=2
4267        domain.beta_w      = 0.9
4268        domain.beta_w_dry  = 0.9
4269        domain.beta_uh     = 0.9
4270        domain.beta_uh_dry = 0.9
4271        domain.beta_vh     = 0.9
4272        domain.beta_vh_dry = 0.9
4273
4274       
4275        # FIXME (Ole): Need tests where this is commented out
4276        domain.tight_slope_limiters = 0 # Backwards compatibility (14/4/7)
4277        domain.use_centroid_velocities = 0 # Backwards compatibility (7/5/8)     
4278       
4279        #Bed-slope and friction at vertices (and interpolated elsewhere)
4280        def x_slope(x, y):
4281            return -x/3
4282
4283        domain.set_quantity('elevation', x_slope)
4284
4285        # Boundary conditions
4286        Br = Reflective_boundary(domain)
4287        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
4288
4289        #Initial condition
4290        domain.set_quantity('stage', expression='elevation+0.05')
4291        domain.check_integrity()
4292
4293        assert allclose(domain.quantities['stage'].centroid_values,
4294                        [0.01296296, 0.03148148, 0.01296296,
4295                        0.03148148, 0.01296296, 0.03148148,
4296                        0.01296296, 0.03148148, 0.01296296,
4297                        0.03148148, 0.01296296, 0.03148148,
4298                        -0.04259259, -0.02407407, -0.04259259,
4299                        -0.02407407, -0.04259259, -0.02407407,
4300                        -0.04259259, -0.02407407, -0.04259259,
4301                        -0.02407407, -0.04259259, -0.02407407,
4302                        -0.09814815, -0.07962963, -0.09814815,
4303                        -0.07962963, -0.09814815, -0.07962963,
4304                        -0.09814815, -0.07962963, -0.09814815,
4305                        -0.07962963, -0.09814815, -0.07962963,
4306                        -0.1537037 , -0.13518519, -0.1537037,
4307                        -0.13518519, -0.1537037, -0.13518519,
4308                        -0.1537037 , -0.13518519, -0.1537037,
4309                        -0.13518519, -0.1537037, -0.13518519,
4310                        -0.20925926, -0.19074074, -0.20925926,
4311                        -0.19074074, -0.20925926, -0.19074074,
4312                        -0.20925926, -0.19074074, -0.20925926,
4313                        -0.19074074, -0.20925926, -0.19074074,
4314                        -0.26481481, -0.2462963, -0.26481481,
4315                        -0.2462963, -0.26481481, -0.2462963,
4316                        -0.26481481, -0.2462963, -0.26481481,
4317                        -0.2462963, -0.26481481, -0.2462963])
4318
4319
4320        #print domain.quantities['stage'].extrapolate_second_order()
4321        #domain.distribute_to_vertices_and_edges()
4322        #print domain.quantities['stage'].vertex_values[:,0]
4323
4324        #Evolution
4325        for t in domain.evolve(yieldstep = 0.05, finaltime = 0.05):
4326            #domain.write_time()
4327            pass
4328
4329
4330        #print domain.quantities['stage'].centroid_values
4331        assert allclose(domain.quantities['stage'].centroid_values,
4332                 [0.01290985, 0.02356019, 0.01619096, 0.02356019, 0.01619096,
4333                  0.02356019, 0.01619096, 0.02356019, 0.01619096, 0.02356019,
4334                  0.01619096, 0.0268413, -0.04411074, -0.0248011, -0.04186556,
4335                  -0.0248011, -0.04186556, -0.0248011, -0.04186556, -0.0248011,
4336                  -0.04186556, -0.0248011, -0.04186556, -0.02255593,
4337                  -0.09966629, -0.08035666, -0.09742112, -0.08035666,
4338                  -0.09742112, -0.08035666, -0.09742112, -0.08035666,
4339                  -0.09742112, -0.08035666, -0.09742112, -0.07811149,
4340                  -0.15522185, -0.13591222, -0.15297667, -0.13591222,
4341                  -0.15297667, -0.13591222, -0.15297667, -0.13591222,
4342                  -0.15297667, -0.13591222, -0.15297667, -0.13366704,
4343                  -0.2107774, -0.19146777, -0.20853223, -0.19146777,
4344                  -0.20853223, -0.19146777, -0.20853223, -0.19146777,
4345                  -0.20853223, -0.19146777, -0.20853223, -0.1892226,
4346                  -0.26120669, -0.24776246, -0.25865535, -0.24776246,
4347                  -0.25865535, -0.24776246, -0.25865535, -0.24776246,
4348                  -0.25865535, -0.24776246, -0.25865535, -0.24521113])
4349
4350        os.remove(domain.get_name() + '.sww')
4351
4352    def test_bedslope_problem_second_order_two_steps(self):
4353
4354        from mesh_factory import rectangular
4355        from Numeric import array
4356
4357        #Create basic mesh
4358        points, vertices, boundary = rectangular(6, 6)
4359
4360        #Create shallow water domain
4361        domain = Domain(points, vertices, boundary)
4362        domain.smooth = False
4363        domain.default_order=2
4364        domain.beta_w      = 0.9
4365        domain.beta_w_dry  = 0.9
4366        domain.beta_uh     = 0.9
4367        domain.beta_uh_dry = 0.9
4368        domain.beta_vh     = 0.9
4369        domain.beta_vh_dry = 0.9
4370       
4371        # FIXME (Ole): Need tests where this is commented out
4372        domain.tight_slope_limiters = 0 # Backwards compatibility (14/4/7)                 
4373        domain.H0 = 0 # Backwards compatibility (6/2/7)
4374        domain.use_centroid_velocities = 0 # Backwards compatibility (7/5/8)
4375       
4376
4377        #Bed-slope and friction at vertices (and interpolated elsewhere)
4378        def x_slope(x, y):
4379            return -x/3
4380
4381        domain.set_quantity('elevation', x_slope)
4382
4383        # Boundary conditions
4384        Br = Reflective_boundary(domain)
4385        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
4386
4387        #Initial condition
4388        domain.set_quantity('stage', expression='elevation+0.05')
4389        domain.check_integrity()
4390
4391        assert allclose(domain.quantities['stage'].centroid_values,
4392                        [0.01296296, 0.03148148, 0.01296296,
4393                        0.03148148, 0.01296296, 0.03148148,
4394                        0.01296296, 0.03148148, 0.01296296,
4395                        0.03148148, 0.01296296, 0.03148148,
4396                        -0.04259259, -0.02407407, -0.04259259,
4397                        -0.02407407, -0.04259259, -0.02407407,
4398                        -0.04259259, -0.02407407, -0.04259259,
4399                        -0.02407407, -0.04259259, -0.02407407,
4400                        -0.09814815, -0.07962963, -0.09814815,
4401                        -0.07962963, -0.09814815, -0.07962963,
4402                        -0.09814815, -0.07962963, -0.09814815,
4403                        -0.07962963, -0.09814815, -0.07962963,
4404                        -0.1537037 , -0.13518519, -0.1537037,
4405                        -0.13518519, -0.1537037, -0.13518519,
4406                        -0.1537037 , -0.13518519, -0.1537037,
4407                        -0.13518519, -0.1537037, -0.13518519,
4408                        -0.20925926, -0.19074074, -0.20925926,
4409                        -0.19074074, -0.20925926, -0.19074074,
4410                        -0.20925926, -0.19074074, -0.20925926,
4411                        -0.19074074, -0.20925926, -0.19074074,
4412                        -0.26481481, -0.2462963, -0.26481481,
4413                        -0.2462963, -0.26481481, -0.2462963,
4414                        -0.26481481, -0.2462963, -0.26481481,
4415                        -0.2462963, -0.26481481, -0.2462963])
4416
4417
4418        #print domain.quantities['stage'].extrapolate_second_order()
4419        #domain.distribute_to_vertices_and_edges()
4420        #print domain.quantities['stage'].vertex_values[:,0]
4421
4422        #Evolution
4423        for t in domain.evolve(yieldstep = 0.05, finaltime = 0.1):
4424            pass
4425
4426
4427        #Data from earlier version of abstract_2d_finite_volumes ft=0.1
4428        assert allclose(domain.min_timestep, 0.0376895634803)
4429        assert allclose(domain.max_timestep, 0.0415635655309)
4430
4431
4432        assert allclose(domain.quantities['stage'].centroid_values,
4433                        [0.00855788, 0.01575204, 0.00994606, 0.01717072,
4434                         0.01005985, 0.01716362, 0.01005985, 0.01716299,
4435                         0.01007098, 0.01736248, 0.01216452, 0.02026776,
4436                         -0.04462374, -0.02479045, -0.04199789, -0.0229465,
4437                         -0.04184033, -0.02295693, -0.04184013, -0.02295675,
4438                         -0.04184486, -0.0228168, -0.04028876, -0.02036486,
4439                         -0.10029444, -0.08170809, -0.09772846, -0.08021704,
4440                         -0.09760006, -0.08022143, -0.09759984, -0.08022124,
4441                         -0.09760261, -0.08008893, -0.09603914, -0.07758209,
4442                         -0.15584152, -0.13723138, -0.15327266, -0.13572906,
4443                         -0.15314427, -0.13573349, -0.15314405, -0.13573331,
4444                         -0.15314679, -0.13560104, -0.15158523, -0.13310701,
4445                         -0.21208605, -0.19283913, -0.20955631, -0.19134189,
4446                         -0.20942821, -0.19134598, -0.20942799, -0.1913458,
4447                         -0.20943005, -0.19120952, -0.20781177, -0.18869401,
4448                         -0.25384082, -0.2463294, -0.25047649, -0.24464654,
4449                         -0.25031159, -0.24464253, -0.25031112, -0.24464253,
4450                         -0.25031463, -0.24454764, -0.24885323, -0.24286438])
4451
4452
4453        os.remove(domain.get_name() + '.sww')
4454
4455    def test_bedslope_problem_second_order_two_yieldsteps(self):
4456
4457        from mesh_factory import rectangular
4458        from Numeric import array
4459
4460        #Create basic mesh
4461        points, vertices, boundary = rectangular(6, 6)
4462
4463        #Create shallow water domain
4464        domain = Domain(points, vertices, boundary)
4465        domain.smooth = False
4466        domain.default_order=2
4467        domain.beta_w      = 0.9
4468        domain.beta_w_dry  = 0.9
4469        domain.beta_uh     = 0.9
4470        domain.beta_uh_dry = 0.9
4471        domain.beta_vh     = 0.9
4472        domain.beta_vh_dry = 0.9
4473       
4474        # FIXME (Ole): Need tests where this is commented out
4475        domain.tight_slope_limiters = 0 # Backwards compatibility (14/4/7)                 
4476        domain.H0 = 0 # Backwards compatibility (6/2/7)
4477        domain.use_centroid_velocities = 0 # Backwards compatibility (7/5/8)
4478       
4479
4480        #Bed-slope and friction at vertices (and interpolated elsewhere)
4481        def x_slope(x, y):
4482            return -x/3
4483
4484        domain.set_quantity('elevation', x_slope)
4485
4486        # Boundary conditions
4487        Br = Reflective_boundary(domain)
4488        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
4489
4490        #Initial condition
4491        domain.set_quantity('stage', expression='elevation+0.05')
4492        domain.check_integrity()
4493
4494        assert allclose(domain.quantities['stage'].centroid_values,
4495                        [0.01296296, 0.03148148, 0.01296296,
4496                        0.03148148, 0.01296296, 0.03148148,
4497                        0.01296296, 0.03148148, 0.01296296,
4498                        0.03148148, 0.01296296, 0.03148148,
4499                        -0.04259259, -0.02407407, -0.04259259,
4500                        -0.02407407, -0.04259259, -0.02407407,
4501                        -0.04259259, -0.02407407, -0.04259259,
4502                        -0.02407407, -0.04259259, -0.02407407,
4503                        -0.09814815, -0.07962963, -0.09814815,
4504                        -0.07962963, -0.09814815, -0.07962963,
4505                        -0.09814815, -0.07962963, -0.09814815,
4506                        -0.07962963, -0.09814815, -0.07962963,
4507                        -0.1537037 , -0.13518519, -0.1537037,
4508                        -0.13518519, -0.1537037, -0.13518519,
4509                        -0.1537037 , -0.13518519, -0.1537037,
4510                        -0.13518519, -0.1537037, -0.13518519,
4511                        -0.20925926, -0.19074074, -0.20925926,
4512                        -0.19074074, -0.20925926, -0.19074074,
4513                        -0.20925926, -0.19074074, -0.20925926,
4514                        -0.19074074, -0.20925926, -0.19074074,
4515                        -0.26481481, -0.2462963, -0.26481481,
4516                        -0.2462963, -0.26481481, -0.2462963,
4517                        -0.26481481, -0.2462963, -0.26481481,
4518                        -0.2462963, -0.26481481, -0.2462963])
4519
4520
4521        #print domain.quantities['stage'].extrapolate_second_order()
4522        #domain.distribute_to_vertices_and_edges()
4523        #print domain.quantities['stage'].vertex_values[:,0]
4524
4525        #Evolution
4526        for t in domain.evolve(yieldstep = 0.05, finaltime = 0.1):   #0.05??
4527            #domain.write_time()
4528            pass
4529
4530
4531
4532        assert allclose(domain.quantities['stage'].centroid_values,
4533                 [0.00855788, 0.01575204, 0.00994606, 0.01717072, 0.01005985,
4534                  0.01716362, 0.01005985, 0.01716299, 0.01007098, 0.01736248,
4535                  0.01216452, 0.02026776, -0.04462374, -0.02479045, -0.04199789,
4536                  -0.0229465, -0.04184033, -0.02295693, -0.04184013,
4537                  -0.02295675, -0.04184486, -0.0228168, -0.04028876,
4538                  -0.02036486, -0.10029444, -0.08170809, -0.09772846,
4539                  -0.08021704, -0.09760006, -0.08022143, -0.09759984,
4540                  -0.08022124, -0.09760261, -0.08008893, -0.09603914,
4541                  -0.07758209, -0.15584152, -0.13723138, -0.15327266,
4542                  -0.13572906, -0.15314427, -0.13573349, -0.15314405,
4543                  -0.13573331, -0.15314679, -0.13560104, -0.15158523,
4544                  -0.13310701, -0.21208605, -0.19283913, -0.20955631,
4545                  -0.19134189, -0.20942821, -0.19134598, -0.20942799,
4546                  -0.1913458, -0.20943005, -0.19120952, -0.20781177,
4547                  -0.18869401, -0.25384082, -0.2463294, -0.25047649,
4548                  -0.24464654, -0.25031159, -0.24464253, -0.25031112,
4549                  -0.24464253, -0.25031463, -0.24454764, -0.24885323,
4550                  -0.24286438])
4551
4552        os.remove(domain.get_name() + '.sww')
4553
4554    def test_bedslope_problem_second_order_more_steps(self):
4555
4556        from mesh_factory import rectangular
4557        from Numeric import array
4558
4559        #Create basic mesh
4560        points, vertices, boundary = rectangular(6, 6)
4561
4562        #Create shallow water domain
4563        domain = Domain(points, vertices, boundary)
4564        domain.smooth = False
4565        domain.default_order=2
4566        domain.beta_w      = 0.9
4567        domain.beta_w_dry  = 0.9
4568        domain.beta_uh     = 0.9
4569        domain.beta_uh_dry = 0.9
4570        domain.beta_vh     = 0.9
4571        domain.beta_vh_dry = 0.9
4572       
4573       
4574        # FIXME (Ole): Need tests where these two are commented out
4575        domain.H0 = 0        # Backwards compatibility (6/2/7)       
4576        domain.tight_slope_limiters = 0 # Backwards compatibility (14/4/7)                 
4577        domain.use_centroid_velocities = 0 # Backwards compatibility (7/5/8)
4578       
4579               
4580
4581        #Bed-slope and friction at vertices (and interpolated elsewhere)
4582        def x_slope(x, y):
4583            return -x/3
4584
4585        domain.set_quantity('elevation', x_slope)
4586
4587        # Boundary conditions
4588        Br = Reflective_boundary(domain)
4589        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
4590
4591        #Initial condition
4592        domain.set_quantity('stage', expression = 'elevation + 0.05')
4593        domain.check_integrity()
4594
4595        assert allclose(domain.quantities['stage'].centroid_values,
4596                        [0.01296296, 0.03148148, 0.01296296,
4597                        0.03148148, 0.01296296, 0.03148148,
4598                        0.01296296, 0.03148148, 0.01296296,
4599                        0.03148148, 0.01296296, 0.03148148,
4600                        -0.04259259, -0.02407407, -0.04259259,
4601                        -0.02407407, -0.04259259, -0.02407407,
4602                        -0.04259259, -0.02407407, -0.04259259,
4603                        -0.02407407, -0.04259259, -0.02407407,
4604                        -0.09814815, -0.07962963, -0.09814815,
4605                        -0.07962963, -0.09814815, -0.07962963,
4606                        -0.09814815, -0.07962963, -0.09814815,
4607                        -0.07962963, -0.09814815, -0.07962963,
4608                        -0.1537037 , -0.13518519, -0.1537037,
4609                        -0.13518519, -0.1537037, -0.13518519,
4610                        -0.1537037 , -0.13518519, -0.1537037,
4611                        -0.13518519, -0.1537037, -0.13518519,
4612                        -0.20925926, -0.19074074, -0.20925926,
4613                        -0.19074074, -0.20925926, -0.19074074,
4614                        -0.20925926, -0.19074074, -0.20925926,
4615                        -0.19074074, -0.20925926, -0.19074074,
4616                        -0.26481481, -0.2462963, -0.26481481,
4617                        -0.2462963, -0.26481481, -0.2462963,
4618                        -0.26481481, -0.2462963, -0.26481481,
4619                        -0.2462963, -0.26481481, -0.2462963])
4620
4621
4622        #print domain.quantities['stage'].extrapolate_second_order()
4623        #domain.distribute_to_vertices_and_edges()
4624        #print domain.quantities['stage'].vertex_values[:,0]
4625
4626        #Evolution
4627        for t in domain.evolve(yieldstep = 0.05, finaltime = 0.5):
4628
4629            # Check that diagnostics works
4630            msg = domain.timestepping_statistics(track_speeds=True)
4631            #FIXME(Ole): One might check the contents of msg here.
4632
4633
4634
4635        assert allclose(domain.quantities['stage'].centroid_values,
4636     [-0.02907028, -0.01475478, -0.02973417, -0.01447186, -0.02932665, -0.01428285,
4637      -0.02901975, -0.0141361,  -0.02898816, -0.01418135, -0.02961409, -0.01403487,
4638      -0.07597998, -0.06252591, -0.07664854, -0.06312532, -0.07638287, -0.06265139,
4639      -0.07571145, -0.06235231, -0.0756817,  -0.06245309, -0.07652292, -0.06289946,
4640      -0.12367464, -0.11088981, -0.12237277, -0.11115338, -0.1218934,  -0.1107174,
4641      -0.12081485, -0.11000491, -0.12038451, -0.11010335, -0.12102113, -0.11012105,
4642      -0.16909116, -0.15831543, -0.16730214, -0.15786249, -0.1665493,  -0.15697919,
4643      -0.16496618, -0.15559852, -0.16338679, -0.15509088, -0.16364092, -0.15424423,
4644      -0.18771107, -0.19903904, -0.18903759, -0.19858437, -0.18701552, -0.19697797,
4645      -0.1833593,  -0.19505871, -0.1818806,  -0.19418042, -0.18586159, -0.19576946,
4646      -0.13986873, -0.14170053, -0.14132188, -0.14560674, -0.14095617, -0.14373292,
4647      -0.13785933, -0.14033364, -0.13592955, -0.13936356, -0.13596008, -0.14216296])
4648
4649        assert allclose(domain.quantities['xmomentum'].centroid_values,
4650     [ 0.00831121,  0.00317948,  0.00731797,  0.00334939,  0.00764717,  0.00348053,
4651       0.00788729,  0.00356522,  0.00780649,  0.00341919,  0.00693525,  0.00310375,
4652       0.02166196,  0.01421475,  0.02017737,  0.01316839,  0.02037015,  0.01368659,
4653       0.02106,     0.01399161,  0.02074514,  0.01354935,  0.01887407,  0.0123113,
4654       0.03775083,  0.02855197,  0.03689337,  0.02759782,  0.03732848,  0.02812072,
4655       0.03872545,  0.02913348,  0.03880939,  0.02803804,  0.03546499,  0.0260039,
4656       0.0632131,   0.04730634,  0.0576324,   0.04592336,  0.05790921,  0.04690514,
4657       0.05986467,  0.04871165,  0.06170068,  0.04811572,  0.05657041,  0.04416292,
4658       0.08489642,  0.07188097,  0.07835261,  0.06843406,  0.07986412,  0.0698247,
4659       0.08201071,  0.07216756,  0.08378418,  0.07273624,  0.080399,    0.06645841,
4660       0.01631548,  0.04691608,  0.0206632,   0.044409,    0.02115518,  0.04560305,
4661       0.02160608,  0.04663725,  0.02174734,  0.04795559,  0.02281427,  0.05667111])
4662
4663
4664        assert allclose(domain.quantities['ymomentum'].centroid_values,
4665     [ 1.45876601e-004, -3.24627393e-004, -1.57572719e-004, -2.92790187e-004,
4666      -9.90988382e-005, -3.06677335e-004, -1.62493106e-004, -3.71310004e-004,
4667      -1.99445058e-004, -3.28493467e-004,  6.68217349e-005, -8.42042805e-006,
4668       5.05093371e-004, -1.42842214e-004, -6.81454718e-005, -5.02084057e-004,
4669      -8.50583861e-005, -4.65443981e-004, -1.96406564e-004, -5.88889562e-004,
4670      -2.70160173e-004, -5.35485454e-004,  2.60780997e-004,  3.12145471e-005,
4671       5.16189608e-004,  1.07069062e-004,  9.29989252e-005, -3.71211119e-004,
4672       1.16350246e-004, -3.82407830e-004, -1.62077969e-004, -6.30906636e-004,
4673      -4.74025708e-004, -6.94463009e-004,  6.15092843e-005,  2.22106820e-004,
4674      -6.29589294e-004,  2.43611937e-004, -5.88125094e-004, -6.94293192e-005,
4675      -4.17914641e-004,  6.64609019e-005, -7.68334577e-004, -3.40232101e-004,
4676      -1.67424308e-003, -7.39485066e-004, -1.59966988e-003,  5.68262838e-005,
4677      -1.48470633e-003, -1.84554882e-003, -2.27200099e-003, -1.67506848e-003,
4678      -1.95610258e-003, -1.47638801e-003, -1.73779477e-003, -1.85498791e-003,
4679      -2.01357843e-003, -2.17675471e-003, -1.65783870e-003, -1.15818681e-003,
4680      -1.18663036e-003, -2.94229849e-003, -3.59309018e-003, -5.13496584e-003,
4681      -6.17359400e-003, -5.98761937e-003, -6.00540116e-003, -5.01121966e-003,
4682      -4.50964850e-003, -3.06319963e-003,  6.08950810e-004, -4.79537921e-004])
4683
4684        os.remove(domain.get_name() + '.sww')
4685
4686
4687
4688    def NOtest_bedslope_problem_second_order_more_steps_feb_2007(self):
4689        """test_bedslope_problem_second_order_more_steps_feb_2007
4690
4691        Test shallow water finite volumes, using parameters from
4692        feb 2007 rather than backward compatibility ad infinitum
4693       
4694        """
4695        from mesh_factory import rectangular
4696        from Numeric import array
4697
4698        #Create basic mesh
4699        points, vertices, boundary = rectangular(6, 6)
4700
4701        #Create shallow water domain
4702        domain = Domain(points, vertices, boundary)
4703        domain.smooth = False
4704        domain.default_order = 2
4705        domain.beta_w      = 0.9
4706        domain.beta_w_dry  = 0.9
4707        domain.beta_uh     = 0.9
4708        domain.beta_uh_dry = 0.9
4709        domain.beta_vh     = 0.9
4710        domain.beta_vh_dry = 0.9
4711        domain.H0 = 0.001
4712        domain.tight_slope_limiters = 1
4713
4714        #Bed-slope and friction at vertices (and interpolated elsewhere)
4715        def x_slope(x, y):
4716            return -x/3
4717
4718        domain.set_quantity('elevation', x_slope)
4719
4720        # Boundary conditions
4721        Br = Reflective_boundary(domain)
4722        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
4723
4724        #Initial condition
4725        domain.set_quantity('stage', expression = 'elevation + 0.05')
4726        domain.check_integrity()
4727
4728        assert allclose(domain.quantities['stage'].centroid_values,
4729                        [0.01296296, 0.03148148, 0.01296296,
4730                        0.03148148, 0.01296296, 0.03148148,
4731                        0.01296296, 0.03148148, 0.01296296,
4732                        0.03148148, 0.01296296, 0.03148148,
4733                        -0.04259259, -0.02407407, -0.04259259,
4734                        -0.02407407, -0.04259259, -0.02407407,
4735                        -0.04259259, -0.02407407, -0.04259259,
4736                        -0.02407407, -0.04259259, -0.02407407,
4737                        -0.09814815, -0.07962963, -0.09814815,
4738                        -0.07962963, -0.09814815, -0.07962963,
4739                        -0.09814815, -0.07962963, -0.09814815,
4740                        -0.07962963, -0.09814815, -0.07962963,
4741                        -0.1537037 , -0.13518519, -0.1537037,
4742                        -0.13518519, -0.1537037, -0.13518519,
4743                        -0.1537037 , -0.13518519, -0.1537037,
4744                        -0.13518519, -0.1537037, -0.13518519,
4745                        -0.20925926, -0.19074074, -0.20925926,
4746                        -0.19074074, -0.20925926, -0.19074074,
4747                        -0.20925926, -0.19074074, -0.20925926,
4748                        -0.19074074, -0.20925926, -0.19074074,
4749                        -0.26481481, -0.2462963, -0.26481481,
4750                        -0.2462963, -0.26481481, -0.2462963,
4751                        -0.26481481, -0.2462963, -0.26481481,
4752                        -0.2462963, -0.26481481, -0.2462963])
4753
4754
4755        #print domain.quantities['stage'].extrapolate_second_order()
4756        #domain.distribute_to_vertices_and_edges()
4757        #print domain.quantities['stage'].vertex_values[:,0]
4758
4759        #Evolution
4760        for t in domain.evolve(yieldstep = 0.05, finaltime = 0.5):
4761            pass
4762
4763
4764        #print domain.quantities['stage'].centroid_values
4765           
4766        assert allclose(domain.quantities['stage'].centroid_values,
4767         [-0.03348416, -0.01749303, -0.03299091, -0.01739241, -0.03246447, -0.01732016,
4768          -0.03205390, -0.01717833, -0.03146383, -0.01699831, -0.03076577, -0.01671795,
4769          -0.07952656, -0.06684763, -0.07721455, -0.06668388, -0.07632976, -0.06600113,
4770          -0.07523678, -0.06546373, -0.07447040, -0.06508861, -0.07438723, -0.06359288,
4771          -0.12526729, -0.11205668, -0.12179433, -0.11068104, -0.12048395, -0.10968948,
4772          -0.11912023, -0.10862628, -0.11784090, -0.10803744, -0.11790629, -0.10742354,
4773          -0.16859613, -0.15427413, -0.16664444, -0.15464452, -0.16570816, -0.15327556,
4774          -0.16409162, -0.15204092, -0.16264608, -0.15102139, -0.16162736, -0.14969205,
4775          -0.18736511, -0.19874036, -0.18811230, -0.19758289, -0.18590182, -0.19580301,
4776          -0.18234588, -0.19423215, -0.18100376, -0.19380116, -0.18509710, -0.19501636,
4777          -0.13982382, -0.14166819, -0.14132775, -0.14528694, -0.14096905, -0.14351126,
4778          -0.13800356, -0.14027920, -0.13613538, -0.13936795, -0.13621902, -0.14204982])
4779
4780                     
4781        assert allclose(domain.quantities['xmomentum'].centroid_values,
4782      [0.00600290,  0.00175780,  0.00591905,  0.00190903,  0.00644462,  0.00203095,
4783       0.00684561,  0.00225089,  0.00708208,  0.00236235,  0.00649095,  0.00222343,
4784       0.02068693,  0.01164034,  0.01983343,  0.01159526,  0.02044611,  0.01233252,
4785       0.02135685,  0.01301289,  0.02161290,  0.01260280,  0.01867612,  0.01133078,
4786       0.04091313,  0.02668283,  0.03634781,  0.02733469,  0.03767692,  0.02836840,
4787       0.03906338,  0.02958073,  0.04025669,  0.02953292,  0.03665616,  0.02583565,
4788       0.06314558,  0.04830935,  0.05663609,  0.04564362,  0.05756200,  0.04739673,
4789       0.05967379,  0.04919083,  0.06124330,  0.04965808,  0.05879240,  0.04629319,
4790       0.08220739,  0.06924725,  0.07713556,  0.06782640,  0.07909499,  0.06992544,
4791       0.08116621,  0.07210181,  0.08281548,  0.07222669,  0.07941059,  0.06755612,
4792       0.01581588,  0.04533609,  0.02017939,  0.04342565,  0.02073232,  0.04476108,
4793       0.02117439,  0.04573358,  0.02129473,  0.04694267,  0.02220398,  0.05533458])
4794
4795       
4796        assert allclose(domain.quantities['ymomentum'].centroid_values,
4797     [-7.65882069e-005, -1.46087080e-004, -1.09630102e-004, -7.80950424e-005,
4798      -1.15922807e-005, -9.09134899e-005, -1.35994542e-004, -1.95673476e-004,
4799      -4.25779199e-004, -2.95890312e-004, -4.00060341e-004, -9.42021290e-005,
4800      -3.41372596e-004, -1.54560195e-004, -2.94810038e-004, -1.08844546e-004,
4801      -6.97240892e-005,  3.50299623e-005, -2.40159184e-004, -2.01805883e-004,
4802      -7.60732405e-004, -5.10897642e-004, -1.00940001e-003, -1.38037759e-004,
4803      -1.06169131e-003, -3.12307760e-004, -9.90602307e-004, -4.21634250e-005,
4804      -6.02424239e-004,  1.52230578e-004, -7.63833035e-004, -1.10273481e-004,
4805      -1.40187071e-003, -5.57831837e-004, -1.63988285e-003, -2.48018092e-004,
4806      -1.83309840e-003, -6.19360836e-004, -1.29955242e-003, -3.76237145e-004,
4807      -1.00613007e-003, -8.63641918e-005, -1.13604124e-003, -3.90589728e-004,
4808      -1.91457355e-003, -9.43783961e-004, -2.28090840e-003, -5.79107025e-004,
4809      -1.54091533e-003, -2.39785792e-003, -2.47947427e-003, -2.02694009e-003,
4810      -2.10441194e-003, -1.82082650e-003, -1.80229336e-003, -2.10418336e-003,
4811      -1.93104408e-003, -2.23200334e-003, -1.57239706e-003, -1.31486358e-003,
4812      -1.17564993e-003, -2.85846494e-003, -3.52956754e-003, -5.12658193e-003,
4813      -6.24238960e-003, -6.01820113e-003, -6.09602201e-003, -5.04787190e-003,
4814      -4.59373845e-003, -3.01393146e-003,  5.08550095e-004, -4.35896549e-004])
4815
4816        os.remove(domain.get_name() + '.sww')
4817
4818
4819    def test_temp_play(self):
4820
4821        from mesh_factory import rectangular
4822        from Numeric import array
4823
4824        #Create basic mesh
4825        points, vertices, boundary = rectangular(5, 5)
4826
4827        #Create shallow water domain
4828        domain = Domain(points, vertices, boundary)
4829        domain.smooth = False
4830        domain.default_order=2
4831        domain.beta_w      = 0.9
4832        domain.beta_w_dry  = 0.9
4833        domain.beta_uh     = 0.9
4834        domain.beta_uh_dry = 0.9
4835        domain.beta_vh     = 0.9
4836        domain.beta_vh_dry = 0.9
4837       
4838        # FIXME (Ole): Need tests where these two are commented out
4839        domain.H0 = 0        # Backwards compatibility (6/2/7)       
4840        domain.tight_slope_limiters = False # Backwards compatibility (14/4/7)
4841        domain.use_centroid_velocities = False # Backwards compatibility (7/5/8)
4842        domain.use_edge_limiter = False # Backwards compatibility (9/5/8)       
4843       
4844
4845        #Bed-slope and friction at vertices (and interpolated elsewhere)
4846        def x_slope(x, y):
4847            return -x/3
4848
4849        domain.set_quantity('elevation', x_slope)
4850
4851        # Boundary conditions
4852        Br = Reflective_boundary(domain)
4853        domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
4854
4855        #Initial condition
4856        domain.set_quantity('stage', expression='elevation+0.05')
4857        domain.check_integrity()
4858
4859        #Evolution
4860        for t in domain.evolve(yieldstep = 0.05, finaltime = 0.1):
4861            pass
4862
4863        assert allclose(domain.quantities['stage'].centroid_values[:4],
4864                        [0.00206836, 0.01296714, 0.00363415, 0.01438924])
4865        #print domain.quantities['xmomentum'].centroid_values[:4]
4866        assert allclose(domain.quantities['xmomentum'].centroid_values[:4],
4867                        [0.01360154, 0.00671133, 0.01264578, 0.00648503])
4868        assert allclose(domain.quantities['ymomentum'].centroid_values[:4],
4869                        [-1.19201077e-003, -7.23647546e-004,
4870                        -6.39083123e-005, 6.29815168e-005])
4871
4872        os.remove(domain.get_name() + '.sww')
4873
4874    def test_complex_bed(self):
4875        #No friction is tested here
4876
4877        from mesh_factory import rectangular
4878        from Numeric import array
4879
4880        N = 12
4881        points, vertices, boundary = rectangular(N, N/2, len1=1.2,len2=0.6,
4882                                                 origin=(-0.07, 0))
4883
4884
4885        domain = Domain(points, vertices, boundary)
4886        domain.smooth = False
4887        domain.default_order=2
4888
4889
4890        inflow_stage = 0.1
4891        Z = Weir(inflow_stage)
4892        domain.set_quantity('elevation', Z)
4893
4894        Br = Reflective_boundary(domain)
4895        Bd = Dirichlet_boundary([inflow_stage, 0.0, 0.0])
4896        domain.set_boundary({'left': Bd, 'right': Br, 'bottom': Br, 'top': Br})
4897
4898        domain.set_quantity('stage', expression='elevation')
4899
4900        for t in domain.evolve(yieldstep = 0.02, finaltime = 0.2):
4901            pass
4902
4903
4904        #print domain.quantities['stage'].centroid_values
4905
4906        #FIXME: These numbers were from version before 25/10
4907        #assert allclose(domain.quantities['stage'].centroid_values,
4908# [3.95822638e-002,  5.61022588e-002,  4.66437868e-002,  5.73081011e-002,
4909#  4.72394613e-002,  5.74684939e-002,  4.74309483e-002,  5.77458084e-002,
4910#  4.80628177e-002,  5.85656225e-002,  4.90498542e-002,  6.02609831e-002,
4911#  1.18470315e-002,  1.75136443e-002,  1.18035266e-002,  2.15565695e-002,
4912#  1.31620268e-002,  2.14351640e-002,  1.32351076e-002,  2.15450687e-002,
4913#  1.36414028e-002,  2.24274619e-002,  1.51689511e-002,  2.21789655e-002,
4914# -7.54337535e-003, -6.86362021e-004, -7.74146760e-003, -1.83756530e-003,
4915# -8.16773628e-003, -4.49916813e-004, -8.08202599e-003, -3.91118720e-004,
4916# -8.10292716e-003, -3.88584984e-004, -7.35226124e-003,  2.73985295e-004,
4917#  1.86166683e-001,  8.74070369e-002,  1.86166712e-001,  8.74035875e-002,
4918#  6.11666935e-002, -3.76173225e-002, -6.38333276e-002, -3.76147365e-002,
4919#  6.11666725e-002,  8.73846774e-002,  1.86166697e-001,  8.74171550e-002,
4920# -4.83333333e-002,  1.18333333e-001, -4.83333333e-002,  1.18333333e-001,
4921# -4.83333333e-002, -6.66666667e-003, -1.73333333e-001, -1.31666667e-001,
4922# -1.73333333e-001, -6.66666667e-003, -4.83333333e-002,  1.18333333e-001,
4923# -2.48333333e-001, -2.31666667e-001, -2.48333333e-001, -2.31666667e-001,
4924# -2.48333333e-001, -2.31666667e-001, -2.48333333e-001, -2.31666667e-001,
4925# -2.48333333e-001, -2.31666667e-001, -2.48333333e-001, -2.31666667e-001,
4926# -4.65000000e-001, -3.65000000e-001, -4.65000000e-001, -3.65000000e-001,
4927# -4.65000000e-001, -3.65000000e-001, -4.65000000e-001, -3.65000000e-001,
4928# -4.65000000e-001, -3.65000000e-001, -4.65000000e-001, -3.65000000e-001,
4929# -5.98333333e-001, -5.81666667e-001, -5.98333333e-001, -5.81666667e-001,
4930# -5.98333333e-001, -5.81666667e-001, -5.98333333e-001, -5.81666667e-001,
4931# -5.98333333e-001, -5.81666667e-001, -5.98333333e-001, -5.81666667e-001,
4932# -6.48333333e-001, -6.31666667e-001, -6.48333333e-001, -6.31666667e-001,
4933# -6.48333333e-001, -6.31666667e-001, -6.48333333e-001, -6.31666667e-001,
4934# -6.48333333e-001, -6.31666667e-001, -6.48333333e-001, -6.31666667e-001,
4935# -5.31666667e-001, -5.98333333e-001, -5.31666667e-001, -5.98333333e-001,
4936# -5.31666667e-001, -5.98333333e-001, -5.31666667e-001, -5.98333333e-001,
4937# -5.31666667e-001, -5.98333333e-001, -5.31666667e-001, -5.98333333e-001,
4938# -4.98333333e-001, -4.81666667e-001, -4.98333333e-001, -4.81666667e-001,
4939# -4.98333333e-001, -4.81666667e-001, -4.98333333e-001, -4.81666667e-001,
4940# -4.98333333e-001, -4.81666667e-001, -4.98333333e-001, -4.81666667e-001,
4941# -5.48333333e-001, -5.31666667e-001, -5.48333333e-001, -5.31666667e-001,
4942# -5.48333333e-001, -5.31666667e-001, -5.48333333e-001, -5.31666667e-001,
4943# -5.48333333e-001, -5.31666667e-001, -5.48333333e-001, -5.31666667e-001])
4944
4945        os.remove(domain.get_name() + '.sww')
4946
4947    def test_spatio_temporal_boundary_1(self):
4948        """Test that boundary values can be read from file and interpolated
4949        in both time and space.
4950
4951        Verify that the same steady state solution is arrived at and that
4952        time interpolation works.
4953
4954        The full solution history is not exactly the same as
4955        file boundary must read and interpolate from *smoothed* version
4956        as stored in sww.
4957        """
4958        import time
4959
4960        #Create sww file of simple propagation from left to right
4961        #through rectangular domain
4962
4963        from mesh_factory import rectangular
4964
4965        #Create basic mesh
4966        points, vertices, boundary = rectangular(3, 3)
4967
4968        #Create shallow water domain
4969        domain1 = Domain(points, vertices, boundary)
4970
4971        domain1.reduction = mean
4972        domain1.smooth = False  #Exact result
4973
4974        domain1.default_order = 2
4975        domain1.store = True
4976        domain1.set_datadir('.')
4977        domain1.set_name('spatio_temporal_boundary_source' + str(time.time()))
4978
4979        #FIXME: This is extremely important!
4980        #How can we test if they weren't stored?
4981        domain1.quantities_to_be_stored = ['stage', 'xmomentum', 'ymomentum']
4982
4983
4984        #Bed-slope and friction at vertices (and interpolated elsewhere)
4985        domain1.set_quantity('elevation', 0)
4986        domain1.set_quantity('friction', 0)
4987
4988        # Boundary conditions
4989        Br = Reflective_boundary(domain1)
4990        Bd = Dirichlet_boundary([0.3,0,0])
4991        domain1.set_boundary({'left': Bd, 'top': Bd, 'right': Br, 'bottom': Br})
4992        #Initial condition
4993        domain1.set_quantity('stage', 0)
4994        domain1.check_integrity()
4995
4996        finaltime = 5
4997        #Evolution  (full domain - large steps)
4998        for t in domain1.evolve(yieldstep = 0.671, finaltime = finaltime):
4999            pass
5000            #domain1.write_time()
5001
5002        cv1 = domain1.quantities['stage'].centroid_values
5003
5004
5005        #Create a triangle shaped domain (reusing coordinates from domain 1),
5006        #formed from the lower and right hand  boundaries and
5007        #the sw-ne diagonal
5008        #from domain 1. Call it domain2
5009
5010        points = [ [0,0], [1.0/3,0], [1.0/3,1.0/3],
5011                   [2.0/3,0], [2.0/3,1.0/3], [2.0/3,2.0/3],
5012                   [1,0], [1,1.0/3], [1,2.0/3], [1,1]]
5013
5014        vertices = [ [1,2,0], [3,4,1], [2,1,4], [4,5,2],
5015                     [6,7,3], [4,3,7], [7,8,4], [5,4,8], [8,9,5]]
5016
5017        boundary = { (0,1):'bottom', (1,1):'bottom', (4,1): 'bottom',
5018                     (4,2):'right', (6,2):'right', (8,2):'right',
5019                     (0,0):'diagonal', (3,0):'diagonal', (8,0):'diagonal'}
5020
5021        domain2 = Domain(points, vertices, boundary)
5022
5023        domain2.reduction = domain1.reduction
5024        domain2.smooth = False
5025        domain2.default_order = 2
5026
5027        #Bed-slope and friction at vertices (and interpolated elsewhere)
5028        domain2.set_quantity('elevation', 0)
5029        domain2.set_quantity('friction', 0)
5030        domain2.set_quantity('stage', 0)
5031
5032        # Boundary conditions
5033        Br = Reflective_boundary(domain2)
5034        #Bf = Spatio_temporal_boundary(domain1.get_name() + '.' +\
5035        #                              domain1.format, domain2)
5036        Bf = Field_boundary(domain1.get_name() + '.' +\
5037                            domain1.format, domain2)       
5038        domain2.set_boundary({'right':Br, 'bottom':Br, 'diagonal':Bf})
5039        domain2.check_integrity()
5040
5041
5042
5043        #Evolution (small steps)
5044        for t in domain2.evolve(yieldstep = 0.0711, finaltime = finaltime):
5045            pass
5046
5047
5048        #Use output from domain1 as spatio-temporal boundary for domain2
5049        #and verify that results at right hand side are close.
5050
5051        cv2 = domain2.quantities['stage'].centroid_values
5052
5053        #print take(cv1, (12,14,16))  #Right
5054        #print take(cv2, (4,6,8))
5055        #print take(cv1, (0,6,12))  #Bottom
5056        #print take(cv2, (0,1,4))
5057        #print take(cv1, (0,8,16))  #Diag
5058        #print take(cv2, (0,3,8))
5059
5060        assert allclose( take(cv1, (0,8,16)), take(cv2, (0,3,8))) #Diag
5061        assert allclose( take(cv1, (0,6,12)), take(cv2, (0,1,4))) #Bottom
5062        assert allclose( take(cv1, (12,14,16)), take(cv2, (4,6,8))) #RHS
5063
5064        #Cleanup
5065        os.remove(domain1.get_name() + '.' + domain1.format)
5066        os.remove(domain2.get_name() + '.' + domain2.format)       
5067
5068
5069
5070    def test_spatio_temporal_boundary_2(self):
5071        """Test that boundary values can be read from file and interpolated
5072        in both time and space.
5073        This is a more basic test, verifying that boundary object
5074        produces the expected results
5075
5076
5077        """
5078        import time
5079
5080        #Create sww file of simple propagation from left to right
5081        #through rectangular domain
5082
5083        from mesh_factory import rectangular
5084
5085        #Create basic mesh
5086        points, vertices, boundary = rectangular(3, 3)
5087
5088        #Create shallow water domain
5089        domain1 = Domain(points, vertices, boundary)
5090
5091        domain1.reduction = mean
5092        domain1.smooth = True #To mimic MOST output
5093
5094        domain1.default_order = 2
5095        domain1.store = True
5096        domain1.set_datadir('.')
5097        domain1.set_name('spatio_temporal_boundary_source' + str(time.time()))
5098
5099        #FIXME: This is extremely important!
5100        #How can we test if they weren't stored?
5101        domain1.quantities_to_be_stored = ['stage', 'xmomentum', 'ymomentum']
5102
5103
5104        #Bed-slope and friction at vertices (and interpolated elsewhere)
5105        domain1.set_quantity('elevation', 0)
5106        domain1.set_quantity('friction', 0)
5107
5108        # Boundary conditions
5109        Br = Reflective_boundary(domain1)
5110        Bd = Dirichlet_boundary([0.3,0,0])
5111        domain1.set_boundary({'left': Bd, 'top': Bd, 'right': Br, 'bottom': Br})
5112        #Initial condition
5113        domain1.set_quantity('stage', 0)
5114        domain1.check_integrity()
5115
5116        finaltime = 5
5117        #Evolution  (full domain - large steps)
5118        for t in domain1.evolve(yieldstep = 1, finaltime = finaltime):
5119            pass
5120            #domain1.write_time()
5121
5122
5123        #Create an triangle shaped domain (coinciding with some
5124        #coordinates from domain 1),
5125        #formed from the lower and right hand  boundaries and
5126        #the sw-ne diagonal
5127        #from domain 1. Call it domain2
5128
5129        points = [ [0,0], [1.0/3,0], [1.0/3,1.0/3],
5130                   [2.0/3,0], [2.0/3,1.0/3], [2.0/3,2.0/3],
5131                   [1,0], [1,1.0/3], [1,2.0/3], [1,1]]
5132
5133        vertices = [ [1,2,0],
5134                     [3,4,1], [2,1,4], [4,5,2],
5135                     [6,7,3], [4,3,7], [7,8,4], [5,4,8], [8,9,5]]
5136
5137        boundary = { (0,1):'bottom', (1,1):'bottom', (4,1): 'bottom',
5138                     (4,2):'right', (6,2):'right', (8,2):'right',
5139                     (0,0):'diagonal', (3,0):'diagonal', (8,0):'diagonal'}
5140
5141        domain2 = Domain(points, vertices, boundary)
5142
5143        domain2.reduction = domain1.reduction
5144        domain2.smooth = False
5145        domain2.default_order = 2
5146
5147        #Bed-slope and friction at vertices (and interpolated elsewhere)
5148        domain2.set_quantity('elevation', 0)
5149        domain2.set_quantity('friction', 0)
5150        domain2.set_quantity('stage', 0)
5151
5152
5153        #Read results for specific timesteps t=1 and t=2
5154        from Scientific.IO.NetCDF import NetCDFFile
5155        fid = NetCDFFile(domain1.get_name() + '.' + domain1.format)
5156
5157        x = fid.variables['x'][:]
5158        y = fid.variabl