Changeset 8373


Ignore:
Timestamp:
Mar 29, 2012, 5:28:53 PM (13 years ago)
Author:
steve
Message:

changing compute_fluxes to use C domain structure

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  
    236236
    237237        self.tight_slope_limiters = tight_slope_limiters
    238         self.optimise_dry_cells = optimise_dry_cells
     238        self.optimise_dry_cells = int(optimise_dry_cells)
    239239
    240240       
     
    582582        """Call correct module function
    583583            (either from this module or C-extension)"""
    584         compute_fluxes(self)
     584        compute_fluxes_structure(self)
    585585
    586586
     
    11061106                                       domain.already_computed_flux,
    11071107                                       domain.max_speed,
    1108                                        int(domain.optimise_dry_cells))
     1108                                       domain.optimise_dry_cells)
    11091109
    11101110    domain.flux_timestep = flux_timestep
     1111
     1112
     1113
     1114def 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
    11111142
    11121143################################################################################
  • trunk/anuga_core/source/anuga/shallow_water/shallow_water_ext.c

    r8371 r8373  
    12311231// fluxes
    12321232//-------------------------------------------------------------------------------
    1233 PyObject *gravity_new(PyObject *self, PyObject *args) {
     1233PyObject *gravity_wb(PyObject *self, PyObject *args) {
    12341234  //
    1235   //  gravity_new(domain)
     1235  //  gravity_wb(domain)
    12361236  //
    12371237
     
    12431243    double g, avg_h, wx, wy, fact;
    12441244    double x0, y0, x1, y1, x2, y2;
    1245     double n[2];
    12461245    double h[3];
    12471246    double w[3];
    1248     double side[2];
     1247    double sidex, sidey;
     1248    double n0, n1;
    12491249    //double epsilon;
    12501250
     
    13031303
    13041304        // Calculate the side correction term
    1305         side[0] = 0.0;
    1306         side[1] = 0.0;
     1305        sidex = 0.0;
     1306        sidey = 0.0;
    13071307        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];
    13101310            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;
    13131313        }
    13141314
    13151315        // 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;
    13181318
    13191319    }
     
    22602260        long* already_computed_flux,
    22612261        double* max_speed_array,
    2262         int optimise_dry_cells) {
     2262        long optimise_dry_cells) {
    22632263    // Local variables
    22642264    double max_speed, length, inv_area, zl, zr;
     
    24282428    return timestep;
    24292429}
     2430
     2431
     2432
     2433int _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
    24302608
    24312609//=========================================================================
     
    26532831   
    26542832  double timestep, epsilon, H0, g;
    2655   int optimise_dry_cells;
     2833  long optimise_dry_cells;
    26562834   
    26572835  // Convert Python arguments to C
     
    27392917
    27402918
     2919
     2920PyObject *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}
    27412965
    27422966
     
    31293353  {"extrapolate_second_order_sw", extrapolate_second_order_sw, METH_VARARGS, "Print out"},
    31303354  {"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"},
    31323356  {"compute_fluxes_ext_kinetic", compute_fluxes_ext_kinetic, METH_VARARGS, "Print out"},
    31333357  {"gravity", gravity, METH_VARARGS, "Print out"},
    3134   {"gravity_new", gravity_new, METH_VARARGS, "Print out"},
     3358  {"gravity_wb", gravity_wb, METH_VARARGS, "Print out"},
    31353359  {"manning_friction_flat", manning_friction_flat, METH_VARARGS, "Print out"},
    31363360  {"manning_friction_sloped", manning_friction_sloped, METH_VARARGS, "Print out"},
  • trunk/anuga_core/source/anuga/shallow_water/sw_domain.h

    r8371 r8373  
    1515    double  H0;
    1616    double  g;
     17    long    optimise_dry_cells;
     18    double  flux_timestep;
    1719
    1820    long*   neighbours;
     
    2224    double* radii;
    2325    double* areas;
     26
    2427    long*   tri_full_flag;
    2528    long*   already_computed_flux;
     29    double* max_speed;
    2630
    2731    double* vertex_coordinates;
     
    6569            *tri_full_flag,
    6670            *already_computed_flux,
    67             *vertex_coordinates;
     71            *vertex_coordinates,
     72            *max_speed;
    6873
    6974    PyObject *quantities;
     
    7378    D->H0 = get_python_double(domain, "H0");
    7479    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");
    7583
    7684    neighbours = get_consecutive_array(domain, "neighbours");
     
    100108    vertex_coordinates = get_consecutive_array(domain, "vertex_coordinates");
    101109    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
    102114
    103115    quantities = get_python_object(domain, "quantities");
Note: See TracChangeset for help on using the changeset viewer.