source: development/pyvolution-1d/test_shallow_water_1d.py @ 3295

Last change on this file since 3295 was 3295, checked in by steve, 18 years ago
File size: 37.3 KB
Line 
1import unittest, os
2from math import sqrt, pi
3from shallow_water_1d import *
4from Numeric import allclose, array, zeros, ones, Float, take
5from config import g, epsilon
6
7#Variable windfield implemented using functions
8#def speed(t,x,y):
9def speed(t,x):
10    """Large speeds halfway between center and edges
11    Low speeds at center and edges
12    """
13
14    from math import sqrt, exp, cos, pi
15
16    x = array(x)
17    #y = array(y)
18
19    N = len(x)
20    s = 0*#New array
21
22    for k in range(N):
23
24        #r = sqrt(x[k]**2 + y[k]**2)
25        r = x[k]
26
27        factor = exp( -(r-0.15)**2 )
28
29        s[k] = 4000 * factor * (cos(t*2*pi/150) + 2)
30
31    return s
32
33
34#def scalar_func(t,x,y):
35def scalar_func(t,x):
36    """Function that returns a scalar.
37    Used to test error message when Numeric array is expected
38    """
39
40    return 17.7
41
42
43#def angle(t,x,y):
44def angle(t,x):
45    """Rotating field
46    """
47    from math import sqrt, atan, pi
48
49    x = array(x)
50    #y = array(y)
51
52    N = len(x)
53    a = 0*#New array
54
55    for k in range(N):
56        #r = sqrt(x[k]**2 + y[k]**2)
57        r =x[k]
58
59        #angle = atan(y[k]/x[k])
60        angle = atan(1/x[k])
61
62        if x[k] < 0:
63            angle+=pi #atan in ]-pi/2; pi/2[
64
65        #Take normal direction
66        angle -= pi/2
67
68        #Ensure positive radians
69        if angle < 0:
70            angle += 2*pi
71
72        a[k] = angle/pi*180
73
74    return a
75
76
77class TestCase(unittest.TestCase):
78    def setUp(self):
79        pass
80
81    def tearDown(self):
82        pass
83
84    def test_flux_zero_case(self):
85        #ql = zeros( 3, Float )
86        #qr = zeros( 3, Float )
87        ql = zeros( 2, Float )
88        qr = zeros( 2, Float )
89       
90        #normal = zeros( 2, Float )
91        zl = zr = 0.
92        flux, max_speed = flux_function(1.0, ql, qr, zl, zr)
93
94        #assert allclose(flux, [0,0,0])
95        assert allclose(flux, [0,0])
96        assert max_speed == 0.
97       
98    def test_flux_constants(self):
99        w = 2.0
100
101        #normal = array([1.,0])
102        #ql = array([w, 0, 0])
103        #qr = array([w, 0, 0])
104        ql = array([w, 0])
105        qr = array([w, 0])
106       
107        zl = zr = 0.
108        h = w - (zl+zr)/2
109
110        #flux, max_speed = flux_function(normal, ql, qr, zl, zr)
111        flux, max_speed = flux_function(1.0, ql, qr, zl, zr)
112
113        #assert allclose(flux, [0., 0.5*g*h**2, 0.])
114        assert allclose(flux, [0., 0.5*g*h**2])
115        assert max_speed == sqrt(g*h)
116   
117    def test_flux1(self):
118        #Use data from previous version of pyvolution
119        #normal = array([1.,0])
120        #ql = array([-0.2, 2, 3])
121        #qr = array([-0.2, 2, 3])
122        ql = array([-0.2, 2])
123        qr = array([-0.2, 2])
124        zl = zr = -0.5
125        #flux, max_speed = flux_function(normal, ql, qr, zl, zr)
126        flux, max_speed = flux_function(1.0, ql, qr, zl, zr)
127       
128        #assert allclose(flux, [2.,13.77433333, 20.])
129        assert allclose(flux, [2.,13.77433333])
130        assert allclose(max_speed, 8.38130948661)
131
132    def test_flux2(self):
133        #Use data from previous version of pyvolution
134        """
135        2D problem
136        normal = array([0., -1.])
137        ql = array([-0.075, 2, 3])
138        qr = array([-0.075, 2, 3])
139        equivlent to solving 1D
140        ql = array([-0.075, -3])
141        qr = array([-0.075, -3])
142        with flux not rotated back
143        i.e flux =  [-3.,30.441])
144        """
145        ql = array([-0.075, -3])
146        qr = array([-0.075, -3])
147       
148        zl = zr = -0.375
149        #flux, max_speed = flux_function(normal, ql, qr, zl, zr)
150        flux, max_speed = flux_function(1.0, ql, qr, zl, zr)
151        #assert allclose(flux, [-3.,-20.0, -30.441])
152        assert allclose(flux, [-3.,30.441])
153        assert allclose(max_speed, 11.7146428199)
154
155       
156    def test_flux3(self):
157        #def test_flux4(self):
158        #Use data from previous version of pyvolution
159        """
160        change from 3d case with rotation
161        normal = array([-sqrt(2)/2, sqrt(2)/2])
162        ql = array([-0.34319278, 0.10254161, 0.07273855])
163        qr = array([-0.30683287, 0.1071986, 0.05930515])
164        to 1d case
165        ql = [-0.30683287, -0.03386578]
166        qr = [-0.04072675,  0.03883622]
167        """
168        ql = array([-0.34319278, -0.02107395])
169        qr = array([-0.30683287, -0.03386578])
170
171        zl = zr = -0.375
172        #flux, max_speed = flux_function(normal, ql, qr, zl, zr)
173        flux, max_speed = flux_function(1.0, ql, qr, zl, zr)
174        #assert allclose(flux, [-0.04072676, -0.07096636, -0.01604364])
175        assert allclose(flux, [-0.04072676, 0.03883622])
176        assert allclose(max_speed, 1.31414103233)
177       
178    def test_sw_domain_simple(self):
179        #a = [0.0, 0.0]
180        #b = [0.0, 2.0]
181        #c = [2.0,0.0]
182        #d = [0.0, 4.0]
183        #e = [2.0, 2.0]
184        #f = [4.0,0.0]
185        a=0.0
186        b=2.0
187        c=4.0
188        d=6.0
189        e=8.0
190        f=10.0
191
192        points = [a, b, c, d, e, f]
193        #bac, bce, ecf, dbe, daf, dae
194        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
195
196        #domain = Domain(points, vertices)
197        domain = Domain(points)
198        domain.check_integrity()
199
200        #for name in ['stage', 'xmomentum', 'ymomentum',
201        for name in ['stage', 'xmomentum',
202                     'elevation', 'friction']:
203            assert domain.quantities.has_key(name)
204
205
206        #assert domain.get_conserved_quantities(0, edge=1) == 0.
207        assert domain.get_conserved_quantities(0, vertex=1) == 0.
208
209    def test_boundary_conditions(self):
210       
211        #a = [0.0, 0.0]
212        #b = [0.0, 2.0]
213        #c = [2.0,0.0]
214        #d = [0.0, 4.0]
215        #e = [2.0, 2.0]
216        #f = [4.0,0.0]
217        a=0.0
218        b=2.0
219        c=4.0
220        d=6.0
221        e=8.0
222        f=10.0
223
224        points = [a, b, c, d, e, f]
225        #bac, bce, ecf, dbe
226        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
227        #boundary = { (0, 0): 'Third',
228        #             (0, 2): 'First',
229        #             (2, 0): 'Second',
230        #             (2, 1): 'Second',
231        #             (3, 1): 'Second',
232        #             (3, 2): 'Third'}
233
234        #there are points -1 segements with edges (0,1) = (left, right)
235        boundary = {(0,0): 'Start', (4,1): 'Finish'}
236        #boundary = {(0,0): 'exterior', (4,1): 'exterior'}
237        #domain = Domain(points, vertices, boundary)
238        domain = Domain(points, boundary)
239        domain.check_integrity()
240
241        #Sets stages in each interval(element)
242        #domain.set_quantity('stage', [[1,2,3], [5,5,5],
243        #                             [0,0,9], [-6, 3, 3]])
244        domain.set_quantity('stage', [[1,2], [5,5],
245                                     [0,0], [-6,3], [3,0]])
246
247        #domain.set_quantity('xmomentum', [[1,1,1], [2,2,2],
248        #                                  [3,3,3], [4, 4, 4]])
249        domain.set_quantity('xmomentum', [[1,1], [2,2],
250                                          [3,3], [4, 4], [5,5]])
251
252        #domain.set_quantity('ymomentum', [[10,10,10], [20,20,20],
253        #                                  [30,30,30], [40, 40, 40]])
254
255        #D = Dirichlet_boundary([5,2,1])
256        #T = Transmissive_boundary(domain)
257        R = Reflective_boundary(domain)
258        domain.set_boundary( {'Start': R, 'Finish': R})
259        #domain.set_boundary( {'exterior': R, 'exterior': R})
260
261        domain.update_boundary()
262
263        #Stage
264        #assert domain.quantities['stage'].boundary_values[0] == 2.5
265        assert domain.quantities['stage'].boundary_values[0] ==\
266               domain.get_conserved_quantities(0, vertex=0)[0] #Reflective (2.5)
267        #assert domain.quantities['stage'].boundary_values[1] == 5. #Dirichlet
268        #assert domain.quantities['stage'].boundary_values[2] ==\
269        #       domain.get_conserved_quantities(2, edge=0)[0] #Transmissive (4.5)
270        #assert domain.quantities['stage'].boundary_values[3] ==\
271        #       domain.get_conserved_quantities(2, edge=1)[0] #Transmissive (4.5)
272        #assert domain.quantities['stage'].boundary_values[4] ==\
273        #       domain.get_conserved_quantities(3, edge=1)[0] #Transmissive (-1.5)
274        #assert domain.quantities['stage'].boundary_values[5] ==\
275        #       domain.get_conserved_quantities(3, edge=2)[0] #Reflective (-1.5)
276
277        #Xmomentum
278        #print 'xmom'
279        print domain.quantities['xmomentum'].boundary_values[0]
280        assert domain.quantities['xmomentum'].boundary_values[0] == 1.0 #Reflective
281
282        #SHOULDN'T THIS BE -1.0
283       
284        #assert domain.quantities['xmomentum'].boundary_values[1] == 2. #Dirichlet
285        #assert domain.quantities['xmomentum'].boundary_values[2] ==\
286        #       domain.get_conserved_quantities(2, edge=0)[1] #Transmissive
287        #assert domain.quantities['xmomentum'].boundary_values[3] ==\
288        #       domain.get_conserved_quantities(2, edge=1)[1] #Transmissive
289        #assert domain.quantities['xmomentum'].boundary_values[4] ==\
290        #       domain.get_conserved_quantities(3, edge=1)[1] #Transmissive
291        assert domain.quantities['xmomentum'].boundary_values[1] == -5.0  #Reflective
292
293    def test_boundary_conditionsII(self):
294
295        #a = [0.0, 0.0]
296        #b = [0.0, 2.0]
297        #c = [2.0,0.0]
298        #d = [0.0, 4.0]
299        #e = [2.0, 2.0]
300        #f = [4.0,0.0]
301        a=0.0
302        b=2.0
303        c=4.0
304        d=6.0
305        e=8.0
306        f=10.0
307
308        points = [a, b, c, d, e, f]
309        #bac, bce, ecf, dbe
310        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
311        #boundary = { (0, 0): 'Third',
312        #             (0, 2): 'First',
313        #             (2, 0): 'Second',
314        #             (2, 1): 'Second',
315        #             (3, 1): 'Second',
316        #             (3, 2): 'Third',
317        #             (0, 1): 'Internal'}
318       
319
320        boundary = {(0,0): 'Start', (1,0) : 'Internal', (4,1): 'Finish'}
321        #domain = Domain(points, vertices, boundary)
322        domain = Domain(points, boundary)
323        domain.check_integrity()
324
325
326        #domain.set_quantity('stage', [[1,2,3], [5,5,5],
327        #                              [0,0,9], [-6, 3, 3]])
328
329        #domain.set_quantity('xmomentum', [[1,1,1], [2,2,2],
330        #                                  [3,3,3], [4, 4, 4]])
331
332        #domain.set_quantity('ymomentum', [[10,10,10], [20,20,20],
333        #                                  [30,30,30], [40, 40, 40]])
334
335        domain.set_quantity('stage', [[1,2], [5,5],
336                                      [0,0], [-6, 3], [3, 0]])
337
338        domain.set_quantity('xmomentum', [[1,1], [2,2],
339                                          [3,3], [4, 4], [5, 5]])
340       
341
342
343        #D = Dirichlet_boundary([5,2,1])
344        #T = Transmissive_boundary(domain)
345        R = Reflective_boundary(domain)
346        domain.set_boundary( {'Start': R, 'Finish': R, 'Internal': None})
347
348        domain.update_boundary()
349        domain.check_integrity()
350   
351    def test_compute_fluxes0(self):
352        #Do a full triangle and check that fluxes cancel out for
353        #the constant stage case
354
355        print 'check min time step in compute fluxes is ok, John'
356
357        #a = [0.0, 0.0]
358        #b = [0.0, 2.0]
359        #c = [2.0,0.0]
360        #d = [0.0, 4.0]
361        #e = [2.0, 2.0]
362        #f = [4.0,0.0]
363        a=0.0
364        b=2.0
365        c=4.0
366        d=6.0
367        e=8.0
368        f=10.0
369       
370        points = [a, b, c, d, e, f]
371        #bac, bce, ecf, dbe
372        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
373
374        domain = Domain(points)
375        #domain.set_quantity('stage', [[2,2,2], [2,2,2],
376        #                              [2,2,2], [2,2,2]])
377        domain.set_quantity('stage', [[2,2], [2,2], [2,2], [2,2], [2,2]])
378        domain.check_integrity()
379
380        #assert allclose(domain.neighbours, [[-1,1,-1], [2,3,0], [-1,-1,1],[1,-1,-1]])
381        assert allclose(domain.neighbours, [[-1,1], [0,2], [1,3],[2,4], [3,-1]])
382        #assert allclose(domain.neighbour_edges, [[-1,2,-1], [2,0,1], [-1,-1,0],[1,-1,-1]])
383        #assert allclose(domain.neighbour_edges, [[-1,0], [1,0], [1,0], [1,0], [1,-1]])
384        assert allclose(domain.neighbour_vertices, [[-1,0], [1,0], [1,0], [1,0], [1,-1]])
385
386        zl=zr=0. #Assume flat bed
387
388        #Flux across right edge of volume 1
389        #normal = domain.get_normal(1,0)
390        #ql = domain.get_conserved_quantities(vol_id=1, edge=0)
391        #qr = domain.get_conserved_quantities(vol_id=2, edge=2)
392        #flux0, max_speed = flux_function(normal, ql, qr, zl, zr)
393
394        #Flux across right edge of element 1
395        ql = domain.get_conserved_quantities(vol_id=1, vertex=1)
396        qr = domain.get_conserved_quantities(vol_id=2, vertex=0)
397        #print 'qr and ql 1'
398        #print qr
399        #print ql
400        flux0, max_speed = flux_function(1.0, ql, qr, zl, zr)
401
402        #Check that flux seen from other triangles is inverse
403        tmp = qr; qr=ql; ql=tmp
404        #print 'qr and ql 2'
405        #print qr
406        #print ql
407        #normal = domain.get_normal(2,2)
408        #flux, max_speed = flux_function(normal, ql, qr, zl, zr)
409        flux, max_speed = flux_function(-1.0, ql, qr, zl, zr)
410        #print 'fluxes'
411        #print flux0
412        #print flux
413        assert allclose(flux + flux0, 0.)
414
415        #Flux across upper edge of volume 1
416        #normal = domain.get_normal(1,1)
417        #ql = domain.get_conserved_quantities(vol_id=1, edge=1)
418        #qr = domain.get_conserved_quantities(vol_id=3, edge=0)
419        #flux1, max_speed = flux_function(normal, ql, qr, zl, zr)
420
421        #Flux across left edge of element 1
422        #ql = domain.get_conserved_quantities(vol_id=1, edge=0)
423        #qr = domain.get_conserved_quantities(vol_id=0, edge=1)
424        ql = domain.get_conserved_quantities(vol_id=1, vertex=0)
425        qr = domain.get_conserved_quantities(vol_id=0, vertex=1)
426        flux1, max_speed = flux_function(-1.0, ql, qr, zl, zr)
427
428        #Check that flux seen from other triangles is inverse
429        tmp = qr; qr=ql; ql=tmp
430        #normal = domain.get_normal(3,0)
431        #flux, max_speed = flux_function(normal, ql, qr, zl, zr)
432        flux, max_speed = flux_function(1.0, ql, qr, zl, zr)
433        assert allclose(flux + flux1, 0.)
434
435        #Flux across lower left hypotenuse of volume 1
436        #normal = domain.get_normal(1,2)
437        #ql = domain.get_conserved_quantities(vol_id=1, edge=2)
438        #qr = domain.get_conserved_quantities(vol_id=0, edge=1)
439        #flux2, max_speed = flux_function(normal, ql, qr, zl, zr)
440
441        #Check that flux seen from other triangles is inverse
442        #tmp = qr; qr=ql; ql=tmp
443        #normal = domain.get_normal(0,1)
444        #flux, max_speed = flux_function(normal, ql, qr, zl, zr)
445        #assert allclose(flux + flux2, 0.)
446
447
448        #Scale by edgelengths, add up anc check that total flux is zero
449        #e0 = domain.edgelengths[1, 0]
450        #e1 = domain.edgelengths[1, 1]
451        #e2 = domain.edgelengths[1, 2]
452
453        #assert allclose(e0*flux0+e1*flux1+e2*flux2, 0.)
454        print 'flux0',flux0
455        print 'flux1',flux1
456        assert allclose(flux0+flux1, 0.)
457
458        #Now check that compute_flux yields zeros as well
459        domain.compute_fluxes()
460
461        #for name in ['stage', 'xmomentum', 'ymomentum']:
462        for name in ['stage', 'xmomentum']:
463            #print name, domain.quantities[name].explicit_update
464            assert allclose(domain.quantities[name].explicit_update[1], 0)
465
466    def test_compute_fluxes1(self):
467        #Use values from previous version
468        print "test compute fluxes 1"
469
470        a=0.0
471        b=2.0
472        c=4.0
473        d=6.0
474        e=8.0
475               
476        points = [a, b, c, d, e]
477       
478        domain = Domain(points)
479       
480        val0 = 2.+2.0/3
481        val1 = 4.+4.0/3
482        val2 = 8.+2.0/3
483        val3 = 2.+8.0/3
484
485        domain.set_quantity('stage', [[val3, val3], [val1, val1],
486                                      [val2, val2], [val0, val0]])
487        stage = domain.get_quantity('stage')
488        print stage
489        domain.check_integrity()
490
491        zl=zr=0. #Assume flat bed
492
493        #Flux across right edge of volume 1
494        ql = domain.get_conserved_quantities(vol_id=1, vertex=1)
495        qr = domain.get_conserved_quantities(vol_id=2, vertex=0)
496        print 'ql',ql
497        print 'qr',qr
498        flux0, max_speed = flux_function(1.0, ql, qr, zl, zr)
499        print 'flux0',flux0
500        print 'max_speed', max_speed
501       
502        #Check that flux seen from other triangles is inverse
503        flux, max_speed = flux_function(-1.0, qr, ql, zl, zr)
504        print flux0
505        print flux
506        assert allclose(flux + flux0, 0.)
507
508        assert allclose(flux0, [-15.3598804, 253.71111111])
509        assert allclose(max_speed, 9.21592824046)
510
511
512        #Flux across left edge of volume 1
513        ql = domain.get_conserved_quantities(vol_id=1, vertex=0)
514        qr = domain.get_conserved_quantities(vol_id=0, vertex=1)
515        flux1, max_speed = flux_function(-1.0, ql, qr, zl, zr)
516        print 'flux1', flux1
517        assert allclose(flux1, [2.4098563, -123.04444444])
518        assert allclose(max_speed, 7.22956891292)
519
520        #Add up and check that compute_fluxes is correct for vol 1
521        total_flux = -(flux0+flux1)/domain.areas[1]
522        print 'total flux', total_flux
523        print 'domain area',domain.areas[1]
524        assert allclose(total_flux, [6.47501205, -65.333333333])
525       
526        domain.compute_fluxes()
527
528        for i, name in enumerate(['stage', 'xmomentum']):
529            assert allclose(total_flux[i],
530                            domain.quantities[name].explicit_update[1])
531
532        #assert allclose(domain.explicit_update, [
533        #    [0., -69.68888889, -69.68888889],
534        #    [-0.68218178, -166.6, -35.93333333],
535        #    [-111.77316251, 69.68888889, 0.],
536        #    [-35.68522449, 0., 69.68888889]])
537
538        print domain.quantities['stage'].explicit_update
539        print domain.quantities['xmomentum'].explicit_update
540        assert allclose(domain.quantities['stage'].explicit_update,
541                        [0., 6.47501205, -111.77316251, -35.68522449])
542        assert allclose(domain.quantities['xmomentum'].explicit_update,
543                        [-69.68888889, -65.33333333, 69.68888889, 0])
544        assert allclose(domain.quantities['ymomentum'].explicit_update,
545                        [-69.68888889, -35.93333333, 0., 69.68888889])
546
547
548        #assert allclose(domain.quantities[name].explicit_update
549
550    def test_catching_negative_heights(self):
551
552        a=0.0
553        b=2.0
554        c=4.0
555        d=6.0
556        e=8.0
557   
558        points = [a, b, c, d, e]
559        domain = Domain(points)
560        val0 = 2.+2.0/3
561        val1 = 4.+4.0/3
562        val2 = 8.+2.0/3
563        val3 = 2.+8.0/3
564
565        zl=zr=4  #Too large
566        domain.set_quantity('elevation', zl*ones( (4,2) ))
567        domain.set_quantity('stage', [[val0, val0-1],
568                                      [val1, val1+1],
569                                      [val2, val2-2],
570                                      [val3-0.5, val3]])
571
572        #Should fail
573        try:
574            domain.check_integrity()
575        except:
576            pass
577
578    def test_initial_condition(self):
579        """Test that initial condition is output at time == 0
580        """
581
582        from config import g
583        import copy
584
585        #a = [0.0, 0.0]
586        #b = [0.0, 2.0]
587        #c = [2.0, 0.0]
588        #d = [0.0, 4.0]
589        #e = [2.0, 2.0]
590        #f = [4.0, 0.0]
591        a=0.0
592        b=2.0
593        c=4.0
594        d=6.0
595        e=8.0
596        #f=10.0
597
598        #points = [a, b, c, d, e, f]
599        points = [a, b, c, d, e]
600        #bac, bce, ecf, dbe
601        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
602
603        #domain = Domain(points, vertices)
604        domain = Domain(points)
605
606        #Set up for a gradient of (3,0) at mid triangle
607        #def slope(x, y):
608        #    return 3*x
609        def slope(x):
610            return 3*x
611
612        h = 0.1
613        #def stage(x,y):
614        #    return slope(x,y)+h
615        def stage(x):
616            return slope(x)+h
617
618        domain.set_quantity('elevation', slope)
619        domain.set_quantity('stage', stage)
620
621        initial_stage = copy.copy(domain.quantities['stage'].vertex_values)
622
623        domain.set_boundary({'exterior': Reflective_boundary(domain)})
624
625        #Evolution
626        for t in domain.evolve(yieldstep = 1.0, finaltime = 2.0):
627            stage = domain.quantities['stage'].vertex_values
628
629            if t == 0.0:
630                assert allclose(stage, initial_stage)
631            else:
632                assert not allclose(stage, initial_stage)
633
634        os.remove(domain.filename + '.sww')
635
636    #####################################################
637    def test_gravity(self):
638        #Assuming no friction
639
640        from config import g
641        a=0.0
642        b=2.0
643        c=4.0
644        d=6.0
645        e=8.0
646       
647        points = [a, b, c, d, e]
648       
649        domain = Domain(points)
650
651        def slope(x):
652            return 3*x
653
654        h = 0.1
655        #def stage(x,y):
656        #    return slope(x,y)+h
657        def stage(x):
658            return slope(x)+h
659
660
661        domain.set_quantity('elevation', slope)
662        domain.set_quantity('stage', stage)
663
664        for name in domain.conserved_quantities:
665            assert allclose(domain.quantities[name].explicit_update, 0)
666            assert allclose(domain.quantities[name].semi_implicit_update, 0)
667
668        domain.compute_forcing_terms()
669
670        assert allclose(domain.quantities['stage'].explicit_update, 0)
671        assert allclose(domain.quantities['xmomentum'].explicit_update, -g*h*3)
672        #assert allclose(domain.quantities['ymomentum'].explicit_update, 0)
673
674
675    def test_manning_friction(self):
676        from config import g
677
678        a=0.0
679        b=2.0
680        c=4.0
681        d=6.0
682        e=8.0
683
684        points = [a, b, c, d, e]
685               
686        domain = Domain(points)
687
688        #Set up for a gradient of (3,0) at mid triangle
689        def slope(x):
690            return 3*x
691
692        h = 0.1
693        #def stage(x,y):
694        #    return slope(x,y)+h
695        def stage(x):
696            return slope(x)+h
697
698        eta = 0.07
699        domain.set_quantity('elevation', slope)
700        domain.set_quantity('stage', stage)
701        domain.set_quantity('friction', eta)
702
703        for name in domain.conserved_quantities:
704            assert allclose(domain.quantities[name].explicit_update, 0)
705            assert allclose(domain.quantities[name].semi_implicit_update, 0)
706
707        domain.compute_forcing_terms()
708
709        assert allclose(domain.quantities['stage'].explicit_update, 0)
710        assert allclose(domain.quantities['xmomentum'].explicit_update, -g*h*3)
711        #assert allclose(domain.quantities['ymomentum'].explicit_update, 0)
712
713        assert allclose(domain.quantities['stage'].semi_implicit_update, 0)
714        assert allclose(domain.quantities['xmomentum'].semi_implicit_update, 0)
715        #assert allclose(domain.quantities['ymomentum'].semi_implicit_update, 0)
716
717        #Create some momentum for friction to work with
718        domain.set_quantity('xmomentum', 1)
719        S = -g * eta**2 / h**(7.0/3)
720
721        domain.compute_forcing_terms()
722        assert allclose(domain.quantities['stage'].semi_implicit_update, 0)
723        assert allclose(domain.quantities['xmomentum'].semi_implicit_update, S)
724        #assert allclose(domain.quantities['ymomentum'].semi_implicit_update, 0)
725
726        #A more complex example
727        domain.quantities['stage'].semi_implicit_update[:] = 0.0
728        domain.quantities['xmomentum'].semi_implicit_update[:] = 0.0
729        #domain.quantities['ymomentum'].semi_implicit_update[:] = 0.0
730
731        #domain.set_quantity('xmomentum', 3)
732        domain.set_quantity('xmomentum', 5)
733        #domain.set_quantity('ymomentum', 4)
734
735        S = -g * eta**2 * 5 / h**(7.0/3)
736        #S = -g * eta**2 / h**(7.0/3)
737
738
739        domain.compute_forcing_terms()
740
741        assert allclose(domain.quantities['stage'].semi_implicit_update, 0)
742        print '5*S', 5*S
743        #CHECK THIS TEST
744        print domain.quantities['xmomentum'].semi_implicit_update
745        #assert allclose(domain.quantities['xmomentum'].semi_implicit_update, 3*S)
746        assert allclose(domain.quantities['xmomentum'].semi_implicit_update, 5*S)
747        #assert allclose(domain.quantities['ymomentum'].semi_implicit_update, 4*S)
748
749    def test_constant_wind_stress(self):
750        from config import rho_a, rho_w, eta_w
751        from math import pi, cos, sin, sqrt
752
753       
754        #a = [0.0, 0.0]
755        #b = [0.0, 2.0]
756        #c = [2.0, 0.0]
757        #d = [0.0, 4.0]
758        #e = [2.0, 2.0]
759        #f = [4.0, 0.0]
760        a=0.0
761        b=2.0
762        c=4.0
763        d=6.0
764        e=8.0
765        #f=10.0
766
767        #points = [a, b, c, d, e, f]
768        points = [a, b, c, d, e]
769        #bac, bce, ecf, dbe
770        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
771
772        #domain = Domain(points, vertices)
773        domain = Domain(points)
774       
775        #Flat surface with 1m of water
776        domain.set_quantity('elevation', 0)
777        domain.set_quantity('stage', 1.0)
778        domain.set_quantity('friction', 0)
779
780        Br = Reflective_boundary(domain)
781        domain.set_boundary({'exterior': Br})
782
783        #Setup only one forcing term, constant wind stress
784        s = 100
785        phi = 135
786        domain.forcing_terms = []
787        domain.forcing_terms.append( Wind_stress(s, phi) )
788
789        domain.compute_forcing_terms()
790
791
792        const = eta_w*rho_a/rho_w
793
794        #Convert to radians
795        phi = phi*pi/180
796
797        #Compute velocity vector (u, v)
798        u = s*cos(phi)
799        #v = s*sin(phi)
800
801        #Compute wind stress
802        #S = const * sqrt(u**2 + v**2)
803        S = const * u
804       
805
806        assert allclose(domain.quantities['stage'].explicit_update, 0)
807        assert allclose(domain.quantities['xmomentum'].explicit_update, S*u)
808        #assert allclose(domain.quantities['ymomentum'].explicit_update, S*v)
809
810
811    def test_variable_wind_stress(self):
812        from config import rho_a, rho_w, eta_w
813        from math import pi, cos, sin, sqrt
814
815        #a = [0.0, 0.0]
816        #b = [0.0, 2.0]
817        #c = [2.0, 0.0]
818        #d = [0.0, 4.0]
819        #e = [2.0, 2.0]
820        #f = [4.0, 0.0]
821        a=0.0
822        b=2.0
823        c=4.0
824        d=6.0
825        e=8.0
826        #f=10.0
827
828        #points = [a, b, c, d, e, f]
829        points = [a, b, c, d, e]
830        #bac, bce, ecf, dbe
831        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
832
833        #domain = Domain(points, vertices)
834        domain = Domain(points)
835
836        #Flat surface with 1m of water
837        domain.set_quantity('elevation', 0)
838        domain.set_quantity('stage', 1.0)
839        domain.set_quantity('friction', 0)
840
841        Br = Reflective_boundary(domain)
842        domain.set_boundary({'exterior': Br})
843
844        domain.time = 5.54 #Take a random time (not zero)
845
846        #Setup only one forcing term, constant wind stress
847        s = 100
848        phi = 135
849        domain.forcing_terms = []
850        domain.forcing_terms.append( Wind_stress(s = speed, phi = angle) )
851
852        domain.compute_forcing_terms()
853
854        #Compute reference solution
855        const = eta_w*rho_a/rho_w
856
857        N = domain.number_of_elements
858
859        xc = domain.get_centroid_coordinates()
860        t = domain.time
861
862        #x = xc[:,0]
863        #y = xc[:,1]
864        x = xc
865       
866        #s_vec = speed(t,x,y)
867        #phi_vec = angle(t,x,y)
868        s_vec = speed(t,x)
869        phi_vec = angle(t,x)
870
871
872        for k in range(N):
873            #Convert to radians
874            phi = phi_vec[k]*pi/180
875            s = s_vec[k]
876
877            #Compute velocity vector (u, v)
878            u = s*cos(phi)
879            #v = s*sin(phi)
880
881            #Compute wind stress
882            #S = const * sqrt(u**2 + v**2)
883            S = const*u
884
885            assert allclose(domain.quantities['stage'].explicit_update[k], 0)
886            assert allclose(domain.quantities['xmomentum'].explicit_update[k], S*u)
887            #assert allclose(domain.quantities['ymomentum'].explicit_update[k], S*v)
888
889    def test_first_order_extrapolator_const_z(self):
890
891        #a = [0.0, 0.0]
892        #b = [0.0, 2.0]
893        #c = [2.0, 0.0]
894        #d = [0.0, 4.0]
895        #e = [2.0, 2.0]
896        #f = [4.0, 0.0]
897        a=0.0
898        b=2.0
899        c=4.0
900        d=6.0
901        e=8.0
902        #f=10.0
903
904        #points = [a, b, c, d, e, f]
905        points = [a, b, c, d, e]
906        #bac, bce, ecf, dbe
907        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
908
909        #domain = Domain(points, vertices)
910        domain = Domain(points)
911
912        val0 = 2.+2.0/3
913        val1 = 4.+4.0/3
914        val2 = 8.+2.0/3
915        val3 = 2.+8.0/3
916
917        zl=zr=-3.75 #Assume constant bed (must be less than stage)
918        #domain.set_quantity('elevation', zl*ones( (4,3) ))
919        domain.set_quantity('elevation', zl*ones( (4,2) ))
920        #domain.set_quantity('stage', [[val0, val0-1, val0-2],
921        #                              [val1, val1+1, val1],
922        #                              [val2, val2-2, val2],
923        #                              [val3-0.5, val3, val3]])
924        domain.set_quantity('stage', [[val0, val0-1],
925                                      [val1, val1+1],
926                                      [val2, val2-2],
927                                      [val3-0.5, val3]])
928
929        domain.order = 1
930        domain.distribute_to_vertices_and_edges()
931
932        #Check that centroid values were distributed to vertices
933        C = domain.quantities['stage'].centroid_values
934        #for i in range(3):
935        for i in range(2):
936            assert allclose( domain.quantities['stage'].vertex_values[:,i], C)
937
938
939    def test_first_order_limiter_variable_z(self):
940        #Check that first order limiter follows bed_slope
941        from Numeric import alltrue, greater_equal
942        from config import epsilon
943
944        #a = [0.0, 0.0]
945        #b = [0.0, 2.0]
946        #c = [2.0,0.0]
947        #d = [0.0, 4.0]
948        #e = [2.0, 2.0]
949        #f = [4.0,0.0]
950        a=0.0
951        b=2.0
952        c=4.0
953        d=6.0
954        e=8.0
955        #f=10.0
956
957        #points = [a, b, c, d, e, f]
958        points = [a, b, c, d, e]
959        #bac, bce, ecf, dbe
960        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
961
962        #domain = Domain(points, vertices)
963        domain = Domain(points)
964
965        val0 = 2.+2.0/3
966        val1 = 4.+4.0/3
967        val2 = 8.+2.0/3
968        val3 = 2.+8.0/3
969
970        #domain.set_quantity('elevation', [[0,0,0], [6,0,0],
971        #                                  [6,6,6], [6,6,6]])
972        #domain.set_quantity('stage', [[val0, val0, val0],
973        #                              [val1, val1, val1],
974        #                              [val2, val2, val2],
975        #                              [val3, val3, val3]])
976        domain.set_quantity('elevation', [[0,0], [6,0],
977                                          [6,6], [6,6]])
978        domain.set_quantity('stage', [[val0, val0],
979                                      [val1, val1],
980                                      [val2, val2],
981                                      [val3, val3]])
982
983        E = domain.quantities['elevation'].vertex_values
984        L = domain.quantities['stage'].vertex_values
985
986
987        #Check that some stages are not above elevation (within eps)
988        #- so that the limiter has something to work with
989        assert not alltrue(alltrue(greater_equal(L,E-epsilon)))
990
991        domain.order = 1
992        domain.distribute_to_vertices_and_edges()
993
994        #Check that all stages are above elevation (within eps)
995        assert alltrue(alltrue(greater_equal(L,E-epsilon)))
996
997
998#####################################################
999    def test_distribute_basic(self):
1000        #Using test data generated by pyvolution-2
1001        #Assuming no friction and flat bed (0.0)
1002        print "\ntest distriute basic"
1003
1004        a=0.0
1005        b=2.0
1006        c=4.0
1007        d=6.0
1008        e=8.0
1009
1010        points = [a, b, c, d, e]
1011        domain = Domain(points)
1012
1013        val0 = 2.
1014        val1 = 4.
1015        val2 = 8.
1016        val3 = 2.
1017
1018        domain.set_quantity('stage', [val0, val1, val2, val3],
1019                            location='centroids')
1020        L = domain.quantities['stage'].vertex_values
1021
1022        #First order
1023        domain.order = 1
1024        domain.distribute_to_vertices_and_edges()
1025        print "First order L", L
1026        assert allclose(L[1], val1)
1027
1028        #Second order       
1029        domain.order = 2
1030        a = domain.quantities['stage'].compute_gradients()
1031        print 'gradients', a
1032               
1033        domain.distribute_to_vertices_and_edges()
1034        print "Second order L", L
1035        print "L[1]", L[1]
1036        #assert allclose(L[1], [2.2, 4.9, 4.9])
1037        assert allclose(L[1], [2.5, 5.5])
1038
1039    def test_distribute_away_from_bed(self):
1040        #Using test data generated by pyvolution-2
1041        #Assuming no friction and flat bed (0.0)
1042
1043        print "\ntest distribute awaway from bed"
1044
1045        a=0.0
1046        b=2.0
1047        c=4.0
1048        d=6.0
1049        e=8.0
1050        #f=10.0
1051
1052        #points = [a, b, c, d, e, f]
1053        points = [a, b, c, d, e]
1054
1055        domain = Domain(points)
1056
1057        L = domain.quantities['stage'].vertex_values
1058
1059        #def stage(x,y):
1060        #    return x**2
1061        def stage(x):
1062            return x**2
1063
1064        domain.set_quantity('stage', stage, location='centroids')
1065
1066        a = domain.quantities['stage'].compute_gradients()
1067        print 'a1', a
1068        ###assert allclose(a[1], 3.33333334)
1069        #assert allclose(b[1], 0.0)
1070
1071        domain.order = 1
1072        domain.distribute_to_vertices_and_edges()
1073        print 'l',L
1074        #assert allclose(L[1], 1.77777778)
1075        assert allclose(L[1], 9)
1076
1077        domain.order = 2
1078        domain.distribute_to_vertices_and_edges()
1079        assert allclose(L[1], [0.57777777, 2.37777778, 2.37777778])
1080
1081"""
1082    def test_1d_solution_I(self):
1083        print "TEST 1D-SOLUTION I"
1084
1085        L = 2000.0     # Length of channel (m)
1086        N = 100        # Number of compuational cells
1087        cell_len = L/N # Origin = 0.0
1088       
1089        points = zeros(N+1,Float)
1090        for i in range(N+1):
1091            points[i] = i*cell_len
1092           
1093        domain = Domain(points)
1094           
1095        def stage(x):
1096            for i in range(len(x)):
1097                if x[i]<=1000.0:
1098                    x[i] = 10.0
1099                else:
1100                    x[i] = 5.0
1101            return x
1102               
1103        domain.set_quantity('stage', stage)
1104        #L = domain.quantities['stage'].vertex_values
1105        #print "Initial Stage"
1106        #print L
1107        domain.set_boundary({'exterior': Reflective_boundary(domain)})
1108
1109        import time
1110        t0 = time.time()
1111        yieldstep = 10
1112        finaltime = 50.0
1113        for t in domain.evolve(yieldstep = yieldstep, finaltime = finaltime):
1114            pass
1115
1116        print 'That took %.2f seconds' %(time.time()-t0)
1117
1118        #L = domain.quantities['stage'].vertex_values
1119        #print "Final Stage"
1120        #print L
1121
1122        C = domain.quantities['stage'].vertex_values
1123        #print C
1124
1125        f = file('test_solution_I.out', 'w')
1126        for i in range(N):
1127            f.write(str(C[i,1]))
1128            f.write("\n")
1129        f.close
1130"""
1131"""
1132    def test_1d_solution_II(self):
1133        print "TEST 1D-SOLUTION II"
1134       
1135        L = 2000.0     # Length of channel (m)
1136        N = 100        # Number of compuational cells
1137        cell_len = L/N # Origin = 0.0
1138       
1139        points = zeros(N+1,Float)
1140        for i in range(N+1):
1141            points[i] = i*cell_len
1142           
1143        domain = Domain(points)
1144           
1145        def stage(x):
1146            for i in range(len(x)):
1147                if x[i]<=1000.0:
1148                    x[i] = 10.0
1149                else:
1150                    x[i] = 0.1
1151            return x
1152                   
1153
1154        domain.set_quantity('stage', stage)
1155        #L = domain.quantities['stage'].vertex_values
1156        #print "Initial Stage"
1157        #print L
1158        domain.set_boundary({'exterior': Reflective_boundary(domain)})
1159       
1160        import time
1161        t0 = time.time()
1162        yieldstep = 1.0
1163        finaltime = 50.0
1164       
1165        for t in domain.evolve(yieldstep = yieldstep, finaltime = finaltime):
1166            a=0
1167
1168        print 'That took %.2f seconds' %(time.time()-t0)
1169        #L = domain.quantities['stage'].vertex_values
1170        #print "Final Stage"
1171        #print L
1172
1173        C = domain.quantities['stage'].vertex_values
1174        #print C
1175       
1176        f = file('test_solution_II.out', 'w')
1177        for i in range(N):
1178            f.write(str(C[i,1]))
1179            f.write("\n")
1180        f.close
1181
1182    def test_1d_solution_III(self):
1183        print "TEST 1D-SOLUTION III"
1184        L = 2000.0     # Length of channel (m)
1185        N = 100        # Number of compuational cells
1186        cell_len = L/N # Origin = 0.0
1187       
1188        points = zeros(N+1,Float)
1189        for i in range(N+1):
1190            points[i] = i*cell_len
1191           
1192        domain = Domain(points)
1193
1194        def stage(x):
1195            for i in range(len(x)):
1196                if x[i]<=1000.0:
1197                    x[i] = 10.0
1198                else:
1199                    x[i] = 0.0
1200            return x
1201
1202        domain.set_quantity('stage', stage)
1203        #L = domain.quantities['stage'].vertex_values
1204        #print "Initial Stage"
1205        #print L
1206        domain.set_boundary({'exterior': Reflective_boundary(domain)})
1207       
1208        import time
1209        t0 = time.time()
1210        yieldstep = 1.0
1211        finaltime = 30.0
1212       
1213        for t in domain.evolve(yieldstep = yieldstep, finaltime = finaltime):
1214            a=0
1215           
1216        print 'That took %.2f seconds' %(time.time()-t0)
1217           
1218        #L = domain.quantities['stage'].vertex_values
1219        #print "Final Stage"
1220        #print L
1221       
1222        C = domain.quantities['stage'].vertex_values
1223        #print C
1224
1225        f = file('test_solution_III.out', 'w')
1226        for i in range(N):
1227            f.write(str(C[i,1]))
1228            f.write("\n")
1229        f.close
1230   """                                         
1231#-------------------------------------------------------------
1232if __name__ == "__main__":
1233    suite = unittest.makeSuite(TestCase,'test')
1234    runner = unittest.TextTestRunner(verbosity=2)
1235    runner.run(suite)
Note: See TracBrowser for help on using the repository browser.