Changeset 8373
- Timestamp:
- Mar 29, 2012, 5:28:53 PM (13 years ago)
- Location:
- trunk/anuga_core/source/anuga/shallow_water
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/anuga_core/source/anuga/shallow_water/shallow_water_domain.py
r8372 r8373 236 236 237 237 self.tight_slope_limiters = tight_slope_limiters 238 self.optimise_dry_cells = optimise_dry_cells238 self.optimise_dry_cells = int(optimise_dry_cells) 239 239 240 240 … … 582 582 """Call correct module function 583 583 (either from this module or C-extension)""" 584 compute_fluxes (self)584 compute_fluxes_structure(self) 585 585 586 586 … … 1106 1106 domain.already_computed_flux, 1107 1107 domain.max_speed, 1108 int(domain.optimise_dry_cells))1108 domain.optimise_dry_cells) 1109 1109 1110 1110 domain.flux_timestep = flux_timestep 1111 1112 1113 1114 def compute_fluxes_structure(domain): 1115 """Compute fluxes and timestep suitable for all volumes in domain. 1116 1117 Compute total flux for each conserved quantity using "flux_function" 1118 1119 Fluxes across each edge are scaled by edgelengths and summed up 1120 Resulting flux is then scaled by area and stored in 1121 explicit_update for each of the three conserved quantities 1122 stage, xmomentum and ymomentum 1123 1124 The maximal allowable speed computed by the flux_function for each volume 1125 is converted to a timestep that must not be exceeded. The minimum of 1126 those is computed as the next overall timestep. 1127 1128 Post conditions: 1129 domain.explicit_update is reset to computed flux values 1130 domain.flux_timestep is set to the largest step satisfying all volumes. 1131 1132 This wrapper calls the underlying C version of compute fluxes 1133 """ 1134 1135 1136 from shallow_water_ext import compute_fluxes_ext_central_structure 1137 1138 1139 compute_fluxes_ext_central_structure(domain) 1140 1141 1111 1142 1112 1143 ################################################################################ -
trunk/anuga_core/source/anuga/shallow_water/shallow_water_ext.c
r8371 r8373 1231 1231 // fluxes 1232 1232 //------------------------------------------------------------------------------- 1233 PyObject *gravity_ new(PyObject *self, PyObject *args) {1233 PyObject *gravity_wb(PyObject *self, PyObject *args) { 1234 1234 // 1235 // gravity_ new(domain)1235 // gravity_wb(domain) 1236 1236 // 1237 1237 … … 1243 1243 double g, avg_h, wx, wy, fact; 1244 1244 double x0, y0, x1, y1, x2, y2; 1245 double n[2];1246 1245 double h[3]; 1247 1246 double w[3]; 1248 double side[2]; 1247 double sidex, sidey; 1248 double n0, n1; 1249 1249 //double epsilon; 1250 1250 … … 1303 1303 1304 1304 // Calculate the side correction term 1305 side [0]= 0.0;1306 side [1]= 0.0;1305 sidex = 0.0; 1306 sidey = 0.0; 1307 1307 for (i=0; i<3; i++) { 1308 n [0]= D.normals[k6+2*i];1309 n [1]= D.normals[k6+2*i+1];1308 n0 = D.normals[k6+2*i]; 1309 n1 = D.normals[k6+2*i+1]; 1310 1310 fact = 0.5*g*D.edgelengths[k3+i]*h[i]*h[i]; 1311 side [0] += fact*n[0];1312 side [1] += fact*n[1];1311 sidex += fact*n0; 1312 sidey += fact*n1; 1313 1313 } 1314 1314 1315 1315 // Update momentum with side terms 1316 D.xmom_explicit_update[k] += side [0];1317 D.ymom_explicit_update[k] += side [1];1316 D.xmom_explicit_update[k] += sidex; 1317 D.ymom_explicit_update[k] += sidey; 1318 1318 1319 1319 } … … 2260 2260 long* already_computed_flux, 2261 2261 double* max_speed_array, 2262 intoptimise_dry_cells) {2262 long optimise_dry_cells) { 2263 2263 // Local variables 2264 2264 double max_speed, length, inv_area, zl, zr; … … 2428 2428 return timestep; 2429 2429 } 2430 2431 2432 2433 int _compute_fluxes_central_structure(struct domain *D) { 2434 2435 // Local variables 2436 double max_speed, length, inv_area, zl, zr; 2437 double timestep = 1.0e30; 2438 double h0 = D->H0*D->H0; // This ensures a good balance when h approaches H0. 2439 2440 double limiting_threshold = 10 * D->H0; // Avoid applying limiter below this 2441 // threshold for performance reasons. 2442 // See ANUGA manual under flux limiting 2443 int k, i, m, n; 2444 int ki, nm = 0, ki2; // Index shorthands 2445 2446 2447 // Workspace (making them static actually made function slightly slower (Ole)) 2448 double ql[3], qr[3], edgeflux[3]; // Work array for summing up fluxes 2449 2450 static long call = 1; // Static local variable flagging already computed flux 2451 2452 // Start computation 2453 call++; // Flag 'id' of flux calculation for this timestep 2454 2455 // Set explicit_update to zero for all conserved_quantities. 2456 // This assumes compute_fluxes called before forcing terms 2457 memset((char*) D->stage_explicit_update, 0, D->number_of_elements * sizeof (double)); 2458 memset((char*) D->xmom_explicit_update, 0, D->number_of_elements * sizeof (double)); 2459 memset((char*) D->ymom_explicit_update, 0, D->number_of_elements * sizeof (double)); 2460 2461 // For all triangles 2462 for (k = 0; k < D->number_of_elements; k++) { 2463 // Loop through neighbours and compute edge flux for each 2464 for (i = 0; i < 3; i++) { 2465 ki = k * 3 + i; // Linear index to edge i of triangle k 2466 2467 if (D->already_computed_flux[ki] == call) { 2468 // We've already computed the flux across this edge 2469 continue; 2470 } 2471 2472 // Get left hand side values from triangle k, edge i 2473 ql[0] = D->stage_edge_values[ki]; 2474 ql[1] = D->xmom_edge_values[ki]; 2475 ql[2] = D->ymom_edge_values[ki]; 2476 zl = D->bed_edge_values[ki]; 2477 2478 // Get right hand side values either from neighbouring triangle 2479 // or from boundary array (Quantities at neighbour on nearest face). 2480 n = D->neighbours[ki]; 2481 if (n < 0) { 2482 // Neighbour is a boundary condition 2483 m = -n - 1; // Convert negative flag to boundary index 2484 2485 qr[0] = D->stage_boundary_values[m]; 2486 qr[1] = D->xmom_boundary_values[m]; 2487 qr[2] = D->ymom_boundary_values[m]; 2488 zr = zl; // Extend bed elevation to boundary 2489 } 2490 else { 2491 // Neighbour is a real triangle 2492 m = D->neighbour_edges[ki]; 2493 nm = n * 3 + m; // Linear index (triangle n, edge m) 2494 2495 qr[0] = D->stage_edge_values[nm]; 2496 qr[1] = D->xmom_edge_values[nm]; 2497 qr[2] = D->ymom_edge_values[nm]; 2498 zr = D->bed_edge_values[nm]; 2499 } 2500 2501 // Now we have values for this edge - both from left and right side. 2502 2503 if (D->optimise_dry_cells) { 2504 // Check if flux calculation is necessary across this edge 2505 // This check will exclude dry cells. 2506 // This will also optimise cases where zl != zr as 2507 // long as both are dry 2508 2509 if (fabs(ql[0] - zl) < D->epsilon && 2510 fabs(qr[0] - zr) < D->epsilon) { 2511 // Cell boundary is dry 2512 2513 D->already_computed_flux[ki] = call; // #k Done 2514 if (n >= 0) { 2515 D->already_computed_flux[nm] = call; // #n Done 2516 } 2517 2518 max_speed = 0.0; 2519 continue; 2520 } 2521 } 2522 2523 2524 if (fabs(zl-zr)>1.0e-10) { 2525 report_python_error(AT,"Discontinuous Elevation"); 2526 return 0.0; 2527 } 2528 2529 // Outward pointing normal vector (domain.normals[k, 2*i:2*i+2]) 2530 ki2 = 2 * ki; //k*6 + i*2 2531 2532 // Edge flux computation (triangle k, edge i) 2533 _flux_function_central(ql, qr, zl, zr, 2534 D->normals[ki2], D->normals[ki2 + 1], 2535 D->epsilon, h0, limiting_threshold, D->g, 2536 edgeflux, &max_speed); 2537 2538 2539 // Multiply edgeflux by edgelength 2540 length = D->edgelengths[ki]; 2541 edgeflux[0] *= length; 2542 edgeflux[1] *= length; 2543 edgeflux[2] *= length; 2544 2545 2546 // Update triangle k with flux from edge i 2547 D->stage_explicit_update[k] -= edgeflux[0]; 2548 D->xmom_explicit_update[k] -= edgeflux[1]; 2549 D->ymom_explicit_update[k] -= edgeflux[2]; 2550 2551 D->already_computed_flux[ki] = call; // #k Done 2552 2553 2554 // Update neighbour n with same flux but reversed sign 2555 if (n >= 0) { 2556 D->stage_explicit_update[n] += edgeflux[0]; 2557 D->xmom_explicit_update[n] += edgeflux[1]; 2558 D->ymom_explicit_update[n] += edgeflux[2]; 2559 2560 D->already_computed_flux[nm] = call; // #n Done 2561 } 2562 2563 // Update timestep based on edge i and possibly neighbour n 2564 if (D->tri_full_flag[k] == 1) { 2565 if (max_speed > D->epsilon) { 2566 // Apply CFL condition for triangles joining this edge (triangle k and triangle n) 2567 2568 // CFL for triangle k 2569 timestep = min(timestep, D->radii[k] / max_speed); 2570 2571 if (n >= 0) { 2572 // Apply CFL condition for neigbour n (which is on the ith edge of triangle k) 2573 timestep = min(timestep, D->radii[n] / max_speed); 2574 } 2575 2576 // Ted Rigby's suggested less conservative version 2577 //if (n>=0) { 2578 // timestep = min(timestep, (radii[k]+radii[n])/max_speed); 2579 //} else { 2580 // timestep = min(timestep, radii[k]/max_speed); 2581 // } 2582 } 2583 } 2584 2585 } // End edge i (and neighbour n) 2586 2587 2588 // Normalise triangle k by area and store for when all conserved 2589 // quantities get updated 2590 inv_area = 1.0 / D->areas[k]; 2591 D->stage_explicit_update[k] *= inv_area; 2592 D->xmom_explicit_update[k] *= inv_area; 2593 D->ymom_explicit_update[k] *= inv_area; 2594 2595 2596 // Keep track of maximal speeds 2597 D->max_speed[k] = max_speed; 2598 2599 } // End triangle k 2600 2601 2602 D->flux_timestep = timestep; 2603 2604 return 0; 2605 } 2606 2607 2430 2608 2431 2609 //========================================================================= … … 2653 2831 2654 2832 double timestep, epsilon, H0, g; 2655 intoptimise_dry_cells;2833 long optimise_dry_cells; 2656 2834 2657 2835 // Convert Python arguments to C … … 2739 2917 2740 2918 2919 2920 PyObject *compute_fluxes_ext_central_structure(PyObject *self, PyObject *args) { 2921 /*Compute all fluxes and the timestep suitable for all volumes 2922 in domain. 2923 2924 Compute total flux for each conserved quantity using "flux_function_central" 2925 2926 Fluxes across each edge are scaled by edgelengths and summed up 2927 Resulting flux is then scaled by area and stored in 2928 explicit_update for each of the three conserved quantities 2929 stage, xmomentum and ymomentum 2930 2931 The maximal allowable speed computed by the flux_function for each volume 2932 is converted to a timestep that must not be exceeded. The minimum of 2933 those is computed as the next overall timestep. 2934 2935 Python call: 2936 domain.timestep = compute_fluxes_ext_central_structure(domain, timestep) 2937 2938 2939 Post conditions: 2940 domain.explicit_update is reset to computed flux values 2941 domain.timestep is set to the largest step satisfying all volumes. 2942 2943 2944 */ 2945 2946 struct domain D; 2947 PyObject *domain; 2948 2949 if (!PyArg_ParseTuple(args, "O", &domain)) { 2950 report_python_error(AT, "could not parse input arguments"); 2951 return NULL; 2952 } 2953 2954 // populate the C domain structure with pointers 2955 // to the python domain data 2956 get_python_domain(&D,domain); 2957 2958 // Call underlying flux computation routine and update 2959 // the explicit update arrays 2960 _compute_fluxes_central_structure(&D); 2961 2962 2963 return Py_BuildValue(""); 2964 } 2741 2965 2742 2966 … … 3129 3353 {"extrapolate_second_order_sw", extrapolate_second_order_sw, METH_VARARGS, "Print out"}, 3130 3354 {"compute_fluxes_ext_central", compute_fluxes_ext_central, METH_VARARGS, "Print out"}, 3131 {"compute_fluxes_ext_central_ new", compute_fluxes_ext_central_new, METH_VARARGS, "Print out"},3355 {"compute_fluxes_ext_central_structure", compute_fluxes_ext_central_structure, METH_VARARGS, "Print out"}, 3132 3356 {"compute_fluxes_ext_kinetic", compute_fluxes_ext_kinetic, METH_VARARGS, "Print out"}, 3133 3357 {"gravity", gravity, METH_VARARGS, "Print out"}, 3134 {"gravity_ new", gravity_new, METH_VARARGS, "Print out"},3358 {"gravity_wb", gravity_wb, METH_VARARGS, "Print out"}, 3135 3359 {"manning_friction_flat", manning_friction_flat, METH_VARARGS, "Print out"}, 3136 3360 {"manning_friction_sloped", manning_friction_sloped, METH_VARARGS, "Print out"}, -
trunk/anuga_core/source/anuga/shallow_water/sw_domain.h
r8371 r8373 15 15 double H0; 16 16 double g; 17 long optimise_dry_cells; 18 double flux_timestep; 17 19 18 20 long* neighbours; … … 22 24 double* radii; 23 25 double* areas; 26 24 27 long* tri_full_flag; 25 28 long* already_computed_flux; 29 double* max_speed; 26 30 27 31 double* vertex_coordinates; … … 65 69 *tri_full_flag, 66 70 *already_computed_flux, 67 *vertex_coordinates; 71 *vertex_coordinates, 72 *max_speed; 68 73 69 74 PyObject *quantities; … … 73 78 D->H0 = get_python_double(domain, "H0"); 74 79 D->g = get_python_double(domain, "g"); 80 D->optimise_dry_cells = get_python_integer(domain, "optimise_dry_cells"); 81 82 D->flux_timestep = get_python_double(domain, "flux_timestep"); 75 83 76 84 neighbours = get_consecutive_array(domain, "neighbours"); … … 100 108 vertex_coordinates = get_consecutive_array(domain, "vertex_coordinates"); 101 109 D->vertex_coordinates = (double *) vertex_coordinates->data; 110 111 max_speed = get_consecutive_array(domain, "max_speed"); 112 D->max_speed = (double *) max_speed->data; 113 102 114 103 115 quantities = get_python_object(domain, "quantities");
Note: See TracChangeset
for help on using the changeset viewer.