Changeset 198 for inundation/ga
- Timestamp:
- Aug 20, 2004, 3:28:34 PM (20 years ago)
- Location:
- inundation/ga/storm_surge/pyvolution
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
inundation/ga/storm_surge/pyvolution/config.py
r195 r198 57 57 58 58 use_extensions = True #Try to use C-extensions 59 #use_extensions = False #Do not use C-extensions59 use_extensions = False #Do not use C-extensions 60 60 61 61 use_psyco = True #Use psyco optimisations -
inundation/ga/storm_surge/pyvolution/mesh.py
r195 r198 201 201 def build_neighbour_structure(self): 202 202 """Update all registered triangles to point to their neighbours. 203 204 Also, keep a tally of the number of boundaries for each triangle 203 205 204 206 Postconditions: … … 297 299 if they exist. Otherwise point to the triangle itself. 298 300 299 Also, keep a tally of the number of boundaries for each triangle300 301 301 The surrogate neighbour structure is useful for computing gradients 302 302 based on centroid values of neighbours. -
inundation/ga/storm_surge/pyvolution/quantity.py
r195 r198 106 106 self.centroid_values /= denominator 107 107 108 def compute_gradients(self): 109 """Compute gradients of triangle surfaces defined by centroids of 110 neighbouring volumes. 111 If one face is on the boundary, use own centroid as neighbour centroid. 112 If two or more are on the boundary, fall back to first order scheme. 113 114 Also return minimum and maximum of conserved quantities 115 """ 116 117 118 from Numeric import array, zeros, Float 119 from util import gradient 120 121 N = self.centroid_values.shape[0] 122 123 a = zeros(N, Float) 124 b = zeros(N, Float) 125 126 for k in range(N): 127 128 number_of_boundaries = self.domain.number_of_boundaries[k] 129 130 if number_of_boundaries == 3: 131 #We have zero neighbouring volumes - 132 #Fall back to first order scheme 133 134 pass 135 136 elif number_of_boundaries == 2: 137 #Special case where we have only one neighbouring volume. 138 139 k0 = k #Self 140 141 #Find index of the one neighbour 142 for k1 in self.domain.neighbours[k,:]: 143 if k1 >= 0: 144 break 145 assert k1 != k0 146 assert k1 >= 0 147 148 #Get data 149 q0 = self.centroid_values[k0] 150 q1 = self.centroid_values[k1] 151 152 x0, y0 = self.domain.centroids[k0] #V0 centroid 153 x1, y1 = self.domain.centroids[k1] #V1 centroid 154 155 #Gradient 156 det = x0*y1 - x1*y0 157 if det != 0.0: 158 a[k] = (y1*q0 - y0*q1)/det 159 b[k] = (x0*q1 - x1*q0)/det 160 161 else: 162 #One or zero missing neighbours 163 #In case of one boundary - own centroid 164 #has been inserted as a surrogate for the one 165 #missing neighbour in neighbour_surrogates 166 167 #Get data 168 k0 = self.domain.surrogate_neighbours[k,0] 169 k1 = self.domain.surrogate_neighbours[k,1] 170 k2 = self.domain.surrogate_neighbours[k,2] 171 172 q0 = self.centroid_values[k0] 173 q1 = self.centroid_values[k1] 174 q2 = self.centroid_values[k2] 175 176 x0, y0 = self.domain.centroids[k0] #V0 centroid 177 x1, y1 = self.domain.centroids[k1] #V1 centroid 178 x2, y2 = self.domain.centroids[k2] #V2 centroid 179 180 #Gradient 181 a[k], b[k] = gradient(x0, y0, x1, y1, x2, y2, q0, q1, q2) 182 #array([q0]), array([q1]), array([q2])) 183 184 return a, b 185 108 186 109 187 def second_order_limiter(self): … … 189 267 self.first_order_limiter() 190 268 elif order == 2: 269 a, b = self.compute_gradients() 270 191 271 self.second_order_limiter() 192 272 else: -
inundation/ga/storm_surge/pyvolution/shallow_water.py
r195 r198 267 267 #################################### 268 268 # Functions for gradient limiting (distribute_to_vertices_and_edges) 269 def first_order_limiter(domain): 270 """First order limiter function, specific to the shallow water wave 271 equation. 272 273 It will ensure that h (w-z) is always non-negative even in the 274 presence of steep bed-slopes (see comment in code) 275 In addition, momemtums get distributed as constant values. 276 277 Precondition: 278 All quantities defined at centroids and bed elevation defined at 279 vertices. 280 281 Postcondition 282 Conserved quantities defined at vertices 269 270 def protect_against_infinitesimal_heights_centroid(domain): 271 """Adjust height and momentum at centroid if height is less than 272 minimum allowed height 283 273 """ 284 274 285 275 #Water levels at centroids 286 276 wc = domain.quantities['level'].centroid_values … … 296 286 ymomc = domain.quantities['ymomentum'].centroid_values 297 287 298 #Water levels at vertices299 wv = domain.quantities['level'].vertex_values300 301 #Bed elevations at vertices302 zv = domain.quantities['elevation'].vertex_values303 304 288 for k in range(domain.number_of_elements): 305 289 #Protect against infinitesimal heights and high velocities … … 312 296 xmomc[k] = ymomc[k] = 0.0 313 297 298 299 300 301 def first_order_limiter(domain): 302 """First order limiter function, specific to the shallow water wave 303 equation. 304 305 It will ensure that h (w-z) is always non-negative even in the 306 presence of steep bed-slopes (see comment in code) 307 In addition, momemtums get distributed as constant values. 308 309 Precondition: 310 All quantities defined at centroids and bed elevation defined at 311 vertices. 312 313 Postcondition 314 Conserved quantities defined at vertices 315 """ 316 317 #FIXME: Might go elsewhere 318 protect_against_infinitesimal_heights_centroid(domain) 319 320 #Update conserved quantities using straight first order 321 for name in domain.conserved_quantities: 322 Q = domain.quantities[name] 323 Q.first_order_limiter() 324 325 326 #Water levels at centroids 327 wc = domain.quantities['level'].centroid_values 328 329 #Bed elevations at centroids 330 zc = domain.quantities['elevation'].centroid_values 331 332 #Water depths at centroids 333 hc = wc - zc 334 335 #Water levels at vertices 336 wv = domain.quantities['level'].vertex_values 337 338 #Bed elevations at vertices 339 zv = domain.quantities['elevation'].vertex_values 314 340 341 #Water depths at vertices 342 hv = wv-zv 343 344 345 #Computed weighted balance between constant levels and and 346 #levels parallel to the bed elevation. 347 for k in range(domain.number_of_elements): 315 348 316 349 #Compute maximal variation in bed elevation … … 327 360 # wvi = (1-alpha)*(zvi+hc) + alpha*(zc+hc) = 328 361 # (1-alpha)*zvi + alpha*zc + hc = 329 # zvi + hc + alpha*(zc-zvi) ;362 # zvi + hc + alpha*(zc-zvi) 330 363 # 331 #where alpha in [0,1] and defined as the ratio nbetween hc and364 #where alpha in [0,1] and defined as the ratio between hc and 332 365 #the maximal difference from zc to zv0, zv1 and zv2 366 # 367 #Mathematically the following can be continued on using hc as 368 # wvi = 369 # zvi + hc + alpha*(zc+hc-zvi-hc) = 370 # zvi + hc + alpha*(hvi-hc) 371 #since hvi = zc+hc-zvi in the constant case 372 333 373 334 374 if z_range > 0.0: … … 339 379 #Update stage 340 380 for i in range(3): 341 wv[k,i] = zv[k,i] + hc[k] + alpha*(zc[k]-zv[k,i]) 342 343 #Update momentum using straight first order 344 for name in ['xmomentum', 'ymomentum']: 345 Q = domain.quantities[name] 346 for i in range(3): 347 Q.vertex_values[:, i] = Q.centroid_values 381 #wv[k,i] = zv[k,i] + hc[k] + alpha*(zc[k]-zv[k,i]) 382 wv[k,i] = zv[k,i] + hc[k] + alpha*(hv[k,i]-hc[k]) 383 348 384 349 385 … … 370 406 371 407 """ 408 409 #FIXME: Might go elsewhere 410 protect_against_infinitesimal_heights_centroid(domain) 411 412 #Update conserved quantities using straight second order 413 for name in domain.conserved_quantities: 414 Q = domain.quantities[name] 415 Q.second_order_limiter() 416 372 417 373 418 #Water levels at centroids -
inundation/ga/storm_surge/pyvolution/test_quantity.py
r195 r198 145 145 146 146 147 def test_gradient(self): 148 quantity = Quantity(self.mesh4) 149 150 #Set up for a gradient of (1,0) 151 quantity.set_values([2.0/3, 4.0/3, 8.0/3, 2.0/3], 152 location = 'centroids') 153 154 #Gradients 155 quantity.compute_gradients() 156 157 #FIXME: 158 159 #HERTIL 160 161 #Gradient of fitted pwl surface 162 #a, b = compute_gradient(v2.id) 163 164 #assert a == 1.0 165 #assert b == 0.0 166 167 168 #And now for the second order stuff 169 # - the full second order extrapolation 170 #domain.order = 2 171 #domain.limiter = dummy_limiter 172 #distribute_to_vertices_and_edges(domain) 173 174 #assert v2.conserved_quantities_vertex0 == 0.0 175 #assert v2.conserved_quantities_vertex1 == 2.0 176 #assert v2.conserved_quantities_vertex2 == 2.0 177 178 179 180 # def test_second_order_extrapolation2(self): 181 182 # initialise_consecutive_datastructure(points=6+4, elements=4) 183 184 # a = Point (0.0, 0.0) 185 # b = Point (0.0, 2.0) 186 # c = Point (2.0, 0.0) 187 # d = Point (0.0, 4.0) 188 # e = Point (2.0, 2.0) 189 # f = Point (4.0, 0.0) 190 191 # #Set up for a gradient of (3,1), f(x) = 3x+y 192 # v1 = Volume(b,a,c,array([2.0+2.0/3,0,0])) 193 # v2 = Volume(b,c,e,array([4.0+4.0/3,0,0])) 194 # v3 = Volume(e,c,f,array([8.0+2.0/3,0,0])) 195 # v4 = Volume(d,b,e,array([2.0+8.0/3,0,0])) 196 197 # #Setup neighbour structure 198 # domain = Domain([v1,v2,v3,v4]) 199 # domain.precompute() 200 # domain.check_integrity() 201 202 # #Lets's check first order first, hey 203 # domain.order = 1 204 # domain.limiter = dummy_limiter 205 # distribute_to_vertices_and_edges(domain) 206 207 # assert allclose(v2.conserved_quantities_vertex0, 208 # v2.conserved_quantities_centroid) 209 # assert allclose(v2.conserved_quantities_vertex1, 210 # v2.conserved_quantities_centroid) 211 # assert allclose(v2.conserved_quantities_vertex2, 212 # v2.conserved_quantities_centroid) 213 214 215 # #Flux across right edge of volume 1 216 # #Outward pointing normal vector 217 # from shallow_water import flux_using_stage as flux_function 218 # normals = Volume.normals 219 220 # normal = Vector.coordinates[normals[1][2]] 221 # ql = Volume.conserved_quantities_face2[1] 222 # qr = Volume.conserved_quantities_face1[0] 223 # fl = array([0.,0.]) 224 # fr = array([0.,0.]) 225 # flux0, max_speed = flux_function(normal, ql, qr, fl, fr) 226 227 # #print flux0, max_speed 228 229 # #print 230 # #print v1.conserved_quantities_face0,\ 231 # # v2.conserved_quantities_face0,\ 232 # # v3.conserved_quantities_face0,\ 233 # # v4.conserved_quantities_face0 234 # #print 235 # #edgelengths = Volume.geometric[:,2:] 236 # #print 237 # #print 238 239 # from python_versions import compute_flux 240 # compute_flux(domain, 100) 241 # F1 = Volume.explicit_update 242 243 # from domain import compute_flux 244 # compute_flux(domain, 100) 245 # F2 = Volume.explicit_update 246 247 # assert allclose(F1, F2) 248 249 # #print F1 250 # #print F2 251 252 253 254 # #Gradient of fitted pwl surface 255 # a, b = compute_gradient(v2.id) 256 257 # assert abs(a[0] - 3.0) < epsilon 258 # assert abs(b[0] - 1.0) < epsilon 259 # #assert qmin[0] == 2.0 + 2.0/3 260 # #assert qmax[0] == 8.0 + 2.0/3 261 262 # #And now for the second order stuff 263 # # - the full second order extrapolation 264 # domain.order = 2 265 # domain.limiter = dummy_limiter 266 # distribute_to_vertices_and_edges(domain) 267 268 # assert allclose(v2.conserved_quantities_vertex0[0], 2.0) 269 # assert allclose(v2.conserved_quantities_vertex1[0], 6.0) 270 # assert allclose(v2.conserved_quantities_vertex2[0], 8.0) 271 272 273 274 275 # def test_limiter(self): 276 277 # initialise_consecutive_datastructure(points=6+4, elements=4) 278 279 # a = Point (0.0, 0.0) 280 # b = Point (0.0, 2.0) 281 # c = Point (2.0, 0.0) 282 # d = Point (0.0, 4.0) 283 # e = Point (2.0, 2.0) 284 # f = Point (4.0, 0.0) 285 286 # #Set up for a gradient of (3,1), f(x) = 3x+y 287 # v1 = Volume(b,a,c,array([0.0,0,0])) 288 # v2 = Volume(b,c,e,array([1.0,0,0])) 289 # v3 = Volume(e,c,f,array([10.0,0,0])) 290 # v4 = Volume(d,b,e,array([0.0,0,0])) 291 292 # #Setup neighbour structure 293 # domain = Domain([v1,v2,v3,v4]) 294 # domain.precompute() 295 296 # #Lets's check first order first, hey 297 # domain.order = 1 298 # domain.limiter = None 299 # distribute_to_vertices_and_edges(domain) 300 # assert allclose(v2.conserved_quantities_vertex0, 301 # v2.conserved_quantities_centroid) 302 # assert allclose(v2.conserved_quantities_vertex1, 303 # v2.conserved_quantities_centroid) 304 # assert allclose(v2.conserved_quantities_vertex2, 305 # v2.conserved_quantities_centroid) 306 307 308 # #Gradient of fitted pwl surface 309 # a, b = compute_gradient(v2.id) 310 311 312 # assert abs(a[0] - 5.0) < epsilon 313 # assert abs(b[0]) < epsilon 314 # #assert qminr[0] == 0.0 315 # #assert qmaxr[0] == 10.0 316 317 # #And now for the second order stuff 318 # # - the full second order extrapolation 319 # domain.order = 2 320 # distribute_to_vertices_and_edges(domain) 321 322 323 # qmin = qmax = v2.conserved_quantities_centroid 324 325 # qmin = minimum(qmin, v1.conserved_quantities_centroid) 326 # qmax = maximum(qmax, v1.conserved_quantities_centroid) 327 328 # qmin = minimum(qmin, v3.conserved_quantities_centroid) 329 # qmax = maximum(qmax, v3.conserved_quantities_centroid) 330 331 # qmin = minimum(qmin, v4.conserved_quantities_centroid) 332 # qmax = maximum(qmax, v4.conserved_quantities_centroid) 333 # #assert qminr == qmin 334 # #assert qmaxr == qmax 335 336 # assert v2.conserved_quantities_vertex0 <= qmax 337 # assert v2.conserved_quantities_vertex0 >= qmin 338 # assert v2.conserved_quantities_vertex1 <= qmax 339 # assert v2.conserved_quantities_vertex1 >= qmin 340 # assert v2.conserved_quantities_vertex2 <= qmax 341 # assert v2.conserved_quantities_vertex2 >= qmin 342 343 344 # #Check that volume has been preserved 345 346 # q = v2.conserved_quantities_centroid[0] 347 # w = (v2.conserved_quantities_vertex0[0] + 348 # v2.conserved_quantities_vertex1[0] + 349 # v2.conserved_quantities_vertex2[0])/3 350 351 # assert allclose(q, w) 352 353 354 355 356 147 357 def test_first_order_limiter(self): 148 358 quantity = Quantity(self.mesh4) … … 161 371 162 372 def test_second_order_limiter(self): 163 164 #FIXME:!!!!!!! 165 166 quantity = Quantity(self.mesh4) 167 168 quantity.set_values([2., 4., 5., 5.], location = 'centroids') 169 #Assume gradient 170 171 #Extrapolate 373 quantity = Quantity(self.mesh4) 374 375 #Create a deliberate overshoot (e.g. from gradient computation) 376 quantity.set_values([[0,3,3], [6,2,2], [3,8,5], [3,5,8]]) 377 378 #Limit and extrapolate 172 379 quantity.second_order_limiter() 173 #print quantity.vertex_values 174 175 380 381 382 #Assert that central triangle is limited by neighbours 383 assert quantity.vertex_values[1,0] <= quantity.vertex_values[2,2] 384 assert quantity.vertex_values[1,0] <= quantity.vertex_values[3,1] 385 386 assert quantity.vertex_values[1,1] <= quantity.vertex_values[3,0] 387 assert quantity.vertex_values[1,1] >= quantity.vertex_values[0,2] 388 389 assert quantity.vertex_values[1,2] <= quantity.vertex_values[2,0] 390 assert quantity.vertex_values[1,2] >= quantity.vertex_values[0,1] 391 392 393 #Assert that quantities are conserved 394 from Numeric import sum 395 for k in range(quantity.centroid_values.shape[0]): 396 assert allclose (quantity.centroid_values[k], 397 sum(quantity.vertex_values[k,:])/3) 398 176 399 177 400 #Check vertices but not edge values -
inundation/ga/storm_surge/pyvolution/test_shallow_water.py
r195 r198 22 22 ql = zeros( 3, Float ) 23 23 qr = zeros( 3, Float ) 24 normal = zeros( 3, Float )24 normal = zeros( 2, Float ) 25 25 zl = zr = 0. 26 26 flux, max_speed = flux_function(normal, ql, qr, zl, zr) … … 110 110 111 111 assert domain.get_conserved_quantities(0, edge=1) == 0. 112 113 112 114 113 … … 602 601 [val3, val3, val3]]) 603 602 603 E = domain.quantities['elevation'].vertex_values 604 604 L = domain.quantities['level'].vertex_values 605 E = domain.quantities['elevation'].vertex_values606 605 607 606 … … 612 611 domain.first_order_limiter() 613 612 614 #Check that all levels are above elevation (within eps) 613 #Check that all levels are above elevation (within eps) 614 615 615 616 assert alltrue(alltrue(greater_equal(L,E-epsilon))) 616 617 -
inundation/ga/storm_surge/pyvolution/util.py
r196 r198 100 100 'Vector of conserved quantities must have length 3'\ 101 101 'for 2D shallow water equation' 102 102 103 try: 103 104 l = len(normal) … … 105 106 raise 'Normal vector must be an Numeric array' 106 107 108 #FIXME: Put this test into C-extension as well 107 109 assert l == 2, 'Normal vector must have 2 components' 108 110 -
inundation/ga/storm_surge/pyvolution/util_ext.c
r195 r198 117 117 return NULL; 118 118 } 119 119 120 120 //Allocate space for return vectors a and b 121 121
Note: See TracChangeset
for help on using the changeset viewer.