Ignore:
Timestamp:
Sep 12, 2007, 4:13:11 PM (17 years ago)
Author:
ole
Message:

Further optimisation when beta_h == 0 (gained about 5s bring the
total time of 30s down to 25s in the okushiri performance test).

Also cleared out some obsolete code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • anuga_core/source/anuga/shallow_water/shallow_water_domain.py

    r4713 r4733  
    206206        self.smooth = not flag
    207207
    208         #Reduction operation for get_vertex_values
     208        # Reduction operation for get_vertex_values
    209209        if reduction is None:
    210210            self.reduction = mean
     
    506506
    507507
    508 #Rotation of momentum vector
     508# Rotation of momentum vector
    509509def rotate(q, normal, direction = 1):
    510510    """Rotate the momentum component q (q[1], q[2])
     
    12211221    """
    12221222
    1223     #Shortcuts
     1223    # FIXME (Ole): I reckon this can be simplified significantly:
     1224    #
     1225    # Always use beta_h == 0, and phase it out.
     1226    # Compute hc and hv in the c-code
     1227    # Omit updating xmomv
     1228    #
     1229    from shallow_water_ext import balance_deep_and_shallow
     1230   
     1231    # Shortcuts
    12241232    wc = domain.quantities['stage'].centroid_values
    12251233    zc = domain.quantities['elevation'].centroid_values
    1226     hc = wc - zc
     1234    #hc = wc - zc
    12271235
    12281236    wv = domain.quantities['stage'].vertex_values
    12291237    zv = domain.quantities['elevation'].vertex_values
    1230     hv = wv - zv
    1231 
    1232     #Momentums at centroids
     1238    #hv = wv - zv
     1239
     1240    # Momentums at centroids
    12331241    xmomc = domain.quantities['xmomentum'].centroid_values
    12341242    ymomc = domain.quantities['ymomentum'].centroid_values
    12351243
    1236     #Momentums at vertices
     1244    # Momentums at vertices
    12371245    xmomv = domain.quantities['xmomentum'].vertex_values
    12381246    ymomv = domain.quantities['ymomentum'].vertex_values
     
    12411249    if domain.beta_h > 0:
    12421250        hvbar = h_limiter(domain)
     1251       
     1252        balance_deep_and_shallow(domain, domain.beta_h,
     1253                                 wc, zc, wv, zv, hvbar,
     1254                                 xmomc, ymomc, xmomv, ymomv)       
    12431255    else:
    12441256        # print 'Using first order h-limiter'
    1245      
     1257        # FIXME: Pass wc in for now - it will be ignored.
    12461258       
    12471259        #This is how one would make a first order h_limited value
    12481260        #as in the old balancer (pre 17 Feb 2005):
    12491261        # If we wish to hard wire this, one should modify the C-code
    1250         from Numeric import zeros, Float
    1251         hvbar = zeros( (len(hc), 3), Float)
    1252         for i in range(3):
    1253             hvbar[:,i] = hc[:]
    1254 
    1255     from shallow_water_ext import balance_deep_and_shallow
    1256     balance_deep_and_shallow(domain, wc, zc, hc, wv, zv, hv, hvbar,
    1257                              xmomc, ymomc, xmomv, ymomv)
     1262        #from Numeric import zeros, Float
     1263        #hvbar = zeros( (len(wc), 3), Float)
     1264        #for i in range(3):
     1265        #    hvbar[:,i] = wc[:] - zc[:]
     1266
     1267        balance_deep_and_shallow(domain, domain.beta_h,
     1268                                 wc, zc, wv, zv, wc,
     1269                                 xmomc, ymomc, xmomv, ymomv)
     1270
    12581271
    12591272
     
    20052018
    20062019
    2007 ##############################
    2008 #OBSOLETE STUFF
    2009 
    2010 def balance_deep_and_shallow_old(domain):
    2011     """Compute linear combination between stage as computed by
    2012     gradient-limiters and stage computed as constant height above bed.
    2013     The former takes precedence when heights are large compared to the
    2014     bed slope while the latter takes precedence when heights are
    2015     relatively small.  Anything in between is computed as a balanced
    2016     linear combination in order to avoid numerical disturbances which
    2017     would otherwise appear as a result of hard switching between
    2018     modes.
    2019     """
    2020 
    2021     #OBSOLETE
    2022 
    2023     #Shortcuts
    2024     wc = domain.quantities['stage'].centroid_values
    2025     zc = domain.quantities['elevation'].centroid_values
    2026     hc = wc - zc
    2027 
    2028     wv = domain.quantities['stage'].vertex_values
    2029     zv = domain.quantities['elevation'].vertex_values
    2030     hv = wv-zv
    2031 
    2032 
    2033     #Computed linear combination between constant stages and and
    2034     #stages parallel to the bed elevation.
    2035     for k in range(len(domain)):
    2036         #Compute maximal variation in bed elevation
    2037         #  This quantitiy is
    2038         #    dz = max_i abs(z_i - z_c)
    2039         #  and it is independent of dimension
    2040         #  In the 1d case zc = (z0+z1)/2
    2041         #  In the 2d case zc = (z0+z1+z2)/3
    2042 
    2043         dz = max(abs(zv[k,0]-zc[k]),
    2044                  abs(zv[k,1]-zc[k]),
    2045                  abs(zv[k,2]-zc[k]))
    2046 
    2047 
    2048         hmin = min( hv[k,:] )
    2049 
    2050         #Create alpha in [0,1], where alpha==0 means using shallow
    2051         #first order scheme and alpha==1 means using the stage w as
    2052         #computed by the gradient limiter (1st or 2nd order)
    2053         #
    2054         #If hmin > dz/2 then alpha = 1 and the bed will have no effect
    2055         #If hmin < 0 then alpha = 0 reverting to constant height above bed.
    2056 
    2057         if dz > 0.0:
    2058             alpha = max( min( 2*hmin/dz, 1.0), 0.0 )
    2059         else:
    2060             #Flat bed
    2061             alpha = 1.0
    2062 
    2063         #Weighted balance between stage parallel to bed elevation
    2064         #(wvi = zvi + hc) and stage as computed by 1st or 2nd
    2065         #order gradient limiter
    2066         #(wvi = zvi + hvi) where i=0,1,2 denotes the vertex ids
    2067         #
    2068         #It follows that the updated wvi is
    2069         #  wvi := (1-alpha)*(zvi+hc) + alpha*(zvi+hvi) =
    2070         #  zvi + hc + alpha*(hvi - hc)
    2071         #
    2072         #Note that hvi = zc+hc-zvi in the first order case (constant).
    2073 
    2074         if alpha < 1:
    2075             for i in range(3):
    2076                 wv[k,i] = zv[k,i] + hc[k] + alpha*(hv[k,i]-hc[k])
    2077 
    2078 
    2079             #Momentums at centroids
    2080             xmomc = domain.quantities['xmomentum'].centroid_values
    2081             ymomc = domain.quantities['ymomentum'].centroid_values
    2082 
    2083             #Momentums at vertices
    2084             xmomv = domain.quantities['xmomentum'].vertex_values
    2085             ymomv = domain.quantities['ymomentum'].vertex_values
    2086 
    2087             # Update momentum as a linear combination of
    2088             # xmomc and ymomc (shallow) and momentum
    2089             # from extrapolator xmomv and ymomv (deep).
    2090             xmomv[k,:] = (1-alpha)*xmomc[k] + alpha*xmomv[k,:]
    2091             ymomv[k,:] = (1-alpha)*ymomc[k] + alpha*ymomv[k,:]
    2092 
    2093 
    2094 
    2095 
    2096 
    2097 ###########################
    2098 ###########################
    2099 #Geometries
    2100 
    2101 
    2102 #FIXME: Rethink this way of creating values.
    2103 
    2104 
    2105 class Weir:
    2106     """Set a bathymetry for weir with a hole and a downstream gutter
    2107     x,y are assumed to be in the unit square
    2108     """
    2109 
    2110     def __init__(self, stage):
    2111         self.inflow_stage = stage
    2112 
    2113     def __call__(self, x, y):
    2114         from Numeric import zeros, Float
    2115         from math import sqrt
    2116 
    2117         N = len(x)
    2118         assert N == len(y)
    2119 
    2120         z = zeros(N, Float)
    2121         for i in range(N):
    2122             z[i] = -x[i]/2  #General slope
    2123 
    2124             #Flattish bit to the left
    2125             if x[i] < 0.3:
    2126                 z[i] = -x[i]/10
    2127 
    2128             #Weir
    2129             if x[i] >= 0.3 and x[i] < 0.4:
    2130                 z[i] = -x[i]+0.9
    2131 
    2132             #Dip
    2133             x0 = 0.6
    2134             #depth = -1.3
    2135             depth = -1.0
    2136             #plateaux = -0.9
    2137             plateaux = -0.6
    2138             if y[i] < 0.7:
    2139                 if x[i] > x0 and x[i] < 0.9:
    2140                     z[i] = depth
    2141 
    2142                 #RHS plateaux
    2143                 if x[i] >= 0.9:
    2144                     z[i] = plateaux
    2145 
    2146 
    2147             elif y[i] >= 0.7 and y[i] < 1.5:
    2148                 #Restrict and deepen
    2149                 if x[i] >= x0 and x[i] < 0.8:
    2150                     z[i] = depth-(y[i]/3-0.3)
    2151                     #z[i] = depth-y[i]/5
    2152                     #z[i] = depth
    2153                 elif x[i] >= 0.8:
    2154                     #RHS plateaux
    2155                     z[i] = plateaux
    2156 
    2157             elif y[i] >= 1.5:
    2158                 if x[i] >= x0 and x[i] < 0.8 + (y[i]-1.5)/1.2:
    2159                     #Widen up and stay at constant depth
    2160                     z[i] = depth-1.5/5
    2161                 elif x[i] >= 0.8 + (y[i]-1.5)/1.2:
    2162                     #RHS plateaux
    2163                     z[i] = plateaux
    2164 
    2165 
    2166             #Hole in weir (slightly higher than inflow condition)
    2167             if x[i] >= 0.3 and x[i] < 0.4 and y[i] > 0.2 and y[i] < 0.4:
    2168                 z[i] = -x[i]+self.inflow_stage + 0.02
    2169 
    2170             #Channel behind weir
    2171             x0 = 0.5
    2172             if x[i] >= 0.4 and x[i] < x0 and y[i] > 0.2 and y[i] < 0.4:
    2173                 z[i] = -x[i]+self.inflow_stage + 0.02
    2174 
    2175             if x[i] >= x0 and x[i] < 0.6 and y[i] > 0.2 and y[i] < 0.4:
    2176                 #Flatten it out towards the end
    2177                 z[i] = -x0+self.inflow_stage + 0.02 + (x0-x[i])/5
    2178 
    2179             #Hole to the east
    2180             x0 = 1.1; y0 = 0.35
    2181             #if x[i] < -0.2 and y < 0.5:
    2182             if sqrt((2*(x[i]-x0))**2 + (2*(y[i]-y0))**2) < 0.2:
    2183                 z[i] = sqrt(((x[i]-x0))**2 + ((y[i]-y0))**2)-1.0
    2184 
    2185             #Tiny channel draining hole
    2186             if x[i] >= 1.14 and x[i] < 1.2 and y[i] >= 0.4 and y[i] < 0.6:
    2187                 z[i] = -0.9 #North south
    2188 
    2189             if x[i] >= 0.9 and x[i] < 1.18 and y[i] >= 0.58 and y[i] < 0.65:
    2190                 z[i] = -1.0 + (x[i]-0.9)/3 #East west
    2191 
    2192 
    2193 
    2194             #Stuff not in use
    2195 
    2196             #Upward slope at inlet to the north west
    2197             #if x[i] < 0.0: # and y[i] > 0.5:
    2198             #    #z[i] = -y[i]+0.5  #-x[i]/2
    2199             #    z[i] = x[i]/4 - y[i]**2 + 0.5
    2200 
    2201             #Hole to the west
    2202             #x0 = -0.4; y0 = 0.35 # center
    2203             #if sqrt((2*(x[i]-x0))**2 + (2*(y[i]-y0))**2) < 0.2:
    2204             #    z[i] = sqrt(((x[i]-x0))**2 + ((y[i]-y0))**2)-0.2
    2205 
    2206 
    2207 
    2208 
    2209 
    2210         return z/2
    2211 
    2212 class Weir_simple:
    2213     """Set a bathymetry for weir with a hole and a downstream gutter
    2214     x,y are assumed to be in the unit square
    2215     """
    2216 
    2217     def __init__(self, stage):
    2218         self.inflow_stage = stage
    2219 
    2220     def __call__(self, x, y):
    2221         from Numeric import zeros, Float
    2222 
    2223         N = len(x)
    2224         assert N == len(y)
    2225 
    2226         z = zeros(N, Float)
    2227         for i in range(N):
    2228             z[i] = -x[i]  #General slope
    2229 
    2230             #Flat bit to the left
    2231             if x[i] < 0.3:
    2232                 z[i] = -x[i]/10  #General slope
    2233 
    2234             #Weir
    2235             if x[i] > 0.3 and x[i] < 0.4:
    2236                 z[i] = -x[i]+0.9
    2237 
    2238             #Dip
    2239             if x[i] > 0.6 and x[i] < 0.9:
    2240                 z[i] = -x[i]-0.5  #-y[i]/5
    2241 
    2242             #Hole in weir (slightly higher than inflow condition)
    2243             if x[i] > 0.3 and x[i] < 0.4 and y[i] > 0.2 and y[i] < 0.4:
    2244                 z[i] = -x[i]+self.inflow_stage + 0.05
    2245 
    2246 
    2247         return z/2
    2248 
    2249 
    2250 
    2251 class Constant_stage:
    2252     """Set an initial condition with constant stage
    2253     """
    2254     def __init__(self, s):
    2255         self.s = s
    2256 
    2257     def __call__(self, x, y):
    2258         return self.s
    2259 
    2260 class Constant_height:
    2261     """Set an initial condition with constant water height, e.g
    2262     stage s = z+h
    2263     """
    2264 
    2265     def __init__(self, W, h):
    2266         self.W = W
    2267         self.h = h
    2268 
    2269     def __call__(self, x, y):
    2270         if self.W is None:
    2271             from Numeric import ones, Float
    2272             return self.h*ones(len(x), Float)
    2273         else:
    2274             return self.W(x,y) + self.h
    2275 
    2276 
    2277 
    2278 
    2279 def compute_fluxes_python(domain):
    2280     """Compute all fluxes and the timestep suitable for all volumes
    2281     in domain.
    2282 
    2283     Compute total flux for each conserved quantity using "flux_function"
    2284 
    2285     Fluxes across each edge are scaled by edgelengths and summed up
    2286     Resulting flux is then scaled by area and stored in
    2287     explicit_update for each of the three conserved quantities
    2288     stage, xmomentum and ymomentum
    2289 
    2290     The maximal allowable speed computed by the flux_function for each volume
    2291     is converted to a timestep that must not be exceeded. The minimum of
    2292     those is computed as the next overall timestep.
    2293 
    2294     Post conditions:
    2295       domain.explicit_update is reset to computed flux values
    2296       domain.timestep is set to the largest step satisfying all volumes.
    2297     """
    2298 
    2299     import sys
    2300     from Numeric import zeros, Float
    2301 
    2302     N = len(domain) # number_of_triangles
    2303 
    2304     #Shortcuts
    2305     Stage = domain.quantities['stage']
    2306     Xmom = domain.quantities['xmomentum']
    2307     Ymom = domain.quantities['ymomentum']
    2308     Bed = domain.quantities['elevation']
    2309 
    2310     #Arrays
    2311     stage = Stage.edge_values
    2312     xmom =  Xmom.edge_values
    2313     ymom =  Ymom.edge_values
    2314     bed =   Bed.edge_values
    2315 
    2316     stage_bdry = Stage.boundary_values
    2317     xmom_bdry =  Xmom.boundary_values
    2318     ymom_bdry =  Ymom.boundary_values
    2319 
    2320     flux = zeros((N,3), Float) #Work array for summing up fluxes
    2321 
    2322     #Loop
    2323     timestep = float(sys.maxint)
    2324     for k in range(N):
    2325 
    2326         for i in range(3):
    2327             #Quantities inside volume facing neighbour i
    2328             ql = [stage[k, i], xmom[k, i], ymom[k, i]]
    2329             zl = bed[k, i]
    2330 
    2331             #Quantities at neighbour on nearest face
    2332             n = domain.neighbours[k,i]
    2333             if n < 0:
    2334                 m = -n-1 #Convert negative flag to index
    2335                 qr = [stage_bdry[m], xmom_bdry[m], ymom_bdry[m]]
    2336                 zr = zl #Extend bed elevation to boundary
    2337             else:
    2338                 m = domain.neighbour_edges[k,i]
    2339                 qr = [stage[n, m], xmom[n, m], ymom[n, m]]
    2340                 zr = bed[n, m]
    2341 
    2342 
    2343             #Outward pointing normal vector
    2344             normal = domain.normals[k, 2*i:2*i+2]
    2345 
    2346             #Flux computation using provided function
    2347             edgeflux, max_speed = flux_function(normal, ql, qr, zl, zr)
    2348 
    2349             flux[k,:] = edgeflux
    2350 
    2351     return flux
    2352 
    2353 
    2354 
    2355 
    2356 
    2357 
    2358 
    2359 ##############################################
    2360 #Initialise module
    2361 
     2020#------------------
     2021# Initialise module
     2022#------------------
    23622023
    23632024from anuga.utilities import compile
    23642025if compile.can_use_C_extension('shallow_water_ext.c'):
    2365     #Replace python version with c implementations
     2026    # Replace python version with c implementations
    23662027
    23672028    from shallow_water_ext import rotate, assign_windfield_values
     
    23802041
    23812042
    2382 #Optimisation with psyco
     2043# Optimisation with psyco
    23832044from anuga.config import use_psyco
    23842045if use_psyco:
     
    24012062    pass
    24022063
    2403 # Profiling stuff
    2404 #import profile
    2405 #profiler = profile.Profile()
     2064
Note: See TracChangeset for help on using the changeset viewer.