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

Last change on this file since 3290 was 2791, checked in by jakeman, 19 years ago

Evolve is initially working

File size: 36.6 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
469        #a = [0.0, 0.0]
470        #b = [0.0, 2.0]
471        #c = [2.0,0.0]
472        #d = [0.0, 4.0]
473        #e = [2.0, 2.0]
474        #f = [4.0,0.0]
475        a=0.0
476        b=2.0
477        c=4.0
478        d=6.0
479        e=8.0
480        #f=10.0
481       
482        #points = [a, b, c, d, e, f]
483        points = [a, b, c, d, e]
484        #bac, bce, ecf, dbe
485        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
486
487        #domain = Domain(points, vertices)
488        domain = Domain(points)
489       
490        val0 = 2.+2.0/3
491        val1 = 4.+4.0/3
492        val2 = 8.+2.0/3
493        val3 = 2.+8.0/3
494
495        #domain.set_quantity('stage', [[val0, val0, val0], [val1, val1, val1],
496        #                              [val2, val2, val2], [val3, val3, val3]])
497        domain.set_quantity('stage', [[val0, val0], [val1, val1],
498                                      [val2, val2], [val3, val3]])
499        stage = domain.get_quantity('stage')
500        print stage
501        domain.check_integrity()
502
503        zl=zr=0. #Assume flat bed
504
505        #Flux across right edge of volume 1
506        #normal = domain.get_normal(1,0)
507        #ql = domain.get_conserved_quantities(vol_id=1, edge=0)
508        #qr = domain.get_conserved_quantities(vol_id=2, edge=2)
509        #flux0, max_speed = flux_function(normal, ql, qr, zl, zr)
510
511        #Flux across right edge of volume 1
512        #ql = domain.get_conserved_quantities(vol_id=1, edge=1)
513        #qr = domain.get_conserved_quantities(vol_id=2, edge=0)
514        ql = domain.get_conserved_quantities(vol_id=1, vertex=1)
515        qr = domain.get_conserved_quantities(vol_id=2, vertex=0)
516        print 'ql',ql
517        print 'qr',qr
518        flux0, max_speed = flux_function(1.0, ql, qr, zl, zr)
519        print 'flux0',flux0
520        print 'max_speed', max_speed
521       
522        #Check that flux seen from other triangles is inverse
523        #tmp = qr; qr=ql; ql=tmp
524        #normal = domain.get_normal(3,0)
525        #flux, max_speed = flux_function(normal, ql, qr, zl, zr)
526        flux, max_speed = flux_function(-1.0, qr, ql, zl, zr)
527        print flux0
528        print flux
529        assert allclose(flux + flux0, 0.)
530
531        #print flux0
532        #print max_speed
533        #assert allclose(flux0, [-15.3598804, 253.71111111, 0.])
534        assert allclose(flux0, [-15.3598804, 253.71111111])
535        assert allclose(max_speed, 9.21592824046)
536
537
538        #Flux across upper edge of volume 1
539        #normal = domain.get_normal(1,1)
540        #ql = domain.get_conserved_quantities(vol_id=1, edge=1)
541        #qr = domain.get_conserved_quantities(vol_id=2, edge=0)
542        ql = domain.get_conserved_quantities(vol_id=1, vertex=0)
543        qr = domain.get_conserved_quantities(vol_id=0, vertex=1)
544        #flux1, max_speed = flux_function(normal, ql, qr, zl, zr)
545        flux1, max_speed = flux_function(-1.0, ql, qr, zl, zr)
546        #assert allclose(flux1, [2.4098563, 0., 123.04444444])
547        print 'flux1', flux1
548        assert allclose(flux1, [2.4098563, 0.])
549        assert allclose(max_speed, 7.22956891292)
550
551        #Flux across lower left hypotenuse of volume 1
552        #normal = domain.get_normal(1,2)
553        #ql = domain.get_conserved_quantities(vol_id=1, edge=2)
554        #qr = domain.get_conserved_quantities(vol_id=0, edge=1)
555        #ql = domain.get_conserved_quantities(vol_id=1, vertex=2)
556        #qr = domain.get_conserved_quantities(vol_id=0, vertex=1)
557        #flux2, max_speed = flux_function(normal, ql, qr, zl, zr)
558
559        #assert allclose(flux2, [9.63942522, -61.59685738, -61.59685738])
560        #assert allclose(max_speed, 7.22956891292)
561
562        #Scale, add up and check that compute_fluxes is correct for vol 1
563        #e0 = domain.edgelengths[1, 0]
564        #e1 = domain.edgelengths[1, 1]
565        #e2 = domain.edgelengths[1, 2]
566
567        #total_flux = -(e0*flux0+e1*flux1+e2*flux2)/domain.areas[1]
568        total_flux = -(flux0+flux1)/domain.areas[1]
569        #assert allclose(total_flux, [-0.68218178, -166.6, -35.93333333])
570        assert allclose(total_flux, [-0.68218178, -166.6])
571       
572
573
574        domain.compute_fluxes()
575
576        #assert allclose(total_flux, domain.explicit_update[1,:])
577        for i, name in enumerate(['stage', 'xmomentum', 'ymomentum']):
578            assert allclose(total_flux[i],
579                            domain.quantities[name].explicit_update[1])
580
581        #assert allclose(domain.explicit_update, [
582        #    [0., -69.68888889, -69.68888889],
583        #    [-0.68218178, -166.6, -35.93333333],
584        #    [-111.77316251, 69.68888889, 0.],
585        #    [-35.68522449, 0., 69.68888889]])
586
587        assert allclose(domain.quantities['stage'].explicit_update,
588                        [0., -0.68218178, -111.77316251, -35.68522449])
589        assert allclose(domain.quantities['xmomentum'].explicit_update,
590                        [-69.68888889, -166.6, 69.68888889, 0])
591        assert allclose(domain.quantities['ymomentum'].explicit_update,
592                        [-69.68888889, -35.93333333, 0., 69.68888889])
593
594
595        #assert allclose(domain.quantities[name].explicit_update
596
597    def test_catching_negative_heights(self):
598
599        #a = [0.0, 0.0]
600        #b = [0.0, 2.0]
601        #c = [2.0,0.0]
602        #d = [0.0, 4.0]
603        #e = [2.0, 2.0]
604        #f = [4.0,0.0]
605        a=0.0
606        b=2.0
607        c=4.0
608        d=6.0
609        e=8.0
610        #f=10.0
611
612        #points = [a, b, c, d, e, f]
613        points = [a, b, c, d, e]
614        #bac, bce, ecf, dbe
615        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
616
617        #domain = Domain(points, vertices)
618        domain = Domain(points)
619        val0 = 2.+2.0/3
620        val1 = 4.+4.0/3
621        val2 = 8.+2.0/3
622        val3 = 2.+8.0/3
623
624        zl=zr=4  #Too large
625        #domain.set_quantity('elevation', zl*ones( (4,3) ))
626        #domain.set_quantity('stage', [[val0, val0-1, val0-2],
627        #                              [val1, val1+1, val1],
628        #                              [val2, val2-2, val2],
629        #                              [val3-0.5, val3, val3]])
630        domain.set_quantity('elevation', zl*ones( (4,2) ))
631        domain.set_quantity('stage', [[val0, val0-1],
632                                      [val1, val1+1],
633                                      [val2, val2-2],
634                                      [val3-0.5, val3]])
635
636        #Should fail
637        try:
638            domain.check_integrity()
639        except:
640            pass
641
642    def test_initial_condition(self):
643        """Test that initial condition is output at time == 0
644        """
645
646        from config import g
647        import copy
648
649        #a = [0.0, 0.0]
650        #b = [0.0, 2.0]
651        #c = [2.0, 0.0]
652        #d = [0.0, 4.0]
653        #e = [2.0, 2.0]
654        #f = [4.0, 0.0]
655        a=0.0
656        b=2.0
657        c=4.0
658        d=6.0
659        e=8.0
660        #f=10.0
661
662        #points = [a, b, c, d, e, f]
663        points = [a, b, c, d, e]
664        #bac, bce, ecf, dbe
665        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
666
667        #domain = Domain(points, vertices)
668        domain = Domain(points)
669
670        #Set up for a gradient of (3,0) at mid triangle
671        #def slope(x, y):
672        #    return 3*x
673        def slope(x):
674            return 3*x
675
676        h = 0.1
677        #def stage(x,y):
678        #    return slope(x,y)+h
679        def stage(x):
680            return slope(x)+h
681
682        domain.set_quantity('elevation', slope)
683        domain.set_quantity('stage', stage)
684
685        initial_stage = copy.copy(domain.quantities['stage'].vertex_values)
686
687        domain.set_boundary({'exterior': Reflective_boundary(domain)})
688
689        #Evolution
690        for t in domain.evolve(yieldstep = 1.0, finaltime = 2.0):
691            stage = domain.quantities['stage'].vertex_values
692
693            if t == 0.0:
694                assert allclose(stage, initial_stage)
695            else:
696                assert not allclose(stage, initial_stage)
697
698        os.remove(domain.filename + '.sww')
699
700    #####################################################
701    def test_gravity(self):
702        #Assuming no friction
703
704        from config import g
705        #a = [0.0, 0.0]
706        #b = [0.0, 2.0]
707        #c = [2.0, 0.0]
708        #d = [0.0, 4.0]
709        #e = [2.0, 2.0]
710        #f = [4.0, 0.0]
711        a=0.0
712        b=2.0
713        c=4.0
714        d=6.0
715        e=8.0
716        #f=10.0
717
718        #points = [a, b, c, d, e, f]
719        points = [a, b, c, d, e]
720        #bac, bce, ecf, dbe
721        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
722
723        #domain = Domain(points, vertices)
724        domain = Domain(points)
725
726        def slope(x):
727            return 3*x
728
729        h = 0.1
730        #def stage(x,y):
731        #    return slope(x,y)+h
732        def stage(x):
733            return slope(x)+h
734
735
736        domain.set_quantity('elevation', slope)
737        domain.set_quantity('stage', stage)
738
739        for name in domain.conserved_quantities:
740            assert allclose(domain.quantities[name].explicit_update, 0)
741            assert allclose(domain.quantities[name].semi_implicit_update, 0)
742
743        domain.compute_forcing_terms()
744
745        assert allclose(domain.quantities['stage'].explicit_update, 0)
746        assert allclose(domain.quantities['xmomentum'].explicit_update, -g*h*3)
747        #assert allclose(domain.quantities['ymomentum'].explicit_update, 0)
748
749
750    def test_manning_friction(self):
751        from config import g
752
753        #a = [0.0, 0.0]
754        #b = [0.0, 2.0]
755        #c = [2.0, 0.0]
756        #d = [0.0, 4.0]
757        #e = [2.0, 2.0]
758        #f = [4.0, 0.0]
759        a=0.0
760        b=2.0
761        c=4.0
762        d=6.0
763        e=8.0
764        #f=10.0
765
766        #points = [a, b, c, d, e, f]
767        points = [a, b, c, d, e]
768        #bac, bce, ecf, dbe
769        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
770
771        #domain = Domain(points, vertices)
772        domain = Domain(points)
773
774        #Set up for a gradient of (3,0) at mid triangle
775        def slope(x):
776            return 3*x
777
778        h = 0.1
779        #def stage(x,y):
780        #    return slope(x,y)+h
781        def stage(x):
782            return slope(x)+h
783
784        eta = 0.07
785        domain.set_quantity('elevation', slope)
786        domain.set_quantity('stage', stage)
787        domain.set_quantity('friction', eta)
788
789        for name in domain.conserved_quantities:
790            assert allclose(domain.quantities[name].explicit_update, 0)
791            assert allclose(domain.quantities[name].semi_implicit_update, 0)
792
793        domain.compute_forcing_terms()
794
795        assert allclose(domain.quantities['stage'].explicit_update, 0)
796        assert allclose(domain.quantities['xmomentum'].explicit_update, -g*h*3)
797        #assert allclose(domain.quantities['ymomentum'].explicit_update, 0)
798
799        assert allclose(domain.quantities['stage'].semi_implicit_update, 0)
800        assert allclose(domain.quantities['xmomentum'].semi_implicit_update, 0)
801        #assert allclose(domain.quantities['ymomentum'].semi_implicit_update, 0)
802
803        #Create some momentum for friction to work with
804        domain.set_quantity('xmomentum', 1)
805        S = -g * eta**2 / h**(7.0/3)
806
807        domain.compute_forcing_terms()
808        assert allclose(domain.quantities['stage'].semi_implicit_update, 0)
809        assert allclose(domain.quantities['xmomentum'].semi_implicit_update, S)
810        #assert allclose(domain.quantities['ymomentum'].semi_implicit_update, 0)
811
812        #A more complex example
813        domain.quantities['stage'].semi_implicit_update[:] = 0.0
814        domain.quantities['xmomentum'].semi_implicit_update[:] = 0.0
815        #domain.quantities['ymomentum'].semi_implicit_update[:] = 0.0
816
817        #domain.set_quantity('xmomentum', 3)
818        domain.set_quantity('xmomentum', 5)
819        #domain.set_quantity('ymomentum', 4)
820
821        S = -g * eta**2 * 5 / h**(7.0/3)
822        #S = -g * eta**2 / h**(7.0/3)
823
824
825        domain.compute_forcing_terms()
826
827        assert allclose(domain.quantities['stage'].semi_implicit_update, 0)
828        print '5*S', 5*S
829        #CHECK THIS TEST
830        print domain.quantities['xmomentum'].semi_implicit_update
831        #assert allclose(domain.quantities['xmomentum'].semi_implicit_update, 3*S)
832        assert allclose(domain.quantities['xmomentum'].semi_implicit_update, 5*S)
833        #assert allclose(domain.quantities['ymomentum'].semi_implicit_update, 4*S)
834
835    def test_constant_wind_stress(self):
836        from config import rho_a, rho_w, eta_w
837        from math import pi, cos, sin, sqrt
838
839       
840        #a = [0.0, 0.0]
841        #b = [0.0, 2.0]
842        #c = [2.0, 0.0]
843        #d = [0.0, 4.0]
844        #e = [2.0, 2.0]
845        #f = [4.0, 0.0]
846        a=0.0
847        b=2.0
848        c=4.0
849        d=6.0
850        e=8.0
851        #f=10.0
852
853        #points = [a, b, c, d, e, f]
854        points = [a, b, c, d, e]
855        #bac, bce, ecf, dbe
856        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
857
858        #domain = Domain(points, vertices)
859        domain = Domain(points)
860       
861        #Flat surface with 1m of water
862        domain.set_quantity('elevation', 0)
863        domain.set_quantity('stage', 1.0)
864        domain.set_quantity('friction', 0)
865
866        Br = Reflective_boundary(domain)
867        domain.set_boundary({'exterior': Br})
868
869        #Setup only one forcing term, constant wind stress
870        s = 100
871        phi = 135
872        domain.forcing_terms = []
873        domain.forcing_terms.append( Wind_stress(s, phi) )
874
875        domain.compute_forcing_terms()
876
877
878        const = eta_w*rho_a/rho_w
879
880        #Convert to radians
881        phi = phi*pi/180
882
883        #Compute velocity vector (u, v)
884        u = s*cos(phi)
885        #v = s*sin(phi)
886
887        #Compute wind stress
888        #S = const * sqrt(u**2 + v**2)
889        S = const * u
890       
891
892        assert allclose(domain.quantities['stage'].explicit_update, 0)
893        assert allclose(domain.quantities['xmomentum'].explicit_update, S*u)
894        #assert allclose(domain.quantities['ymomentum'].explicit_update, S*v)
895
896
897    def test_variable_wind_stress(self):
898        from config import rho_a, rho_w, eta_w
899        from math import pi, cos, sin, sqrt
900
901        #a = [0.0, 0.0]
902        #b = [0.0, 2.0]
903        #c = [2.0, 0.0]
904        #d = [0.0, 4.0]
905        #e = [2.0, 2.0]
906        #f = [4.0, 0.0]
907        a=0.0
908        b=2.0
909        c=4.0
910        d=6.0
911        e=8.0
912        #f=10.0
913
914        #points = [a, b, c, d, e, f]
915        points = [a, b, c, d, e]
916        #bac, bce, ecf, dbe
917        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
918
919        #domain = Domain(points, vertices)
920        domain = Domain(points)
921
922        #Flat surface with 1m of water
923        domain.set_quantity('elevation', 0)
924        domain.set_quantity('stage', 1.0)
925        domain.set_quantity('friction', 0)
926
927        Br = Reflective_boundary(domain)
928        domain.set_boundary({'exterior': Br})
929
930        domain.time = 5.54 #Take a random time (not zero)
931
932        #Setup only one forcing term, constant wind stress
933        s = 100
934        phi = 135
935        domain.forcing_terms = []
936        domain.forcing_terms.append( Wind_stress(s = speed, phi = angle) )
937
938        domain.compute_forcing_terms()
939
940        #Compute reference solution
941        const = eta_w*rho_a/rho_w
942
943        N = domain.number_of_elements
944
945        xc = domain.get_centroid_coordinates()
946        t = domain.time
947
948        #x = xc[:,0]
949        #y = xc[:,1]
950        x = xc
951       
952        #s_vec = speed(t,x,y)
953        #phi_vec = angle(t,x,y)
954        s_vec = speed(t,x)
955        phi_vec = angle(t,x)
956
957
958        for k in range(N):
959            #Convert to radians
960            phi = phi_vec[k]*pi/180
961            s = s_vec[k]
962
963            #Compute velocity vector (u, v)
964            u = s*cos(phi)
965            #v = s*sin(phi)
966
967            #Compute wind stress
968            #S = const * sqrt(u**2 + v**2)
969            S = const*u
970
971            assert allclose(domain.quantities['stage'].explicit_update[k], 0)
972            assert allclose(domain.quantities['xmomentum'].explicit_update[k], S*u)
973            #assert allclose(domain.quantities['ymomentum'].explicit_update[k], S*v)
974
975    def test_first_order_extrapolator_const_z(self):
976
977        #a = [0.0, 0.0]
978        #b = [0.0, 2.0]
979        #c = [2.0, 0.0]
980        #d = [0.0, 4.0]
981        #e = [2.0, 2.0]
982        #f = [4.0, 0.0]
983        a=0.0
984        b=2.0
985        c=4.0
986        d=6.0
987        e=8.0
988        #f=10.0
989
990        #points = [a, b, c, d, e, f]
991        points = [a, b, c, d, e]
992        #bac, bce, ecf, dbe
993        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
994
995        #domain = Domain(points, vertices)
996        domain = Domain(points)
997
998        val0 = 2.+2.0/3
999        val1 = 4.+4.0/3
1000        val2 = 8.+2.0/3
1001        val3 = 2.+8.0/3
1002
1003        zl=zr=-3.75 #Assume constant bed (must be less than stage)
1004        #domain.set_quantity('elevation', zl*ones( (4,3) ))
1005        domain.set_quantity('elevation', zl*ones( (4,2) ))
1006        #domain.set_quantity('stage', [[val0, val0-1, val0-2],
1007        #                              [val1, val1+1, val1],
1008        #                              [val2, val2-2, val2],
1009        #                              [val3-0.5, val3, val3]])
1010        domain.set_quantity('stage', [[val0, val0-1],
1011                                      [val1, val1+1],
1012                                      [val2, val2-2],
1013                                      [val3-0.5, val3]])
1014
1015        domain.order = 1
1016        domain.distribute_to_vertices_and_edges()
1017
1018        #Check that centroid values were distributed to vertices
1019        C = domain.quantities['stage'].centroid_values
1020        #for i in range(3):
1021        for i in range(2):
1022            assert allclose( domain.quantities['stage'].vertex_values[:,i], C)
1023
1024
1025    def test_first_order_limiter_variable_z(self):
1026        #Check that first order limiter follows bed_slope
1027        from Numeric import alltrue, greater_equal
1028        from config import epsilon
1029
1030        #a = [0.0, 0.0]
1031        #b = [0.0, 2.0]
1032        #c = [2.0,0.0]
1033        #d = [0.0, 4.0]
1034        #e = [2.0, 2.0]
1035        #f = [4.0,0.0]
1036        a=0.0
1037        b=2.0
1038        c=4.0
1039        d=6.0
1040        e=8.0
1041        #f=10.0
1042
1043        #points = [a, b, c, d, e, f]
1044        points = [a, b, c, d, e]
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        domain = Domain(points)
1050
1051        val0 = 2.+2.0/3
1052        val1 = 4.+4.0/3
1053        val2 = 8.+2.0/3
1054        val3 = 2.+8.0/3
1055
1056        #domain.set_quantity('elevation', [[0,0,0], [6,0,0],
1057        #                                  [6,6,6], [6,6,6]])
1058        #domain.set_quantity('stage', [[val0, val0, val0],
1059        #                              [val1, val1, val1],
1060        #                              [val2, val2, val2],
1061        #                              [val3, val3, val3]])
1062        domain.set_quantity('elevation', [[0,0], [6,0],
1063                                          [6,6], [6,6]])
1064        domain.set_quantity('stage', [[val0, val0],
1065                                      [val1, val1],
1066                                      [val2, val2],
1067                                      [val3, val3]])
1068
1069        E = domain.quantities['elevation'].vertex_values
1070        L = domain.quantities['stage'].vertex_values
1071
1072
1073        #Check that some stages are not above elevation (within eps)
1074        #- so that the limiter has something to work with
1075        assert not alltrue(alltrue(greater_equal(L,E-epsilon)))
1076
1077        domain.order = 1
1078        domain.distribute_to_vertices_and_edges()
1079
1080        #Check that all stages are above elevation (within eps)
1081        assert alltrue(alltrue(greater_equal(L,E-epsilon)))
1082
1083
1084#####################################################
1085    def test_distribute_basic(self):
1086        #Using test data generated by pyvolution-2
1087        #Assuming no friction and flat bed (0.0)
1088
1089        #a = [0.0, 0.0]
1090        #b = [0.0, 2.0]
1091        #c = [2.0,0.0]
1092        #d = [0.0, 4.0]
1093        #e = [2.0, 2.0]
1094        #f = [4.0,0.0]
1095        a=0.0
1096        b=2.0
1097        c=4.0
1098        d=6.0
1099        e=8.0
1100        #f=10.0
1101
1102        #points = [a, b, c, d, e, f]
1103        points = [a, b, c, d, e]
1104        #bac, bce, ecf, dbe
1105        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
1106
1107        #domain = Domain(points, vertices)
1108        domain = Domain(points)
1109
1110        val0 = 2.
1111        val1 = 4.
1112        val2 = 8.
1113        val3 = 2.
1114
1115        domain.set_quantity('stage', [val0, val1, val2, val3],
1116                            location='centroids')
1117        L = domain.quantities['stage'].vertex_values
1118
1119        #First order
1120        domain.order = 1
1121        domain.distribute_to_vertices_and_edges()
1122        assert allclose(L[1], val1)
1123
1124        #Second order
1125        domain.order = 2
1126        domain.distribute_to_vertices_and_edges()
1127        assert allclose(L[1], [2.2, 4.9, 4.9])
1128
1129
1130
1131    def test_distribute_away_from_bed(self):
1132        #Using test data generated by pyvolution-2
1133        #Assuming no friction and flat bed (0.0)
1134
1135        #a = [0.0, 0.0]
1136        #b = [0.0, 2.0]
1137        #c = [2.0,0.0]
1138        #d = [0.0, 4.0]
1139        #e = [2.0, 2.0]
1140        #f = [4.0,0.0]
1141        a=0.0
1142        b=2.0
1143        c=4.0
1144        d=6.0
1145        e=8.0
1146        #f=10.0
1147
1148        #points = [a, b, c, d, e, f]
1149        points = [a, b, c, d, e]
1150        #bac, bce, ecf, dbe
1151        #vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
1152
1153        #domain = Domain(points, vertices)
1154        domain = Domain(points)
1155
1156        L = domain.quantities['stage'].vertex_values
1157
1158        #def stage(x,y):
1159        #    return x**2
1160        def stage(x):
1161            return x**2
1162
1163        domain.set_quantity('stage', stage, location='centroids')
1164
1165        a = domain.quantities['stage'].compute_gradients()
1166        print 'a1', a
1167        ###assert allclose(a[1], 3.33333334)
1168        #assert allclose(b[1], 0.0)
1169
1170        domain.order = 1
1171        domain.distribute_to_vertices_and_edges()
1172        print 'l',L
1173        #assert allclose(L[1], 1.77777778)
1174        assert allclose(L[1], 9)
1175
1176        domain.order = 2
1177        domain.distribute_to_vertices_and_edges()
1178        assert allclose(L[1], [0.57777777, 2.37777778, 2.37777778])
1179
1180
1181
1182
1183
1184#-------------------------------------------------------------
1185if __name__ == "__main__":
1186    suite = unittest.makeSuite(TestCase,'test')
1187    runner = unittest.TextTestRunner(verbosity=2)
1188    runner.run(suite)
Note: See TracBrowser for help on using the repository browser.