Changeset 1387 for inundation/ga/storm_surge/pyvolution/shallow_water_ext.c
- Timestamp:
- May 13, 2005, 6:15:08 PM (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
inundation/ga/storm_surge/pyvolution/shallow_water_ext.c
r1017 r1387 2 2 // 3 3 // To compile (Python2.3): 4 // gcc -c domain_ext.c -I/usr/include/python2.3 -o domain_ext.o -Wall -O 5 // gcc -shared domain_ext.o -o domain_ext.so 4 // gcc -c domain_ext.c -I/usr/include/python2.3 -o domain_ext.o -Wall -O 5 // gcc -shared domain_ext.o -o domain_ext.so 6 6 // 7 7 // or use python compile.py … … 11 11 // 12 12 // Ole Nielsen, GA 2004 13 14 13 14 15 15 #include "Python.h" 16 16 #include "Numeric/arrayobject.h" 17 17 #include "math.h" 18 #include <stdio.h> 18 19 19 20 //Shared code snippets … … 26 27 /*Rotate the momentum component q (q[1], q[2]) 27 28 from x,y coordinates to coordinates based on normal vector (n1, n2). 28 29 Result is returned in array 3x1 r 29 30 Result is returned in array 3x1 r 30 31 To rotate in opposite direction, call rotate with (q, n1, -n2) 31 32 Contents of q are changed by this function */ 32 33 Contents of q are changed by this function */ 33 34 34 35 35 36 double q1, q2; 36 37 37 38 //Shorthands 38 39 q1 = q[1]; //uh momentum … … 41 42 //Rotate 42 43 q[1] = n1*q1 + n2*q2; 43 q[2] = -n2*q1 + n1*q2; 44 q[2] = -n2*q1 + n1*q2; 44 45 45 46 return 0; 46 } 47 48 49 47 } 48 49 50 50 51 // Computational function for flux computation (using stage w=z+h) 51 int flux_function(double *q_left, double *q_right, 52 double z_left, double z_right, 53 double n1, double n2, 54 double epsilon, double g, 52 int flux_function(double *q_left, double *q_right, 53 double z_left, double z_right, 54 double n1, double n2, 55 double epsilon, double g, 55 56 double *edgeflux, double *max_speed) { 56 57 57 58 /*Compute fluxes between volumes for the shallow water wave equation 58 cast in terms of the 'stage', w = h+z using 59 cast in terms of the 'stage', w = h+z using 59 60 the 'central scheme' as described in 60 61 61 62 Kurganov, Noelle, Petrova. 'Semidiscrete Central-Upwind Schemes For 62 63 Hyperbolic Conservation Laws and Hamilton-Jacobi Equations'. 63 64 Siam J. Sci. Comput. Vol. 23, No. 3, pp. 707-740. 64 65 The implemented formula is given in equation (3.15) on page 714 65 66 The implemented formula is given in equation (3.15) on page 714 66 67 */ 67 68 68 69 int i; 69 70 70 71 double w_left, h_left, uh_left, vh_left, u_left; 71 72 double w_right, h_right, uh_right, vh_right, u_right; 72 73 double s_min, s_max, soundspeed_left, soundspeed_right; 73 74 double denom, z; 74 double q_left_copy[3], q_right_copy[3]; 75 double q_left_copy[3], q_right_copy[3]; 75 76 double flux_right[3], flux_left[3]; 76 77 77 78 //Copy conserved quantities to protect from modification 78 79 for (i=0; i<3; i++) { 79 80 q_left_copy[i] = q_left[i]; 80 81 q_right_copy[i] = q_right[i]; 81 } 82 82 } 83 83 84 //Align x- and y-momentum with x-axis 84 85 _rotate(q_left_copy, n1, n2); 85 _rotate(q_right_copy, n1, n2); 86 _rotate(q_right_copy, n1, n2); 86 87 87 88 z = (z_left+z_right)/2; //Take average of field values … … 95 96 h_left = 0.0; //Could have been negative 96 97 u_left = 0.0; 97 } else { 98 } else { 98 99 u_left = uh_left/h_left; 99 100 } 100 101 101 102 w_right = q_right_copy[0]; 102 103 h_right = w_right-z; … … 106 107 h_right = 0.0; //Could have been negative 107 108 u_right = 0.0; 108 } else { 109 } else { 109 110 u_right = uh_right/h_right; 110 111 } 111 112 112 //Momentum in y-direction 113 //Momentum in y-direction 113 114 vh_left = q_left_copy[2]; 114 vh_right = q_right_copy[2]; 115 115 vh_right = q_right_copy[2]; 116 116 117 117 118 //Maximal and minimal wave speeds 118 soundspeed_left = sqrt(g*h_left); 119 soundspeed_left = sqrt(g*h_left); 119 120 soundspeed_right = sqrt(g*h_right); 120 121 121 122 s_max = max(u_left+soundspeed_left, u_right+soundspeed_right); 122 if (s_max < 0.0) s_max = 0.0; 123 123 if (s_max < 0.0) s_max = 0.0; 124 124 125 s_min = min(u_left-soundspeed_left, u_right-soundspeed_right); 125 if (s_min > 0.0) s_min = 0.0; 126 127 //Flux formulas 126 if (s_min > 0.0) s_min = 0.0; 127 128 //Flux formulas 128 129 flux_left[0] = u_left*h_left; 129 130 flux_left[1] = u_left*uh_left + 0.5*g*h_left*h_left; 130 131 flux_left[2] = u_left*vh_left; 131 132 132 133 flux_right[0] = u_right*h_right; 133 134 flux_right[1] = u_right*uh_right + 0.5*g*h_right*h_right; 134 135 flux_right[2] = u_right*vh_right; 135 136 137 //Flux computation 136 137 138 //Flux computation 138 139 denom = s_max-s_min; 139 140 if (denom == 0.0) { 140 141 for (i=0; i<3; i++) edgeflux[i] = 0.0; 141 142 *max_speed = 0.0; 142 } else { 143 } else { 143 144 for (i=0; i<3; i++) { 144 145 edgeflux[i] = s_max*flux_left[i] - s_min*flux_right[i]; 145 146 edgeflux[i] += s_max*s_min*(q_right_copy[i]-q_left_copy[i]); 146 147 edgeflux[i] /= denom; 147 } 148 148 } 149 149 150 //Maximal wavespeed 150 151 *max_speed = max(fabs(s_max), fabs(s_min)); 151 152 //Rotate back 152 153 //Rotate back 153 154 _rotate(edgeflux, n1, -n2); 154 155 } 155 156 return 0; 156 157 } 157 158 void _manning_friction(double g, double eps, int N, 159 double* w, double* z, 160 double* uh, double* vh, 161 double* eta, double* xmom, double* ymom) { 158 159 void _manning_friction(double g, double eps, int N, 160 double* w, double* z, 161 double* uh, double* vh, 162 double* eta, double* xmom, double* ymom) { 162 163 163 164 int k; 164 165 double S, h; 165 166 166 167 for (k=0; k<N; k++) { 167 168 if (eta[k] > eps) { … … 180 181 } 181 182 } 182 183 183 184 184 185 185 186 int _balance_deep_and_shallow(int N, 186 187 double* wc, 187 double* zc, 188 double* hc, 189 double* wv, 190 double* zv, 188 double* zc, 189 double* hc, 190 double* wv, 191 double* zv, 191 192 double* hv, 192 double* hvbar, 193 double* xmomc, 194 double* ymomc, 195 double* xmomv, 196 double* ymomv) { 197 193 double* hvbar, 194 double* xmomc, 195 double* ymomc, 196 double* xmomv, 197 double* ymomv) { 198 198 199 int k, k3, i; 199 200 double dz, hmin, alpha; 200 201 201 202 //Compute linear combination between w-limited stages and 202 //h-limited stages close to the bed elevation. 203 203 //h-limited stages close to the bed elevation. 204 204 205 for (k=0; k<N; k++) { 205 206 // Compute maximal variation in bed elevation … … 211 212 212 213 k3 = 3*k; 213 214 214 215 //FIXME: Try with this one precomputed 215 216 dz = 0.0; … … 220 221 } 221 222 222 223 //Create alpha in [0,1], where alpha==0 means using the h-limited 223 224 //Create alpha in [0,1], where alpha==0 means using the h-limited 224 225 //stage and alpha==1 means using the w-limited stage as 225 226 //computed by the gradient limiter (both 1st or 2nd order) … … 227 228 //If hmin > dz/2 then alpha = 1 and the bed will have no effect 228 229 //If hmin < 0 then alpha = 0 reverting to constant height above bed. 229 230 230 231 231 232 if (dz > 0.0) 232 //if (hmin<0.0) 233 //if (hmin<0.0) 233 234 // alpha = 0.0; 234 235 //else 235 236 // alpha = max( min( hc[k]/dz, 1.0), 0.0 ); 236 237 alpha = max( min( 2.0*hmin/dz, 1.0), 0.0 ); 237 238 238 else 239 239 alpha = 1.0; //Flat bed 240 240 241 //alpha = 1.0; 242 241 243 //printf("dz = %.3f, alpha = %.8f\n", dz, alpha); 242 244 243 // Let 244 // 245 // wvi be the w-limited stage (wvi = zvi + hvi) 245 // Let 246 // 247 // wvi be the w-limited stage (wvi = zvi + hvi) 246 248 // wvi- be the h-limited state (wvi- = zvi + hvi-) 247 // 248 // 249 // 250 // 249 251 // where i=0,1,2 denotes the vertex ids 250 // 251 // Weighted balance between w-limited and h-limited stage is 252 // 253 // wvi := (1-alpha)*(zvi+hvi-) + alpha*(zvi+hvi) 254 // 252 // 253 // Weighted balance between w-limited and h-limited stage is 254 // 255 // wvi := (1-alpha)*(zvi+hvi-) + alpha*(zvi+hvi) 256 // 255 257 // It follows that the updated wvi is 256 258 // wvi := zvi + (1-alpha)*hvi- + alpha*hvi 257 // 259 // 258 260 // Momentum is balanced between constant and limited 259 261 260 if (alpha < 1) { 262 if (alpha < 1) { 261 263 for (i=0; i<3; i++) { 262 264 wv[k3+i] = zv[k3+i] + (1-alpha)*hvbar[k3+i] + alpha*hv[k3+i]; 263 264 //Update momentum as a linear combination of 265 266 //Update momentum as a linear combination of 265 267 //xmomc and ymomc (shallow) and momentum 266 268 //from extrapolator xmomv and ymomv (deep). 267 xmomv[k3+i] = (1-alpha)*xmomc[k] + alpha*xmomv[k3+i]; 269 xmomv[k3+i] = (1-alpha)*xmomc[k] + alpha*xmomv[k3+i]; 268 270 ymomv[k3+i] = (1-alpha)*ymomc[k] + alpha*ymomv[k3+i]; 269 } 271 } 270 272 } 271 } 273 } 272 274 return 0; 273 275 } … … 275 277 276 278 277 int _protect(int N, 278 double minimum_allowed_height, 279 int _protect(int N, 280 double minimum_allowed_height, 279 281 double* wc, 280 double* zc, 281 double* xmomc, 282 double* zc, 283 double* xmomc, 282 284 double* ymomc) { 283 284 int k; 285 286 int k; 285 287 double hc; 286 288 287 289 //Protect against initesimal and negative heights 288 290 289 291 for (k=0; k<N; k++) { 290 292 hc = wc[k] - zc[k]; 291 292 if (hc < minimum_allowed_height) { 293 wc[k] = zc[k]; 293 294 if (hc < minimum_allowed_height) { 295 wc[k] = zc[k]; 294 296 xmomc[k] = 0.0; 295 ymomc[k] = 0.0; 297 ymomc[k] = 0.0; 296 298 } 297 299 298 300 } 299 301 return 0; … … 309 311 int _assign_wind_field_values(int N, 310 312 double* xmom_update, 311 double* ymom_update, 313 double* ymom_update, 312 314 double* s_vec, 313 315 double* phi_vec, … … 318 320 int k; 319 321 double S, s, phi, u, v; 320 322 321 323 for (k=0; k<N; k++) { 322 324 323 325 s = s_vec[k]; 324 326 phi = phi_vec[k]; … … 330 332 u = s*cos(phi); 331 333 v = s*sin(phi); 332 334 333 335 //Compute wind stress 334 336 S = cw * sqrt(u*u + v*v); 335 337 xmom_update[k] += S*u; 336 ymom_update[k] += S*v; 337 } 338 return 0; 339 } 338 ymom_update[k] += S*v; 339 } 340 return 0; 341 } 340 342 341 343 … … 348 350 // gravity(g, h, v, x, xmom, ymom) 349 351 // 350 351 352 353 352 354 PyArrayObject *h, *v, *x, *xmom, *ymom; 353 355 int k, i, N, k3, k6; 354 356 double g, avg_h, zx, zy; 355 357 double x0, y0, x1, y1, x2, y2, z0, z1, z2; 356 358 357 359 if (!PyArg_ParseTuple(args, "dOOOOO", 358 &g, &h, &v, &x, 359 &xmom, &ymom)) 360 return NULL; 360 &g, &h, &v, &x, 361 &xmom, &ymom)) 362 return NULL; 361 363 362 364 N = h -> dimensions[0]; 363 365 for (k=0; k<N; k++) { 364 366 k3 = 3*k; // base index 365 k6 = 6*k; // base index 366 367 k6 = 6*k; // base index 368 367 369 avg_h = 0.0; 368 370 for (i=0; i<3; i++) { 369 371 avg_h += ((double *) h -> data)[k3+i]; 370 } 372 } 371 373 avg_h /= 3; 372 373 374 375 374 376 //Compute bed slope 375 377 x0 = ((double*) x -> data)[k6 + 0]; 376 y0 = ((double*) x -> data)[k6 + 1]; 378 y0 = ((double*) x -> data)[k6 + 1]; 377 379 x1 = ((double*) x -> data)[k6 + 2]; 378 y1 = ((double*) x -> data)[k6 + 3]; 380 y1 = ((double*) x -> data)[k6 + 3]; 379 381 x2 = ((double*) x -> data)[k6 + 4]; 380 y2 = ((double*) x -> data)[k6 + 5]; 382 y2 = ((double*) x -> data)[k6 + 5]; 381 383 382 384 383 385 z0 = ((double*) v -> data)[k3 + 0]; 384 386 z1 = ((double*) v -> data)[k3 + 1]; 385 z2 = ((double*) v -> data)[k3 + 2]; 387 z2 = ((double*) v -> data)[k3 + 2]; 386 388 387 389 _gradient(x0, y0, x1, y1, x2, y2, z0, z1, z2, &zx, &zy); … … 389 391 //Update momentum 390 392 ((double*) xmom -> data)[k] += -g*zx*avg_h; 391 ((double*) ymom -> data)[k] += -g*zy*avg_h; 392 } 393 393 ((double*) ymom -> data)[k] += -g*zy*avg_h; 394 } 395 394 396 return Py_BuildValue(""); 395 397 } … … 400 402 // manning_friction(g, eps, h, uh, vh, eta, xmom_update, ymom_update) 401 403 // 402 403 404 405 404 406 PyArrayObject *w, *z, *uh, *vh, *eta, *xmom, *ymom; 405 407 int N; 406 408 double g, eps; 407 409 408 410 if (!PyArg_ParseTuple(args, "ddOOOOOOO", 409 &g, &eps, &w, &z, &uh, &vh, &eta, 410 &xmom, &ymom)) 411 return NULL; 412 413 N = w -> dimensions[0]; 411 &g, &eps, &w, &z, &uh, &vh, &eta, 412 &xmom, &ymom)) 413 return NULL; 414 415 N = w -> dimensions[0]; 414 416 _manning_friction(g, eps, N, 415 417 (double*) w -> data, 416 (double*) z -> data, 417 (double*) uh -> data, 418 (double*) vh -> data, 418 (double*) z -> data, 419 (double*) uh -> data, 420 (double*) vh -> data, 419 421 (double*) eta -> data, 420 (double*) xmom -> data, 422 (double*) xmom -> data, 421 423 (double*) ymom -> data); 422 424 423 425 return Py_BuildValue(""); 424 } 426 } 425 427 426 428 PyObject *rotate(PyObject *self, PyObject *args, PyObject *kwargs) { … … 431 433 // normal a Float numeric array of length 2. 432 434 433 435 434 436 PyObject *Q, *Normal; 435 437 PyArrayObject *q, *r, *normal; 436 438 437 439 static char *argnames[] = {"q", "normal", "direction", NULL}; 438 440 int dimensions[1], i, direction=1; 439 441 double n1, n2; 440 442 441 // Convert Python arguments to C 442 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i", argnames, 443 &Q, &Normal, &direction)) 444 return NULL; 443 // Convert Python arguments to C 444 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i", argnames, 445 &Q, &Normal, &direction)) 446 return NULL; 445 447 446 448 //Input checks (convert sequences into numeric arrays) 447 q = (PyArrayObject *) 449 q = (PyArrayObject *) 448 450 PyArray_ContiguousFromObject(Q, PyArray_DOUBLE, 0, 0); 449 normal = (PyArrayObject *) 451 normal = (PyArrayObject *) 450 452 PyArray_ContiguousFromObject(Normal, PyArray_DOUBLE, 0, 0); 451 453 452 454 453 455 if (normal -> dimensions[0] != 2) { 454 456 PyErr_SetString(PyExc_RuntimeError, "Normal vector must have 2 components"); … … 456 458 } 457 459 458 //Allocate space for return vector r (don't DECREF) 460 //Allocate space for return vector r (don't DECREF) 459 461 dimensions[0] = 3; 460 462 r = (PyArrayObject *) PyArray_FromDims(1, dimensions, PyArray_DOUBLE); … … 462 464 //Copy 463 465 for (i=0; i<3; i++) { 464 ((double *) (r -> data))[i] = ((double *) (q -> data))[i]; 465 } 466 466 ((double *) (r -> data))[i] = ((double *) (q -> data))[i]; 467 } 468 467 469 //Get normal and direction 468 n1 = ((double *) normal -> data)[0]; 469 n2 = ((double *) normal -> data)[1]; 470 n1 = ((double *) normal -> data)[0]; 471 n2 = ((double *) normal -> data)[1]; 470 472 if (direction == -1) n2 = -n2; 471 473 … … 474 476 475 477 //Release numeric arrays 476 Py_DECREF(q); 478 Py_DECREF(q); 477 479 Py_DECREF(normal); 478 480 479 481 //return result using PyArray to avoid memory leak 480 482 return PyArray_Return(r); 481 } 483 } 482 484 483 485 … … 490 492 Fluxes across each edge are scaled by edgelengths and summed up 491 493 Resulting flux is then scaled by area and stored in 492 explicit_update for each of the three conserved quantities 494 explicit_update for each of the three conserved quantities 493 495 stage, xmomentum and ymomentum 494 496 … … 496 498 is converted to a timestep that must not be exceeded. The minimum of 497 499 those is computed as the next overall timestep. 498 500 499 501 Python call: 500 domain.timestep = compute_fluxes(timestep, 501 domain.epsilon, 502 domain.timestep = compute_fluxes(timestep, 503 domain.epsilon, 502 504 domain.g, 503 505 domain.neighbours, 504 506 domain.neighbour_edges, 505 507 domain.normals, 506 domain.edgelengths, 508 domain.edgelengths, 507 509 domain.radii, 508 510 domain.areas, 509 Stage.edge_values, 510 Xmom.edge_values, 511 Ymom.edge_values, 512 Bed.edge_values, 511 Stage.edge_values, 512 Xmom.edge_values, 513 Ymom.edge_values, 514 Bed.edge_values, 513 515 Stage.boundary_values, 514 516 Xmom.boundary_values, … … 517 519 Xmom.explicit_update, 518 520 Ymom.explicit_update) 519 521 520 522 521 523 Post conditions: 522 524 domain.explicit_update is reset to computed flux values 523 domain.timestep is set to the largest step satisfying all volumes. 524 525 525 domain.timestep is set to the largest step satisfying all volumes. 526 527 526 528 */ 527 529 528 530 529 531 PyArrayObject *neighbours, *neighbour_edges, 530 532 *normals, *edgelengths, *radii, *areas, 531 *stage_edge_values, 532 *xmom_edge_values, 533 *ymom_edge_values, 534 *bed_edge_values, 533 *stage_edge_values, 534 *xmom_edge_values, 535 *ymom_edge_values, 536 *bed_edge_values, 535 537 *stage_boundary_values, 536 538 *xmom_boundary_values, … … 540 542 *ymom_explicit_update; 541 543 542 543 //Local variables 544 545 //Local variables 544 546 double timestep, max_speed, epsilon, g; 545 547 double normal[2], ql[3], qr[3], zl, zr; … … 548 550 int number_of_elements, k, i, j, m, n; 549 551 int ki, nm, ki2; //Index shorthands 550 551 552 // Convert Python arguments to C 552 553 554 // Convert Python arguments to C 553 555 if (!PyArg_ParseTuple(args, "dddOOOOOOOOOOOOOOOO", 554 556 ×tep, 555 557 &epsilon, 556 558 &g, 557 &neighbours, 559 &neighbours, 558 560 &neighbour_edges, 559 &normals, 561 &normals, 560 562 &edgelengths, &radii, &areas, 561 &stage_edge_values, 562 &xmom_edge_values, 563 &ymom_edge_values, 564 &bed_edge_values, 563 &stage_edge_values, 564 &xmom_edge_values, 565 &ymom_edge_values, 566 &bed_edge_values, 565 567 &stage_boundary_values, 566 568 &xmom_boundary_values, … … 574 576 575 577 number_of_elements = stage_edge_values -> dimensions[0]; 576 577 578 579 578 580 for (k=0; k<number_of_elements; k++) { 579 581 580 582 //Reset work array 581 583 for (j=0; j<3; j++) flux[j] = 0.0; 582 584 583 585 //Loop through neighbours and compute edge flux for each 584 586 for (i=0; i<3; i++) { … … 586 588 ql[0] = ((double *) stage_edge_values -> data)[ki]; 587 589 ql[1] = ((double *) xmom_edge_values -> data)[ki]; 588 ql[2] = ((double *) ymom_edge_values -> data)[ki]; 589 zl = ((double *) bed_edge_values -> data)[ki]; 590 ql[2] = ((double *) ymom_edge_values -> data)[ki]; 591 zl = ((double *) bed_edge_values -> data)[ki]; 590 592 591 593 //Quantities at neighbour on nearest face … … 593 595 if (n < 0) { 594 596 m = -n-1; //Convert negative flag to index 595 qr[0] = ((double *) stage_boundary_values -> data)[m]; 596 qr[1] = ((double *) xmom_boundary_values -> data)[m]; 597 qr[2] = ((double *) ymom_boundary_values -> data)[m]; 597 qr[0] = ((double *) stage_boundary_values -> data)[m]; 598 qr[1] = ((double *) xmom_boundary_values -> data)[m]; 599 qr[2] = ((double *) ymom_boundary_values -> data)[m]; 598 600 zr = zl; //Extend bed elevation to boundary 599 } else { 601 } else { 600 602 m = ((long *) neighbour_edges -> data)[ki]; 601 602 nm = n*3+m; 603 604 nm = n*3+m; 603 605 qr[0] = ((double *) stage_edge_values -> data)[nm]; 604 606 qr[1] = ((double *) xmom_edge_values -> data)[nm]; 605 qr[2] = ((double *) ymom_edge_values -> data)[nm]; 606 zr = ((double *) bed_edge_values -> data)[nm]; 607 qr[2] = ((double *) ymom_edge_values -> data)[nm]; 608 zr = ((double *) bed_edge_values -> data)[nm]; 607 609 } 608 610 609 611 //printf("%d %d [%d] (%d, %d): %.2f %.2f %.2f\n", k, i, ki, n, m, 610 // ql[0], ql[1], ql[2]); 611 612 613 // Outward pointing normal vector 612 // ql[0], ql[1], ql[2]); 613 614 615 // Outward pointing normal vector 614 616 // normal = domain.normals[k, 2*i:2*i+2] 615 617 ki2 = 2*ki; //k*6 + i*2 616 618 normal[0] = ((double *) normals -> data)[ki2]; 617 normal[1] = ((double *) normals -> data)[ki2+1]; 619 normal[1] = ((double *) normals -> data)[ki2+1]; 618 620 619 621 //Edge flux computation 620 flux_function(ql, qr, zl, zr, 622 flux_function(ql, qr, zl, zr, 621 623 normal[0], normal[1], 622 epsilon, g, 624 epsilon, g, 623 625 edgeflux, &max_speed); 624 626 625 627 626 628 //flux -= edgeflux * edgelengths[k,i] 627 for (j=0; j<3; j++) { 629 for (j=0; j<3; j++) { 628 630 flux[j] -= edgeflux[j]*((double *) edgelengths -> data)[ki]; 629 631 } 630 632 631 633 //Update timestep 632 634 //timestep = min(timestep, domain.radii[k]/max_speed) … … 634 636 if (max_speed > epsilon) { 635 637 timestep = min(timestep, ((double *) radii -> data)[k]/max_speed); 636 } 638 } 637 639 } // end for i 638 640 639 641 //Normalise by area and store for when all conserved 640 642 //quantities get updated 641 643 // flux /= areas[k] 642 for (j=0; j<3; j++) { 644 for (j=0; j<3; j++) { 643 645 flux[j] /= ((double *) areas -> data)[k]; 644 646 } … … 646 648 ((double *) stage_explicit_update -> data)[k] = flux[0]; 647 649 ((double *) xmom_explicit_update -> data)[k] = flux[1]; 648 ((double *) ymom_explicit_update -> data)[k] = flux[2]; 650 ((double *) ymom_explicit_update -> data)[k] = flux[2]; 649 651 650 652 } //end for k 651 653 652 654 return Py_BuildValue("d", timestep); 653 } 655 } 654 656 655 657 … … 658 660 // 659 661 // protect(minimum_allowed_height, wc, zc, xmomc, ymomc) 660 661 662 PyArrayObject 662 663 664 PyArrayObject 663 665 *wc, //Stage at centroids 664 *zc, //Elevation at centroids 666 *zc, //Elevation at centroids 665 667 *xmomc, //Momentums at centroids 666 *ymomc; 667 668 669 int N; 668 *ymomc; 669 670 671 int N; 670 672 double minimum_allowed_height; 671 672 // Convert Python arguments to C 673 if (!PyArg_ParseTuple(args, "dOOOO", 673 674 // Convert Python arguments to C 675 if (!PyArg_ParseTuple(args, "dOOOO", 674 676 &minimum_allowed_height, 675 677 &wc, &zc, &xmomc, &ymomc)) … … 677 679 678 680 N = wc -> dimensions[0]; 679 681 680 682 _protect(N, 681 683 minimum_allowed_height, 682 684 (double*) wc -> data, 683 (double*) zc -> data, 684 (double*) xmomc -> data, 685 (double*) zc -> data, 686 (double*) xmomc -> data, 685 687 (double*) ymomc -> data); 686 687 return Py_BuildValue(""); 688 689 return Py_BuildValue(""); 688 690 } 689 691 … … 694 696 // balance_deep_and_shallow(wc, zc, hc, wv, zv, hv, 695 697 // xmomc, ymomc, xmomv, ymomv) 696 697 698 PyArrayObject 698 699 700 PyArrayObject 699 701 *wc, //Stage at centroids 700 *zc, //Elevation at centroids 701 *hc, //Height at centroids 702 *zc, //Elevation at centroids 703 *hc, //Height at centroids 702 704 *wv, //Stage at vertices 703 705 *zv, //Elevation at vertices 704 *hv, //Depths at vertices 705 *hvbar, //h-Limited depths at vertices 706 *hv, //Depths at vertices 707 *hvbar, //h-Limited depths at vertices 706 708 *xmomc, //Momentums at centroids and vertices 707 *ymomc, 708 *xmomv, 709 *ymomv; 710 709 *ymomc, 710 *xmomv, 711 *ymomv; 712 711 713 int N; //, err; 712 713 // Convert Python arguments to C 714 if (!PyArg_ParseTuple(args, "OOOOOOOOOOO", 715 &wc, &zc, &hc, 714 715 // Convert Python arguments to C 716 if (!PyArg_ParseTuple(args, "OOOOOOOOOOO", 717 &wc, &zc, &hc, 716 718 &wv, &zv, &hv, &hvbar, 717 719 &xmomc, &ymomc, &xmomv, &ymomv)) … … 719 721 720 722 N = wc -> dimensions[0]; 721 723 722 724 _balance_deep_and_shallow(N, 723 725 (double*) wc -> data, 724 (double*) zc -> data, 725 (double*) hc -> data, 726 (double*) wv -> data, 727 (double*) zv -> data, 726 (double*) zc -> data, 727 (double*) hc -> data, 728 (double*) wv -> data, 729 (double*) zv -> data, 728 730 (double*) hv -> data, 729 (double*) hvbar -> data, 730 (double*) xmomc -> data, 731 (double*) ymomc -> data, 732 (double*) xmomv -> data, 733 (double*) ymomv -> data); 734 735 736 return Py_BuildValue(""); 731 (double*) hvbar -> data, 732 (double*) xmomc -> data, 733 (double*) ymomc -> data, 734 (double*) xmomv -> data, 735 (double*) ymomv -> data); 736 737 738 return Py_BuildValue(""); 737 739 } 738 740 … … 740 742 741 743 PyObject *h_limiter(PyObject *self, PyObject *args) { 742 744 743 745 PyObject *domain, *Tmp; 744 PyArrayObject 745 *hv, *hc, //Depth at vertices and centroids 746 PyArrayObject 747 *hv, *hc, //Depth at vertices and centroids 746 748 *hvbar, //Limited depth at vertices (return values) 747 749 *neighbours; 748 750 749 751 int k, i, n, N, k3; 750 752 int dimensions[2]; 751 753 double beta_h; //Safety factor (see config.py) 752 754 double *hmin, *hmax, hn; 753 754 // Convert Python arguments to C 755 if (!PyArg_ParseTuple(args, "OOO", &domain, &hc, &hv)) 755 756 // Convert Python arguments to C 757 if (!PyArg_ParseTuple(args, "OOO", &domain, &hc, &hv)) 756 758 return NULL; 757 759 … … 759 761 760 762 //Get safety factor beta_h 761 Tmp = PyObject_GetAttrString(domain, "beta_h"); 762 if (!Tmp) 763 return NULL; 764 765 beta_h = PyFloat_AsDouble(Tmp); 766 767 Py_DECREF(Tmp); 763 Tmp = PyObject_GetAttrString(domain, "beta_h"); 764 if (!Tmp) 765 return NULL; 766 767 beta_h = PyFloat_AsDouble(Tmp); 768 769 Py_DECREF(Tmp); 768 770 769 771 N = hc -> dimensions[0]; 770 772 771 773 //Create hvbar 772 774 dimensions[0] = N; 773 dimensions[1] = 3; 775 dimensions[1] = 3; 774 776 hvbar = (PyArrayObject *) PyArray_FromDims(2, dimensions, PyArray_DOUBLE); 775 777 776 778 777 779 //Find min and max of this and neighbour's centroid values 778 780 hmin = malloc(N * sizeof(double)); 779 hmax = malloc(N * sizeof(double)); 781 hmax = malloc(N * sizeof(double)); 780 782 for (k=0; k<N; k++) { 781 783 k3=k*3; 782 784 783 785 hmin[k] = ((double*) hc -> data)[k]; 784 786 hmax[k] = hmin[k]; 785 787 786 788 for (i=0; i<3; i++) { 787 789 n = ((long*) neighbours -> data)[k3+i]; 788 790 789 791 //Initialise hvbar with values from hv 790 ((double*) hvbar -> data)[k3+i] = ((double*) hv -> data)[k3+i]; 791 792 ((double*) hvbar -> data)[k3+i] = ((double*) hv -> data)[k3+i]; 793 792 794 if (n >= 0) { 793 795 hn = ((double*) hc -> data)[n]; //Neighbour's centroid value 794 796 795 797 hmin[k] = min(hmin[k], hn); 796 798 hmax[k] = max(hmax[k], hn); … … 798 800 } 799 801 } 800 802 801 803 // Call underlying standard routine 802 804 _limit(N, beta_h, (double*) hc -> data, (double*) hvbar -> data, hmin, hmax); 803 804 // // //Py_DECREF(domain); //FIXME: NEcessary? 805 806 // // //Py_DECREF(domain); //FIXME: NEcessary? 805 807 free(hmin); 806 free(hmax); 807 808 //return result using PyArray to avoid memory leak 808 free(hmax); 809 810 //return result using PyArray to avoid memory leak 809 811 return PyArray_Return(hvbar); 810 //return Py_BuildValue(""); 812 //return Py_BuildValue(""); 811 813 } 812 814 … … 819 821 // s_vec, phi_vec, self.const) 820 822 821 823 822 824 823 825 PyArrayObject //(one element per triangle) 824 *s_vec, //Speeds 825 *phi_vec, //Bearings 826 *s_vec, //Speeds 827 *phi_vec, //Bearings 826 828 *xmom_update, //Momentum updates 827 *ymom_update; 828 829 830 int N; 829 *ymom_update; 830 831 832 int N; 831 833 double cw; 832 833 // Convert Python arguments to C 834 if (!PyArg_ParseTuple(args, "OOOOd", 834 835 // Convert Python arguments to C 836 if (!PyArg_ParseTuple(args, "OOOOd", 835 837 &xmom_update, 836 &ymom_update, 837 &s_vec, &phi_vec, 838 &ymom_update, 839 &s_vec, &phi_vec, 838 840 &cw)) 839 841 return NULL; 840 842 841 843 N = xmom_update -> dimensions[0]; 842 844 843 845 _assign_wind_field_values(N, 844 846 (double*) xmom_update -> data, 845 (double*) ymom_update -> data, 846 (double*) s_vec -> data, 847 (double*) ymom_update -> data, 848 (double*) s_vec -> data, 847 849 (double*) phi_vec -> data, 848 850 cw); 849 850 return Py_BuildValue(""); 851 } 852 853 854 855 856 ////////////////////////////////////////// 851 852 return Py_BuildValue(""); 853 } 854 855 856 857 858 ////////////////////////////////////////// 857 859 // Method table for python module 858 860 static struct PyMethodDef MethodTable[] = { … … 861 863 * three. 862 864 */ 863 865 864 866 {"rotate", (PyCFunction)rotate, METH_VARARGS | METH_KEYWORDS, "Print out"}, 865 {"compute_fluxes", compute_fluxes, METH_VARARGS, "Print out"}, 866 {"gravity", gravity, METH_VARARGS, "Print out"}, 867 {"manning_friction", manning_friction, METH_VARARGS, "Print out"}, 868 {"balance_deep_and_shallow", balance_deep_and_shallow, 869 METH_VARARGS, "Print out"}, 870 {"h_limiter", h_limiter, 871 METH_VARARGS, "Print out"}, 872 {"protect", protect, METH_VARARGS | METH_KEYWORDS, "Print out"}, 873 {"assign_windfield_values", assign_windfield_values, 874 METH_VARARGS | METH_KEYWORDS, "Print out"}, 875 //{"distribute_to_vertices_and_edges", 876 // distribute_to_vertices_and_edges, METH_VARARGS}, 877 //{"update_conserved_quantities", 878 // update_conserved_quantities, METH_VARARGS}, 879 //{"set_initialcondition", 880 // set_initialcondition, METH_VARARGS}, 867 {"compute_fluxes", compute_fluxes, METH_VARARGS, "Print out"}, 868 {"gravity", gravity, METH_VARARGS, "Print out"}, 869 {"manning_friction", manning_friction, METH_VARARGS, "Print out"}, 870 {"balance_deep_and_shallow", balance_deep_and_shallow, 871 METH_VARARGS, "Print out"}, 872 {"h_limiter", h_limiter, 873 METH_VARARGS, "Print out"}, 874 {"protect", protect, METH_VARARGS | METH_KEYWORDS, "Print out"}, 875 {"assign_windfield_values", assign_windfield_values, 876 METH_VARARGS | METH_KEYWORDS, "Print out"}, 877 //{"distribute_to_vertices_and_edges", 878 // distribute_to_vertices_and_edges, METH_VARARGS}, 879 //{"update_conserved_quantities", 880 // update_conserved_quantities, METH_VARARGS}, 881 //{"set_initialcondition", 882 // set_initialcondition, METH_VARARGS}, 881 883 {NULL, NULL} 882 884 }; 883 884 // Module initialisation 885 886 // Module initialisation 885 887 void initshallow_water_ext(void){ 886 888 Py_InitModule("shallow_water_ext", MethodTable); 887 888 import_array(); //Necessary for handling of NumPY structures 889 } 889 890 import_array(); //Necessary for handling of NumPY structures 891 }
Note: See TracChangeset
for help on using the changeset viewer.