Changeset 9383


Ignore:
Timestamp:
Dec 16, 2014, 2:27:44 PM (10 years ago)
Author:
steve
Message:

get_flow_through_polygon should now work if sww stored uniquely

Location:
trunk/anuga_core/source/anuga
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/anuga_core/source/anuga/file/sww.py

    r9263 r9383  
    13681368        raise DataDomainError, msg
    13691369
     1370    def gather(quantity):
     1371           
     1372        shape = quantity.shape
     1373       
     1374        if len(shape) == 2:
     1375            # time array
     1376            if shape[1] == len(mesh.nodes):
     1377                return quantity
     1378            # need to calculate unique vertex values
     1379            n_time = shape[0]
     1380            n_nodes = len(mesh.nodes)
     1381           
     1382            mesh_ids = mesh.triangles.ravel()
     1383            temp_uv = num.zeros((n_time,n_nodes))
     1384       
     1385            count_uv = num.zeros(len(mesh.nodes))
     1386            num.add.at(count_uv, mesh_ids, 1)
     1387   
     1388            for i in range(n_time):
     1389                num.add.at(temp_uv[i,:], mesh_ids, quantity[i,:] )
     1390                temp_uv[i,:] = temp_uv[i,:]/count_uv
     1391   
     1392        elif len(shape) == 1:
     1393            # non time array
     1394            if shape[0] == len(mesh.nodes):
     1395                return quantity
     1396           
     1397            mesh_ids = mesh.triangles.ravel()
     1398            temp_uv = num.zeros(len(mesh.nodes))
     1399
     1400            count_uv = num.zeros(len(mesh.nodes))
     1401            num.add.at(count_uv, mesh_ids, 1)
     1402            num.add.at(temp_uv, mesh_ids, quantity )
     1403           
     1404        else:
     1405            raise Exception
     1406       
     1407        return temp_uv
     1408
     1409       
    13701410    quantities = {}
    1371     quantities['elevation'] = elevation
    1372     quantities['stage'] = stage
    1373     quantities['xmomentum'] = xmomentum
    1374     quantities['ymomentum'] = ymomentum
     1411    quantities['elevation'] = gather(elevation)
     1412    quantities['stage'] = gather(stage)
     1413    quantities['xmomentum'] = gather(xmomentum)
     1414    quantities['ymomentum'] = gather(ymomentum)
    13751415
    13761416    fid.close()
  • trunk/anuga_core/source/anuga/file/test_sww.py

    r9382 r9383  
    263263        length = 50
    264264        t_end = 10
    265         points, vertices, boundary = rectangular(length, width, 50, 5)
     265        points, vertices, boundary = rectangular(10, 1, length, width)
    266266
    267267        # Create shallow water domain
     
    294294        mesh, quantities, time = X
    295295       
    296 
     296       
     297       
     298
     299        #print quantities
     300        #print time
     301
     302        dhash = domain.get_nodes()[:,0]*10+domain.get_nodes()[:,1]
     303        mhash = mesh.nodes[:,0]*10+mesh.nodes[:,1]       
     304
     305
     306        #print 'd_nodes',len(dhash)
     307        #print 'm_nodes',len(mhash)
     308        di = num.argsort(dhash)
     309        mi = num.argsort(mhash)
     310        minv = num.argsort(mi)
     311        dinv = num.argsort(di)
     312
     313        #print 'd_tri',len(domain.get_triangles())
     314        #print 'm_tri',len(mesh.triangles)
     315       
    297316        # Check that mesh has been recovered
    298         assert num.alltrue(mesh.triangles == domain.get_triangles())
    299         assert num.allclose(mesh.nodes, domain.get_nodes())
     317        # triangle order should be ok
     318        assert num.allclose(mesh.nodes[mi,:],domain.get_nodes()[di,:])
     319        assert num.alltrue(minv[mesh.triangles] == dinv[domain.get_triangles()])
     320
    300321
    301322        # Check that time has been recovered
    302323        assert num.allclose(time, range(t_end+1))
    303324
    304         # Check that quantities have been recovered
    305         # (sww files use single precision)
    306325        z=domain.get_quantity('elevation').get_values(location='unique vertices')
     326       
    307327        assert num.allclose(quantities['elevation'], z)
    308328
     
    313333            #print q,quantities[q]
    314334            q_sww=quantities[q][-1,:]
    315 
     335           
    316336            msg = 'Quantity %s failed to be recovered' %q
    317             assert num.allclose(q_ref, q_sww, atol=1.0e-6), msg
     337            assert num.allclose(q_ref[di], q_sww[mi], atol=1.0e-6), msg
    318338           
    319339        # Cleanup
  • trunk/anuga_core/source/anuga/shallow_water/test_sww_interrogate.py

    r8996 r9383  
    321321
    322322
     323    def test_get_flow_through_cross_section_stored_uniquely(self):
     324        """test_get_flow_through_cross_section_stored_uniquely(self):
     325
     326        Test that the total flow through a cross section can be
     327        correctly obtained from an sww file.
     328       
     329        This test creates a flat bed with a known flow through it and tests
     330        that the function correctly returns the expected flow.
     331
     332        The specifics are
     333        u = 2 m/s
     334        h = 1 m
     335        w = 3 m (width of channel)
     336
     337        q = u*h*w = 6 m^3/s
     338       
     339       
     340        """
     341
     342        import time, os
     343        from anuga.file.netcdf import NetCDFFile
     344
     345        # Setup
     346        from mesh_factory import rectangular
     347
     348        # Create basic mesh (20m x 3m)
     349        width = 3
     350        length = 20
     351        t_end = 3
     352        points, vertices, boundary = rectangular(length, width,
     353                                                 length, width)
     354
     355        # Create shallow water domain
     356        domain = Domain(points, vertices, boundary)
     357        domain.default_order = 2
     358        domain.set_minimum_storable_height(0.01)
     359
     360        domain.set_name('flowtest_uniquely')
     361        swwfile = domain.get_name() + '.sww'
     362
     363        domain.set_store_vertices_uniquely()
     364       
     365        domain.set_datadir('.')
     366        domain.format = 'sww'
     367        domain.smooth = True
     368
     369        h = 1.0
     370        u = 2.0
     371        uh = u*h
     372
     373        Br = Reflective_boundary(domain)     # Side walls
     374        Bd = Dirichlet_boundary([h, uh, 0])  # 2 m/s across the 3 m inlet:
     375
     376
     377       
     378        domain.set_quantity('elevation', 0.0)
     379        domain.set_quantity('stage', h)
     380        domain.set_quantity('xmomentum', uh)
     381        domain.set_boundary( {'left': Bd, 'right': Bd, 'top': Br, 'bottom': Br})
     382
     383        for t in domain.evolve(yieldstep=1, finaltime = t_end):
     384            pass
     385
     386        # Check that momentum is as it should be in the interior
     387
     388        I = [[0, width/2.],
     389             [length/2., width/2.],
     390             [length, width/2.]]
     391       
     392        f = file_function(swwfile,
     393                          quantities=['stage', 'xmomentum', 'ymomentum'],
     394                          interpolation_points=I,
     395                          verbose=False)
     396        for t in range(t_end+1):
     397            for i in range(3):
     398                assert num.allclose(f(t, i), [1, 2, 0], atol=1.0e-6)
     399           
     400
     401        # Check flows through the middle
     402        for i in range(5):
     403            x = length/2. + i*0.23674563 # Arbitrary
     404            cross_section = [[x, 0], [x, width]]
     405            time, Q = get_flow_through_cross_section(swwfile,
     406                                                     cross_section,
     407                                                     verbose=False)
     408
     409            assert num.allclose(Q, uh*width)
     410
     411
     412       
     413        # Try the same with partial lines
     414        x = length/2.
     415        for i in range(5):
     416            start_point = [length/2., i*width/5.]
     417            #print start_point
     418                           
     419            cross_section = [start_point, [length/2., width]]
     420            time, Q = get_flow_through_cross_section(swwfile,
     421                                                     cross_section,
     422                                                     verbose=False)
     423
     424            #print i, Q, (width-start_point[1])
     425            assert num.allclose(Q, uh*(width-start_point[1]))
     426
     427
     428        # Verify no flow when line is parallel to flow
     429        cross_section = [[length/2.-10, width/2.], [length/2.+10, width/2.]]
     430        time, Q = get_flow_through_cross_section(swwfile,
     431                                                 cross_section,
     432                                                 verbose=False)
     433
     434        #print i, Q
     435        assert num.allclose(Q, 0, atol=1.0e-5)       
     436
     437
     438        # Try with lines on an angle (all flow still runs through here)
     439        cross_section = [[length/2., 0], [length/2.+width, width]]
     440        time, Q = get_flow_through_cross_section(swwfile,
     441                                                 cross_section,
     442                                                 verbose=False)
     443
     444        assert num.allclose(Q, uh*width)       
     445       
     446
     447
    323448                                     
    324449    def test_get_flow_through_cross_section_with_geo(self):
     
    529654
    530655
     656
     657
     658
    531659    def test_get_maximum_inundation_from_sww(self):
    532660        """test_get_maximum_inundation_from_sww(self)
    533661
    534662        Test of get_maximum_inundation_elevation()
    535         and get_maximum_inundation_location() from data_manager.py
    536 
     663        and get_maximum_inundation_location().
     664   
    537665        This is based on test_get_maximum_inundation_3(self) but works with the
    538666        stored results instead of with the internal data structure.
     
    541669        """
    542670
    543 
     671        verbose = False
     672        from anuga.config import minimum_storable_height
     673       
    544674        initial_runup_height = -0.4
    545675        final_runup_height = -0.3
    546 
    547         filename = 'runup_test_1'
     676        filename = 'runup_test_2'
    548677
    549678        #--------------------------------------------------------------
     
    555684        domain.set_name(filename)
    556685        domain.set_maximum_allowed_speed(1.0)
     686        #domain.set_minimum_storable_height(1.0e-5)
     687        domain.set_store_vertices_uniquely()
    557688
    558689        # FIXME: This works better with old limiters so far
     
    588719        assert num.alltrue(z < initial_runup_height)
    589720
    590         q_ref = domain.get_maximum_inundation_elevation()
     721        q_ref = domain.get_maximum_inundation_elevation(minimum_height=minimum_storable_height)
    591722        # First order accuracy
    592723        assert num.allclose(q_ref, initial_runup_height, rtol=1.0/N)
     
    595726        # Let triangles adjust
    596727        #--------------------------------------------------------------
     728        q_max = None
    597729        for t in domain.evolve(yieldstep = 0.1, finaltime = 1.0):
    598             pass
     730            q = domain.get_maximum_inundation_elevation(minimum_height=minimum_storable_height)
     731
     732            if verbose:
     733                domain.write_time()
     734                print q
     735               
     736            if q > q_max:
     737                q_max = q
    599738
    600739        #--------------------------------------------------------------
    601740        # Test inundation height again
    602741        #--------------------------------------------------------------
    603         q_ref = domain.get_maximum_inundation_elevation()
     742        #q_ref = domain.get_maximum_inundation_elevation()
    604743        q = get_maximum_inundation_elevation(filename+'.sww')
    605         msg = 'We got %f, should have been %f' % (q, q_ref)
    606         assert num.allclose(q, q_ref, rtol=1.0/N), msg
    607 
    608         q = get_maximum_inundation_elevation(filename+'.sww')
     744        msg = 'We got %f, should have been %f' % (q, q_max)
     745        assert num.allclose(q, q_max, rtol=2.0/N), msg
     746
    609747        msg = 'We got %f, should have been %f' % (q, initial_runup_height)
    610748        assert num.allclose(q, initial_runup_height, rtol = 1.0/N), msg
     
    635773        # Evolve system through time
    636774        #--------------------------------------------------------------
    637         q_max = None
     775       
    638776        for t in domain.evolve(yieldstep = 0.1, finaltime = 3.0,
    639777                               skip_initial_step = True):
    640             q = domain.get_maximum_inundation_elevation()
     778            q = domain.get_maximum_inundation_elevation(minimum_height=minimum_storable_height)
     779
     780            if verbose:
     781                domain.write_time()
     782                print q
     783
    641784            if q > q_max:
    642785                q_max = q
     786               
    643787
    644788        #--------------------------------------------------------------
     
    649793                get_values(location='centroids', indices=indices)
    650794
    651         assert num.alltrue(z < final_runup_height)
     795
     796        assert num.alltrue(z < final_runup_height+1.0/N)
    652797
    653798        q = domain.get_maximum_inundation_elevation()
     
    661806        assert num.allclose(-loc[0]/2, q)    # From topography formula
    662807
    663         q = get_maximum_inundation_elevation(filename+'.sww')
     808        q = get_maximum_inundation_elevation(filename+'.sww',verbose = verbose)
    664809        loc = get_maximum_inundation_location(filename+'.sww')
     810       
     811       
    665812        msg = 'We got %f, should have been %f' % (q, q_max)
    666813        assert num.allclose(q, q_max, rtol=1.0/N), msg
     
    713860        # Cleanup
    714861        try:
    715             os.remove(domain.get_name() + '.sww')
    716         except:
    717             pass
    718             #FIXME(Ole): Windows won't allow removal of this
    719 
    720 
    721     def test_get_maximum_inundation_from_sww(self):
    722         """test_get_maximum_inundation_from_sww(self)
    723 
    724         Test of get_maximum_inundation_elevation()
    725         and get_maximum_inundation_location().
    726    
    727         This is based on test_get_maximum_inundation_3(self) but works with the
    728         stored results instead of with the internal data structure.
    729 
    730         This test uses the underlying get_maximum_inundation_data for tests
    731         """
    732 
    733         verbose = False
    734         from anuga.config import minimum_storable_height
    735        
    736         initial_runup_height = -0.4
    737         final_runup_height = -0.3
    738         filename = 'runup_test_2'
    739 
    740         #--------------------------------------------------------------
    741         # Setup computational domain
    742         #--------------------------------------------------------------
    743         N = 10
    744         points, vertices, boundary = rectangular_cross(N, N)
    745         domain = Domain(points, vertices, boundary)
    746         domain.set_name(filename)
    747         domain.set_maximum_allowed_speed(1.0)
    748         #domain.set_minimum_storable_height(1.0e-5)
    749         domain.set_store_vertices_uniquely()
    750 
    751         # FIXME: This works better with old limiters so far
    752         domain.tight_slope_limiters = 0
    753 
    754         #--------------------------------------------------------------
    755         # Setup initial conditions
    756         #--------------------------------------------------------------
    757         def topography(x, y):
    758             return -x/2                             # linear bed slope
    759 
    760         # Use function for elevation
    761         domain.set_quantity('elevation', topography)
    762         domain.set_quantity('friction', 0.)                # Zero friction
    763         # Constant negative initial stage
    764         domain.set_quantity('stage', initial_runup_height)
    765 
    766         #--------------------------------------------------------------
    767         # Setup boundary conditions
    768         #--------------------------------------------------------------
    769         Br = Reflective_boundary(domain)                       # Reflective wall
    770         Bd = Dirichlet_boundary([final_runup_height, 0, 0])    # Constant inflow
    771 
    772         # All reflective to begin with (still water)
    773         domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
    774 
    775         #--------------------------------------------------------------
    776         # Test initial inundation height
    777         #--------------------------------------------------------------
    778         indices = domain.get_wet_elements()
    779         z = domain.get_quantity('elevation').\
    780                 get_values(location='centroids', indices=indices)
    781         assert num.alltrue(z < initial_runup_height)
    782 
    783         q_ref = domain.get_maximum_inundation_elevation(minimum_height=minimum_storable_height)
    784         # First order accuracy
    785         assert num.allclose(q_ref, initial_runup_height, rtol=1.0/N)
    786 
    787         #--------------------------------------------------------------
    788         # Let triangles adjust
    789         #--------------------------------------------------------------
    790         q_max = None
    791         for t in domain.evolve(yieldstep = 0.1, finaltime = 1.0):
    792             q = domain.get_maximum_inundation_elevation(minimum_height=minimum_storable_height)
    793 
    794             if verbose:
    795                 domain.write_time()
    796                 print q
    797                
    798             if q > q_max:
    799                 q_max = q
    800 
    801         #--------------------------------------------------------------
    802         # Test inundation height again
    803         #--------------------------------------------------------------
    804         #q_ref = domain.get_maximum_inundation_elevation()
    805         q = get_maximum_inundation_elevation(filename+'.sww')
    806         msg = 'We got %f, should have been %f' % (q, q_max)
    807         assert num.allclose(q, q_max, rtol=2.0/N), msg
    808 
    809         msg = 'We got %f, should have been %f' % (q, initial_runup_height)
    810         assert num.allclose(q, initial_runup_height, rtol = 1.0/N), msg
    811 
    812         # Test error condition if time interval is out
    813         try:
    814             q = get_maximum_inundation_elevation(filename+'.sww',
    815                                                  time_interval=[2.0, 3.0])
    816         except ValueError:
    817             pass
    818         else:
    819             msg = 'should have caught wrong time interval'
    820             raise Exception, msg
    821 
    822         # Check correct time interval
    823         q, loc = get_maximum_inundation_data(filename+'.sww',
    824                                              time_interval=[0.0, 3.0])
    825         msg = 'We got %f, should have been %f' % (q, initial_runup_height)
    826         assert num.allclose(q, initial_runup_height, rtol = 1.0/N), msg
    827         assert num.allclose(-loc[0]/2, q)    # From topography formula
    828 
    829         #--------------------------------------------------------------
    830         # Update boundary to allow inflow
    831         #--------------------------------------------------------------
    832         domain.set_boundary({'right': Bd})
    833 
    834         #--------------------------------------------------------------
    835         # Evolve system through time
    836         #--------------------------------------------------------------
    837        
    838         for t in domain.evolve(yieldstep = 0.1, finaltime = 3.0,
    839                                skip_initial_step = True):
    840             q = domain.get_maximum_inundation_elevation(minimum_height=minimum_storable_height)
    841 
    842             if verbose:
    843                 domain.write_time()
    844                 print q
    845 
    846             if q > q_max:
    847                 q_max = q
    848                
    849 
    850         #--------------------------------------------------------------
    851         # Test inundation height again
    852         #--------------------------------------------------------------
    853         indices = domain.get_wet_elements()
    854         z = domain.get_quantity('elevation').\
    855                 get_values(location='centroids', indices=indices)
    856 
    857 
    858         assert num.alltrue(z < final_runup_height+1.0/N)
    859 
    860         q = domain.get_maximum_inundation_elevation()
    861         # First order accuracy
    862         assert num.allclose(q, final_runup_height, rtol=1.0/N)
    863 
    864         q, loc = get_maximum_inundation_data(filename+'.sww',
    865                                              time_interval=[3.0, 3.0])
    866         msg = 'We got %f, should have been %f' % (q, final_runup_height)
    867         assert num.allclose(q, final_runup_height, rtol=1.0/N), msg
    868         assert num.allclose(-loc[0]/2, q)    # From topography formula
    869 
    870         q = get_maximum_inundation_elevation(filename+'.sww',verbose = verbose)
    871         loc = get_maximum_inundation_location(filename+'.sww')
    872        
    873        
    874         msg = 'We got %f, should have been %f' % (q, q_max)
    875         assert num.allclose(q, q_max, rtol=1.0/N), msg
    876         assert num.allclose(-loc[0]/2, q)    # From topography formula
    877 
    878         q = get_maximum_inundation_elevation(filename+'.sww',
    879                                              time_interval=[0, 3])
    880         msg = 'We got %f, should have been %f' % (q, q_max)
    881         assert num.allclose(q, q_max, rtol=1.0/N), msg
    882 
    883         # Check polygon mode
    884         # Runup region
    885         polygon = [[0.3, 0.0], [0.9, 0.0], [0.9, 1.0], [0.3, 1.0]]
    886         q = get_maximum_inundation_elevation(filename+'.sww',
    887                                              polygon = polygon,
    888                                              time_interval=[0, 3])
    889         msg = 'We got %f, should have been %f' % (q, q_max)
    890         assert num.allclose(q, q_max, rtol=1.0/N), msg
    891 
    892         # Offshore region
    893         polygon = [[0.9, 0.0], [1.0, 0.0], [1.0, 1.0], [0.9, 1.0]]
    894         q, loc = get_maximum_inundation_data(filename+'.sww',
    895                                              polygon = polygon,
    896                                              time_interval=[0, 3])
    897         msg = 'We got %f, should have been %f' % (q, -0.475)
    898         assert num.allclose(q, -0.475, rtol=1.0/N), msg
    899         assert is_inside_polygon(loc, polygon)
    900         assert num.allclose(-loc[0]/2, q)    # From topography formula
    901 
    902         # Dry region
    903         polygon = [[0.0, 0.0], [0.4, 0.0], [0.4, 1.0], [0.0, 1.0]]
    904         q, loc = get_maximum_inundation_data(filename+'.sww',
    905                                              polygon = polygon,
    906                                              time_interval=[0, 3])
    907         msg = 'We got %s, should have been None' % (q)
    908         assert q is None, msg
    909         msg = 'We got %s, should have been None' % (loc)
    910         assert loc is None, msg
    911 
    912         # Check what happens if no time point is within interval
    913         try:
    914             q = get_maximum_inundation_elevation(filename+'.sww',
    915                                                  time_interval=[2.75, 2.75])
    916         except AssertionError:
    917             pass
    918         else:
    919             msg = 'Time interval should have raised an exception'
    920             raise Exception, msg
    921 
    922         # Cleanup
    923         try:
    924862            pass
    925863            #os.remove(domain.get_name() + '.sww')
Note: See TracChangeset for help on using the changeset viewer.