Ignore:
Timestamp:
Feb 16, 2005, 10:18:23 PM (20 years ago)
Author:
ole
Message:

First experiment with new limiter (near bed)

Location:
inundation/ga/storm_surge/pyvolution
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • inundation/ga/storm_surge/pyvolution/flatbed.py

    r773 r901  
    1414from Numeric import array
    1515from util import Polygon_function, read_polygon
    16 from config import data_dir
     16
    1717
    1818#Create basic mesh
     
    2424domain.store = True
    2525domain.set_name('polygons')
    26 print "Output being written to " + data_dir + sep + \
     26print "Output being written to " + domain.get_datadir() + sep + \
    2727              domain.filename + "_size%d." %len(domain) + domain.format
    2828       
  • inundation/ga/storm_surge/pyvolution/netherlands.py

    r773 r901  
    9797N = 60
    9898
    99 N = 140
     99#N = 140
     100
     101N = 15
    100102
    101103print 'Creating domain'
  • inundation/ga/storm_surge/pyvolution/shallow_water.py

    r851 r901  
    595595   
    596596   
    597 def balance_deep_and_shallow(domain):
     597def balance_deep_and_shallow_old(domain):
    598598    """Compute linear combination between stage as computed by
    599599    gradient-limiters and stage computed as constant height above bed.
     
    633633        hmin = min( hv[k,:] )
    634634
    635        
    636635        #Create alpha in [0,1], where alpha==0 means using shallow
    637636        #first order scheme and alpha==1 means using the stage w as
     
    647646            alpha = 1.0
    648647
    649 
    650648        #Weighted balance between stage parallel to bed elevation
    651649        #(wvi = zvi + hc) and stage as computed by 1st or 2nd
     
    664662           
    665663
     664            #Momentums at centroids
     665            xmomc = domain.quantities['xmomentum'].centroid_values
     666            ymomc = domain.quantities['ymomentum'].centroid_values       
     667
     668            #Momentums at vertices
     669            xmomv = domain.quantities['xmomentum'].vertex_values
     670            ymomv = domain.quantities['ymomentum'].vertex_values         
     671
     672            # Update momentum as a linear combination of
     673            # xmomc and ymomc (shallow) and momentum
     674            # from extrapolator xmomv and ymomv (deep).
     675            xmomv[k,:] = (1-alpha)*xmomc[k] + alpha*xmomv[k,:]           
     676            ymomv[k,:] = (1-alpha)*ymomc[k] + alpha*ymomv[k,:]
     677           
     678
     679def limit_on_h(domain):       
     680    """Limit slopes for each volume to eliminate artificial variance
     681    introduced by e.g. second order extrapolator
     682   
     683    limit on h = w-z
     684    """
     685
     686    from Numeric import zeros, Float
     687
     688    N = domain.number_of_elements
     689    beta = domain.beta   
     690   
     691    #Shortcuts
     692    wc = domain.quantities['stage'].centroid_values
     693    zc = domain.quantities['elevation'].centroid_values
     694    hc = wc - zc
     695   
     696    wv = domain.quantities['stage'].vertex_values
     697    zv = domain.quantities['elevation'].vertex_values
     698    hv = wv-zv
     699
     700    hvbar = zeros(hv.shape, Float) #h-limited values
     701   
     702    #Find min and max of this and neighbour's centroid values
     703    hmax = zeros(hc.shape, Float)
     704    hmin = zeros(hc.shape, Float)       
     705   
     706    for k in range(N):
     707        hmax[k] = hmin[k] = hc[k]
     708        for i in range(3):
     709            n = domain.neighbours[k,i]
     710            if n >= 0:
     711                hn = hc[n] #Neighbour's centroid value
     712               
     713                hmin[k] = min(hmin[k], hn)
     714                hmax[k] = max(hmax[k], hn)
     715     
     716   
     717    #Diffences between centroids and maxima/minima
     718    dhmax = hmax - hc
     719    dhmin = hmin - hc
     720       
     721    #Deltas between vertex and centroid values
     722    dh = zeros(hv.shape, Float)
     723    for i in range(3):
     724        dh[:,i] = hv[:,i] - hc
     725
     726    #Phi limiter   
     727    for k in range(N):
     728       
     729        #Find the gradient limiter (phi) across vertices
     730        phi = 1.0
     731        for i in range(3):
     732            r = 1.0
     733            if (dh[k,i] > 0): r = dhmax[k]/dh[k,i]
     734            if (dh[k,i] < 0): r = dhmin[k]/dh[k,i]
     735           
     736            phi = min( min(r*beta, 1), phi )   
     737
     738        #Then update using phi limiter
     739        for i in range(3):           
     740            hvbar[k,i] = hc[k] + phi*dh[k,i]
     741
     742    return hvbar
     743   
     744                                           
     745def balance_deep_and_shallow(domain):
     746    """Compute linear combination between stage as computed by
     747    gradient-limiters limiting using w, and stage computed as
     748    constant height above bed and limited using h.
     749    The former takes precedence when heights are large compared to the
     750    bed slope while the latter takes precedence when heights are
     751    relatively small.  Anything in between is computed as a balanced
     752    linear combination in order to avoid numerical disturbances which
     753    would otherwise appear as a result of hard switching between
     754    modes.
     755    """
     756
     757    #New idea.
     758    #
     759    # In the presence and near of bedslope it is necessary to
     760    # limit slopes based on differences in h rather than w
     761    # (which is what is needed away from the bed).
     762    #
     763    # So whether extrapolation was first order or second order,
     764    # it will need to be balanced with a h-limited gradient.
     765    #
     766    # For this we will use the quantity alpha as before
     767    #
     768       
     769    #Shortcuts
     770    wc = domain.quantities['stage'].centroid_values
     771    zc = domain.quantities['elevation'].centroid_values
     772    hc = wc - zc
     773   
     774    wv = domain.quantities['stage'].vertex_values
     775    zv = domain.quantities['elevation'].vertex_values
     776    hv = wv-zv
     777
     778    for k in range(domain.number_of_elements):
     779        #Compute maximal variation in bed elevation
     780        #  This quantitiy is
     781        #    dz = max_i abs(z_i - z_c)
     782        #  and it is independent of dimension
     783        #  In the 1d case zc = (z0+z1)/2
     784        #  In the 2d case zc = (z0+z1+z2)/3
     785
     786        dz = max(abs(zv[k,0]-zc[k]),
     787                 abs(zv[k,1]-zc[k]),
     788                 abs(zv[k,2]-zc[k]))
     789
     790       
     791        hmin = min( hv[k,:] )
     792
     793        #Create alpha in [0,1], where alpha==0 means using shallow
     794        #first order scheme and alpha==1 means using the stage w as
     795        #computed by the gradient limiter (1st or 2nd order)
     796        #
     797        #If hmin > dz/2 then alpha = 1 and the bed will have no effect
     798        #If hmin < 0 then alpha = 0 reverting to constant height above bed.
     799     
     800        if dz > 0.0:
     801            alpha = max( min( 2*hmin/dz, 1.0), 0.0 )
     802        else:
     803            #Flat bed
     804            alpha = 1.0
     805
     806        #Let
     807        #
     808        #  wvi- be the h-limited state (wvi- = zvi + hvi-)
     809        #  wvi~ be the w-limited stage (wvi~ = zvi + hvi~)
     810        # 
     811        #   
     812        #where i=0,1,2 denotes the vertex ids
     813        #
     814        #Weighted balance between w-limited and h-limited stage is 
     815        #
     816        #  wvi := (1-alpha)*(zvi+hvi-) + alpha*(zvi+hvi~)   
     817        #
     818        #It follows that the updated wvi is
     819        #  wvi := zvi + (1-alpha)*hvi- + alpha*hvi~
     820        #
     821        # Momentum is balanced between constant and limited ???
     822
     823        #print 'Alpha = ', alpha
     824        #FIXME: if alpha == 0 compute only h-limited slope,
     825        #if alpha == 1 compute only w-limited slope
     826        #
     827        if alpha < 1:         
     828       
     829            #Limit h
     830            hvbar = limit_on_h(domain)
     831   
     832            for i in range(3):
     833                wv[k,i] = zv[k,i] + (1-alpha)*hvbar[k,i] + alpha*hv[k,i]
     834           
    666835            #Momentums at centroids
    667836            xmomc = domain.quantities['xmomentum'].centroid_values
     
    12891458    manning_friction = manning_friction_c
    12901459    balance_deep_and_shallow = balance_deep_and_shallow_c
     1460    #balance_deep_and_shallow = balance_deep_and_shallow_old
    12911461    protect_against_infinitesimal_and_negative_heights = protect_against_infinitesimal_and_negative_heights_c
    12921462
  • inundation/ga/storm_surge/pyvolution/test_shallow_water.py

    r896 r901  
    125125        assert allclose(flux, [0., 0.5*g*h**2, 0.])
    126126        assert max_speed == sqrt(g*h)
     127       
     128    #def test_flux_slope(self):
     129    #    #FIXME: TODO
     130    #    w = 2.0
     131    #   
     132    #    normal = array([1.,0])       
     133    #    ql = array([w, 0, 0])
     134    #    qr = array([w, 0, 0])
     135    #    zl = zr = 0.
     136    #    h = w - (zl+zr)/2
     137    #   
     138    #    flux, max_speed = flux_function(normal, ql, qr, zl, zr)
     139    #
     140    #    assert allclose(flux, [0., 0.5*g*h**2, 0.])
     141    #    assert max_speed == sqrt(g*h)
    127142       
    128143
  • inundation/ga/storm_surge/pyvolution/util.py

    r900 r901  
    263263            for i, t in enumerate(self.T):
    264264                #Interpolate quantities at this timestep
    265                 print ' time step %d of %d' %(i, len(self.T))
     265                #print ' time step %d of %d' %(i, len(self.T))
    266266                for name in self.quantities:
    267267                    self.values[name][i, :] =\
Note: See TracChangeset for help on using the changeset viewer.