#include "Python.h" #include "Numeric/arrayobject.h" #include "math.h" #include const double pi = 3.14159265358979; // Shared code snippets #include "util_ext.h" /* double max(double a, double b) { */ /* double z; */ /* z=(a>b)?a:b; */ /* return z;} */ /* double min(double a, double b) { */ /* double z; */ /* z=(a 0.0) s_minl = 0.0; s_maxr = max(u_rightm+soundspeed_rightm, u_rightp+soundspeed_rightp); if (s_maxr < 0.0) s_maxr = 0.0; s_minr = min(u_rightm-soundspeed_rightm, u_rightp-soundspeed_rightp); if (s_minr > 0.0) s_minr = 0.0; // Flux formulas for left hand side flux_left[0] = d_leftm; flux_left[1] = u_leftm*d_leftm + 0.5*g*h_leftm*h_leftm*b_leftm; flux_right[0] = d_leftp; flux_right[1] = u_leftp*d_leftp + 0.5*g*h_leftp*h_leftp*b_leftp; // Flux computation for left hand side denom = s_maxl-s_minl; if (denom < epsilon) { for (i=0; i<2; i++) edgeflux[i] = 0.0; } else { edgeflux[0] = s_maxl*flux_left[0] - s_minl*flux_right[0]; batemp = (h_leftp)*b_leftp-(h_leftm)*b_leftm; edgeflux[0] += s_maxl*s_minl*batemp; edgeflux[0] /= denom; edgeflux[1] = s_maxl*flux_left[1] - s_minl*flux_right[1]; edgeflux[1] += s_maxl*s_minl*(d_leftp-d_leftm); edgeflux[1] /= denom; } fluxtemp0 = edgeflux[0]; fluxtemp1 = edgeflux[1]; // Flux formulas for right hand side flux_left[0] = d_rightm; flux_left[1] = u_rightm*d_rightm + 0.5*g*h_rightm*h_rightm*b_rightm; flux_right[0] = d_rightp; flux_right[1] = u_rightp*d_rightp + 0.5*g*h_rightp*h_rightp*b_rightp; // Flux computation for right hand side denom = s_maxr-s_minr; if (denom < epsilon) { for (i=0; i<2; i++) edgeflux[i] = 0.0; } else { edgeflux[0] = s_maxr*flux_left[0] - s_minr*flux_right[0]; batemp = (h_rightp)*b_rightp-(h_rightm)*b_rightm; edgeflux[0] += s_maxr*s_minr*batemp; edgeflux[0] /= denom; edgeflux[1] = s_maxr*flux_left[1] - s_minr*flux_right[1]; edgeflux[1] += s_maxr*s_minr*(d_rightp-d_rightm); edgeflux[1] /= denom; } edgeflux[0]=edgeflux[0]-fluxtemp0; edgeflux[1]=edgeflux[1]-fluxtemp1; edgeflux[1]-=0.5*g*h_rightm*h_rightm*b_rightm-0.5*g*hrightstar*hrightstar*b_rightm+0.5*g*hleftstar*hleftstar*b_leftp-0.5*g*h_leftp*h_leftp*b_leftp; //edgeflux[1]-=0.5*g*h_rightm*h_rightm-0.5*g*hrightstar*hrightstar+0.5*g*hleftstar*hleftstar-0.5*g*h_leftp*h_leftp; //edgeflux[1]-=0.5*g*b_rightm*h_rightm*h_rightm-0.5*g*b_leftp*h_leftp*h_leftp; // Maximal wavespeed if ( (s_maxl-s_minl) epsilon) { // Original CFL calculation timestep = min(timestep, 0.5*cfl*areas[k]/max_speed); if (n>=0) { timestep = min(timestep, 0.5*cfl*areas[n]/max_speed); } } // End edge i (and neighbour n) flux[0] /= areas[k]; area_explicit_update[k] = flux[0]; flux[1] /= areas[k]; discharge_explicit_update[k] = flux[1]; //Keep track of maximal speeds max_speed_array[k]=max_speed; } return timestep; } //------------------------------------------------------------- // Old code //------------------------------------------------------------ //Innermost flux function (using w=z+h) // Computational function for flux computation //========================================================================= // Python Glue //========================================================================= //------------------------------------------------ // New velocity based compute fluxes //------------------------------------------------ PyObject *compute_fluxes_channel_ext(PyObject *self, PyObject *args) { PyObject *domain, *area, *discharge, *bed, *height, *velocity, *width; PyArrayObject *neighbours, *neighbour_vertices, *normals, *areas, *area_vertex_values, *discharge_vertex_values, *bed_vertex_values, *height_vertex_values, *velocity_vertex_values, *width_vertex_values, *area_boundary_values, *discharge_boundary_values, *bed_boundary_values, *height_boundary_values, *velocity_boundary_values, *width_boundary_values, *area_explicit_update, *discharge_explicit_update, *max_speed_array; double timestep, epsilon, g, h0, cfl; int number_of_elements; // Convert Python arguments to C if (!PyArg_ParseTuple(args, "dOOOOOOO", ×tep, &domain, &area, &discharge, &bed, &height, &velocity, &width)) { PyErr_SetString(PyExc_RuntimeError, "comp_flux_channel_ext.c: compute_fluxes_channel_ext could not parse input"); return NULL; } epsilon = get_python_double(domain,"epsilon"); g = get_python_double(domain,"g"); h0 = get_python_double(domain,"h0"); cfl = get_python_double(domain,"CFL"); neighbours = get_consecutive_array(domain, "neighbours"); neighbour_vertices= get_consecutive_array(domain, "neighbour_vertices"); normals = get_consecutive_array(domain, "normals"); areas = get_consecutive_array(domain, "areas"); max_speed_array = get_consecutive_array(domain, "max_speed_array"); area_vertex_values = get_consecutive_array(area, "vertex_values"); discharge_vertex_values = get_consecutive_array(discharge, "vertex_values"); bed_vertex_values = get_consecutive_array(bed, "vertex_values"); height_vertex_values = get_consecutive_array(height, "vertex_values"); velocity_vertex_values = get_consecutive_array(velocity, "vertex_values"); width_vertex_values = get_consecutive_array(width, "vertex_values"); area_boundary_values = get_consecutive_array(area, "boundary_values"); discharge_boundary_values = get_consecutive_array(discharge, "boundary_values"); bed_boundary_values = get_consecutive_array(bed, "boundary_values"); height_boundary_values = get_consecutive_array(height, "boundary_values"); velocity_boundary_values = get_consecutive_array(velocity, "boundary_values"); width_boundary_values = get_consecutive_array(width, "boundary_values"); area_explicit_update = get_consecutive_array(area, "explicit_update"); discharge_explicit_update = get_consecutive_array(discharge, "explicit_update"); number_of_elements = area_vertex_values -> dimensions[0]; // Call underlying flux computation routine and update // the explicit update arrays timestep = _compute_fluxes_channel_ext(cfl, timestep, epsilon, g, h0, (long*) neighbours -> data, (long*) neighbour_vertices -> data, (double*) normals -> data, (double*) areas -> data, (double*) area_vertex_values -> data, (double*) discharge_vertex_values -> data, (double*) bed_vertex_values -> data, (double*) height_vertex_values -> data, (double*) velocity_vertex_values -> data, (double*) width_vertex_values -> data, (double*) area_boundary_values -> data, (double*) discharge_boundary_values -> data, (double*) bed_boundary_values -> data, (double*) height_boundary_values -> data, (double*) velocity_boundary_values -> data, (double*) width_boundary_values -> data, (double*) area_explicit_update -> data, (double*) discharge_explicit_update -> data, number_of_elements, (double*) max_speed_array -> data); Py_DECREF(neighbours); Py_DECREF(neighbour_vertices); Py_DECREF(normals); Py_DECREF(areas); Py_DECREF(area_vertex_values); Py_DECREF(discharge_vertex_values); Py_DECREF(bed_vertex_values); Py_DECREF(height_vertex_values); Py_DECREF(velocity_vertex_values); Py_DECREF(width_vertex_values); Py_DECREF(area_boundary_values); Py_DECREF(discharge_boundary_values); Py_DECREF(bed_boundary_values); Py_DECREF(height_boundary_values); Py_DECREF(velocity_boundary_values); Py_DECREF(width_boundary_values); Py_DECREF(area_explicit_update); Py_DECREF(discharge_explicit_update); Py_DECREF(max_speed_array); // Return updated flux timestep return Py_BuildValue("d", timestep); } //------------------------------- // Method table for python module //------------------------------- static struct PyMethodDef MethodTable[] = { {"compute_fluxes_channel_ext", compute_fluxes_channel_ext, METH_VARARGS, "Print out"}, {NULL} }; /* // Module initialisation */ /* void initcomp_flux_vel_ext(void){ */ /* Py_InitModule("comp_flux_vel_ext", MethodTable); */ /* import_array(); */ /* } */ void initchannel_domain_ext(void){ Py_InitModule("channel_domain_ext", MethodTable); import_array(); }