Changeset 3510


Ignore:
Timestamp:
Aug 21, 2006, 10:03:42 AM (18 years ago)
Author:
jakeman
Message:

Files now contain inmplementation of method in which advection terms and
pressure terms are split. problems are present.

Location:
development/pyvolution-1d
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • development/pyvolution-1d/domain.py

    r3425 r3510  
    2222
    2323        self.beta = 1.0
     24        #self.limiter = "minmod_kurganov"
     25        #self.limiter_type = "steven"
     26        self.fluxfunc = "unsplit"
     27       
    2428        #Store Points
    2529        self.coordinates = array(coordinates)
  • development/pyvolution-1d/quantity.py

    r3425 r3510  
    5151        #self.edge_values = zeros((N, 2), Float)
    5252        #edge values are values of the ends of each interval
    53        
    54         #does oe dimension need edge values???
    55 
     53     
    5654        #Intialise centroid values
    5755        self.interpolate()
     
    414412        self.centroid_values += timestep*self.explicit_update
    415413
     414        #SECOND ORDER RUNGE_KUTTA
     415        #Re-evaluate source term with updated centroid values
     416        #and update conserved quantities accordingly
     417        """
     418        self.explicit_update = zeros(N, Float)
     419        self.domain.compute_forcing_terms()
     420        self.centroid_values += 0.5*timestep*(explicit_update
     421        """
     422       
    416423##         #Semi implicit updates
    417424##         denominator = ones(N, Float)-timestep*self.semi_implicit_update
     
    679686    """
    680687
    681     def limit(self):
    682         """Limit slopes for each volume to eliminate artificial variance
     688    """def limit(self):
     689        Limit slopes for each volume to eliminate artificial variance
    683690        introduced by e.g. second order extrapolator
    684691
     
    690697        postcondition:
    691698        vertex values are updated
    692         """
    693 
     699       
    694700        from Numeric import zeros, Float
    695701
    696702        N = self.domain.number_of_elements
    697         #beta = self.beta
    698         beta = 0.8
     703        beta = self.beta
     704        #beta = 0.8
    699705
    700706        qc = self.centroid_values
     
    741747                qv[k,i] = qc[k] + phi*dq[k,i]
    742748
    743        
    744 
     749    """
     750   
     751   
     752    def limit(self):
     753        """Limit slopes for each volume to eliminate artificial variance
     754         introduced by e.g. second order extrapolator
     755         
     756        This is an unsophisticated limiter as it does not take into
     757        account dependencies among quantities.
     758
     759        precondition:
     760        vertex values are estimated from gradient
     761        postcondition:
     762        vertex values are updated
     763
     764        """
     765        import sys
     766        from Numeric import zeros, Float
     767        from util import minmod, minmod_kurganov, maxmod, vanleer
     768
     769        N = self.domain.number_of_elements
     770        limiter = self.domain.limiter
     771        limiter_type = self.domain.limiter_type
     772           
     773        qc = self.centroid_values
     774        qv = self.vertex_values
     775
     776        #Find min and max of this and neighbour's centroid values
     777        beta_p = zeros(N,Float)
     778        beta_m = zeros(N,Float)
     779        beta_x = zeros(N,Float)
     780        C = self.domain.centroids
     781        X = self.domain.vertices
     782
     783        for k in range(N):
     784       
     785            n0 = self.domain.neighbours[k,0]
     786            n1 = self.domain.neighbours[k,1]
     787            if limiter_type == "slope":
     788                if ( n0 >= 0) & (n1 >= 0):
     789                    #SLOPE DERIVATIVE LIMIT
     790                    beta_p[k] = (qc[k]-qc[k-1])/(C[k]-C[k-1])
     791                    beta_m[k] = (qc[k+1]-qc[k])/(C[k+1]-C[k])
     792                    beta_x[k] = (qc[k+1]-qc[k-1])/(C[k+1]-C[k-1])
     793            elif limiter_type == "flux":
     794                if (n0 >= 0) & (n1 >= 0):
     795                    # Check denominator not zero
     796                    if (qc[k+1]-qc[k]) == 0.0:
     797                        beta_p[k] = float(sys.maxint)
     798                        beta_m[k] = float(sys.maxint)
     799                    else:
     800                        #STEVE LIMIT
     801                        beta_p[k] = (qc[k]-qc[k-1])/(qc[k+1]-qc[k])
     802                        beta_m[k] = (qc[k+2]-qc[k+1])/(qc[k+1]-qc[k])
     803
     804        #Deltas between vertex and centroid values
     805        dq = zeros(qv.shape, Float)
     806        for i in range(2):
     807            dq[:,i] =self.domain.vertices[:,i]-self.domain.centroids
     808           
     809        #Phi limiter
     810        for k in range(N):
     811            if limiter_type == "slope":
     812                if limiter == "minmod":
     813                    phi = minmod(beta_p[k],beta_m[k])
     814
     815                elif limiter == "minmod_kurganov":
     816                    # Also known as monotonized central difference limiter
     817                    # if theta = 2.0
     818                    theta = 2.0
     819                    phi = minmod_kurganov(theta*beta_p[k],theta*beta_m[k],beta_x[k])
     820                elif limiter == "superbee":
     821                    slope1 = minmod(beta_m[k],2.0*beta_p[k])
     822                    slope2 = minmod(2.0*beta_m[k],beta_p[k])
     823                    phi = maxmod(slope1,slope2)
     824                    #phi = max(0.0,min(1.0,2.0*beta_m[k]),min(2.0,beta_m[k]))+max(0.0,min(1.0,2.0*beta_p[k]),min(2.0,beta_p[k]))-1.0
     825
     826                elif limiter == "vanleer":
     827                    phi = vanleer(beta_p[k],beta_m[k])
     828
     829
     830                elif limiter == "muscl":
     831
     832                    #MINMOD
     833                    #phi = minmod(1.0,beta_m[k])
     834                    #SUPERBEE
     835                    #phi = max(0.0,min(2.0*beta_m[k],1.0),min(beta_m[k],2.0))
     836                    #VAN LEER
     837                    phi = (beta_m[k]+abs(beta_m[k]))/(1.0+abs(beta_m[k]))
     838                   
     839                for i in range(2):
     840                    qv[k,i] = qc[k] + phi*dq[k,i]
     841               
     842            elif limiter_type == "flux":
     843                phi = 0.0
     844                if limiter == "flux_minmod":
     845                    #FLUX MINMOD
     846                    phi = minmod_kurganov(1.0,beta_m[k],beta_p[k])
     847                elif limiter == "flux_superbee":
     848                    #FLUX SUPERBEE
     849                    phi = max(0.0,min(1.0,2.0*beta_m[k]),min(2.0,beta_m[k]))+max(0.0,min(1.0,2.0*beta_p[k]),min(2.0,beta_p[k]))-1.0
     850                elif limiter == "flux_muscl":
     851                    #FLUX MUSCL
     852                    phi = max(0.0,min(2.0,2.0*beta_m[k],2.0*beta_p[k],0.5*(beta_m[k]+beta_p[k])))
     853                elif limiter == "flux_vanleer":
     854                    #FLUX VAN LEER
     855                    phi = (beta_m[k]+abs(beta_m[k]))/(1.0+abs(beta_m[k]))+(beta_p[k]+abs(beta_p[k]))/(1.0+abs(beta_p[k]))-1.0
     856
     857                #Then update using phi limiter
     858                n = self.domain.neighbours[k,1]
     859                if n>=0:
     860                    #qv[k,0] = qc[k] - 0.5*phi*(qc[k+1]-qc[k])
     861                    #qv[k,1] = qc[k] + 0.5*phi*(qc[k+1]-qc[k])
     862                    qv[k,0] = qc[k] + 0.5*phi*(qv[k,0]-qc[k])
     863                    qv[k,1] = qc[k] + 0.5*phi*(qv[k,1]-qc[k])
     864                else:
     865                    qv[k,i] = qc[k]
     866                   
     867           
    745868def newLinePlot(title='Simple Plot'):
    746869    import Gnuplot
  • development/pyvolution-1d/shallow_water_1d.py

    r3425 r3510  
    6464        #forcing terms not included in 1d domain ?WHy?
    6565        self.forcing_terms.append(gravity)
    66         self.forcing_terms.append(manning_friction)
     66        #self.forcing_terms.append(manning_friction)
    6767        #print "\nI have Removed forcing terms line 64 1dsw"
    6868
     
    283283
    284284
    285 # Flux computation
    286 #def flux_function(normal, ql, qr, zl, zr):
    287 def flux_function(normal, ql, qr, zl, zr):
     285def flux_function_unsplit(normal, ql, qr, zl, zr):
    288286    """Compute fluxes between volumes for the shallow water wave equation
    289287    cast in terms of w = h+z using the 'central scheme' as described in
     
    376374
    377375    return edgeflux, max_speed
     376
     377def flux_function_split(normal, ql, qr, zl, zr):
     378    from config import g, epsilon
     379    from math import sqrt
     380    from Numeric import array
     381
     382    #print 'ql',ql
     383
     384    #Align momentums with x-axis
     385    #q_left  = rotate(ql, normal, direction = 1)
     386    #q_right = rotate(qr, normal, direction = 1)
     387    q_left = ql
     388    q_left[1] = q_left[1]*normal
     389    q_right = qr
     390    q_right[1] = q_right[1]*normal
     391
     392    #z = (zl+zr)/2 #Take average of field values
     393    z = 0.5*(zl+zr) #Take average of field values
     394
     395    w_left  = q_left[0]   #w=h+z
     396    h_left  = w_left-z
     397    uh_left = q_left[1]
     398
     399    if h_left < epsilon:
     400        u_left = 0.0  #Could have been negative
     401        h_left = 0.0
     402    else:
     403        u_left  = uh_left/h_left
     404
     405
     406    w_right  = q_right[0]  #w=h+z
     407    h_right  = w_right-z
     408    uh_right = q_right[1]
     409
     410
     411    if h_right < epsilon:
     412        u_right = 0.0  #Could have been negative
     413        h_right = 0.0
     414    else:
     415        u_right  = uh_right/h_right
     416
     417    #vh_left  = q_left[2]
     418    #vh_right = q_right[2]
     419
     420    #soundspeed_left  = sqrt(g*h_left)
     421    #soundspeed_right = sqrt(g*h_right)
     422
     423    #Maximal wave speed
     424    #s_max = max(u_left+soundspeed_left, u_right+soundspeed_right, 0)
     425    s_max = max(u_left, u_right, 0)
     426   
     427    #Minimal wave speed
     428    #s_min = min(u_left-soundspeed_left, u_right-soundspeed_right, 0)
     429    s_min = min(u_left, u_right, 0)
     430   
     431    #Flux computation
     432
     433    #flux_left  = array([u_left*h_left,
     434    #                    u_left*uh_left + 0.5*g*h_left*h_left])
     435    #flux_right = array([u_right*h_right,
     436    #                    u_right*uh_right + 0.5*g*h_right*h_right])
     437    flux_left  = array([u_left*h_left,
     438                        u_left*uh_left])# + 0.5*g*h_left*h_left])
     439    flux_right = array([u_right*h_right,
     440                        u_right*uh_right])# + 0.5*g*h_right*h_right])
     441   
     442    denom = s_max-s_min
     443    if denom == 0.0:
     444        edgeflux = array([0.0, 0.0])
     445        max_speed = 0.0
     446    else:
     447        edgeflux = (s_max*flux_left - s_min*flux_right)/denom
     448        edgeflux += s_max*s_min*(q_right-q_left)/denom
     449       
     450        edgeflux[1] = edgeflux[1]*normal
     451
     452        max_speed = max(abs(s_max), abs(s_min))
     453
     454    return edgeflux, max_speed   
     455
    378456
    379457def compute_fluxes(domain):
     
    471549            #print 'qr',qr
    472550           
    473             edgeflux, max_speed = flux_function(normal, ql, qr, zl, zr)
     551
     552            if domain.fluxfunc == "unsplit":
     553                edgeflux, max_speed = flux_function_unsplit(normal, ql, qr, zl, zr)
     554            elif domain.fluxfunc == "split":
     555                edgeflux, max_speed = flux_function_split(normal, ql, qr, zl, zr)
    474556            #print 'edgeflux', edgeflux
    475557
     
    480562            try:
    481563                #timestep = min(timestep, 0.5*domain.radii[k]/max_speed)
    482                 #timestep = 0.01
    483            
    484564                timestep = min(timestep, domain.cfl*0.5*domain.areas[k]/max_speed)
    485                 if (timestep < 1e-6) & (enter == True):
    486                     #print "domain.order", domain.order
    487                     #domain.write_time()
    488                     print "cell number", k
    489                     print "timestep", timestep
    490                     print 'max_speed', max_speed
    491                     s = domain.quantities['stage']
    492                     s = s.centroid_values
    493                     xm = domain.quantities['xmomentum']
    494                     xm = xm.centroid_values
    495                     print 'h', s[k]
    496                     print 'xm', xm[k]
    497                     print 'u', xm[k]/s[k]
    498                     enter = False
    499            
    500565            except ZeroDivisionError:
    501566                pass
     
    504569        #quantities get updated
    505570        flux /= domain.areas[k]
    506         # ADD ABOVE LINE AGAIN
     571
    507572        Stage.explicit_update[k] = flux[0]
    508573        Xmom.explicit_update[k] = flux[1]
     
    608673
    609674    #Remove very thin layers of water
    610     ##protect_against_infinitesimal_and_negative_heights(domain)
     675    protect_against_infinitesimal_and_negative_heights(domain)
    611676
    612677    #Extrapolate all conserved quantities
     
    10011066    #h = Stage.edge_values - Elevation.edge_values
    10021067    h = Stage.vertex_values - Elevation.vertex_values
    1003     v = Elevation.vertex_values
     1068    b = Elevation.vertex_values
     1069    w = Stage.vertex_values
    10041070
    10051071    x = domain.get_vertex_coordinates()
     
    10141080        x0, x1 = x[k,:]
    10151081        #z0, z1, z2 = v[k,:]
    1016         z0, z1 = v[k,:]
     1082        b0, b1 = b[k,:]
     1083
     1084        w0, w1 = w[k,:]
     1085        wx = gradient(x0, x1, w0, w1)
    10171086
    10181087        #zx, zy = gradient(x0, y0, x1, y1, x2, y2, z0, z1, z2)
    1019         zx = gradient(x0, x1, z0, z1)
     1088        bx = gradient(x0, x1, b0, b1)
    10201089       
    10211090        #Update momentum
    1022         xmom[k] += -g*zx*avg_h
     1091        if domain.fluxfunc == "unsplit":
     1092            xmom[k] += -g*bx*avg_h
     1093        elif domain.fluxfunc == "split":
     1094            xmom[k] += -g*wx*avg_h
    10231095#        ymom[k] += -g*zy*avg_h
    10241096
Note: See TracChangeset for help on using the changeset viewer.