Changeset 4990


Ignore:
Timestamp:
Feb 5, 2008, 5:25:32 PM (17 years ago)
Author:
steve
Message:

Combining calculation of gradient, limiting edge by neighbour
and extrapolation in one procedure in quantity

Location:
anuga_core/source/anuga/abstract_2d_finite_volumes
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • anuga_core/source/anuga/abstract_2d_finite_volumes/quantity.py

    r4962 r4990  
    14041404        extrapolate_from_gradient(self)
    14051405
     1406    def extrapolate_second_order_and_limit(self):
     1407        #Call correct module function
     1408        #(either from this module or C-extension)
     1409        extrapolate_second_order_and_limit(self)       
     1410
    14061411    def backup_centroid_values(self):
    14071412        #Call correct module function
  • anuga_core/source/anuga/abstract_2d_finite_volumes/quantity_ext.c

    r4978 r4990  
    1616//Shared code snippets
    1717#include "util_ext.h"
    18 //#include "quantity_ext.h" //Obsolete
    19 
    20 
     18
     19
     20//-------------------------------------------
     21// Low level routines (called from wrappers)
     22//------------------------------------------
    2123
    2224int _compute_gradients(int N,
     
    9092        return 0;
    9193}
    92 
    9394
    9495
     
    135136        return 0;
    136137}
     138
     139
     140int _extrapolate_and_limit_from_gradient(int N,double beta,
     141                                         double* centroids,
     142                                         long*   neighbours,
     143                                         double* centroid_values,
     144                                         double* vertex_coordinates,
     145                                         double* vertex_values,
     146                                         double* edge_values,
     147                                         double* x_gradient,
     148                                         double* y_gradient) {
     149
     150        int i, k, k2, k3, k6;
     151        double x, y, x0, y0, x1, y1, x2, y2;
     152        long n;
     153        double qmin, qmax, qn, qc;
     154        double dq, dqa[3], phi, r;
     155
     156
     157        for (k=0; k<N; k++){
     158                k6 = 6*k;
     159                k3 = 3*k;
     160                k2 = 2*k;
     161
     162                // Centroid coordinates
     163                x = centroids[k2]; y = centroids[k2+1];
     164
     165                // vertex coordinates
     166                // x0, y0, x1, y1, x2, y2 = X[k,:]
     167                x0 = vertex_coordinates[k6 + 0];
     168                y0 = vertex_coordinates[k6 + 1];
     169                x1 = vertex_coordinates[k6 + 2];
     170                y1 = vertex_coordinates[k6 + 3];
     171                x2 = vertex_coordinates[k6 + 4];
     172                y2 = vertex_coordinates[k6 + 5];
     173
     174                //Centroid Value
     175                qc = centroid_values[k];
     176
     177                // Extrapolate to Vertices
     178                vertex_values[k3+0] = centroid_values[k] + x_gradient[k]*(x0-x) + y_gradient[k]*(y0-y);
     179                vertex_values[k3+1] = centroid_values[k] + x_gradient[k]*(x1-x) + y_gradient[k]*(y1-y);
     180                vertex_values[k3+2] = centroid_values[k] + x_gradient[k]*(x2-x) + y_gradient[k]*(y2-y);
     181
     182                // Extrapolate to Edges (midpoints)
     183                edge_values[k3+0] = 0.5*(vertex_values[k3 + 1]+vertex_values[k3 + 2]);
     184                edge_values[k3+1] = 0.5*(vertex_values[k3 + 2]+vertex_values[k3 + 0]);
     185                edge_values[k3+2] = 0.5*(vertex_values[k3 + 0]+vertex_values[k3 + 1]);
     186
     187
     188                phi = 1.0;
     189
     190                for (i=0; i<3; i++) {
     191                    dq = edge_values[k3+i] - qc;      //Delta between edge and centroid values
     192                    dqa[i] = dq;                      //Save dq for use in updating vertex values
     193
     194                    n = neighbours[k3+i];
     195                    if (n >= 0) {
     196                        qn = centroid_values[n];     //Neighbour's centroid value
     197
     198                        qmin = min(qc, qn);
     199                        qmax = max(qc, qn);
     200
     201
     202                        r = 1.0;
     203     
     204                        if (dq > 0.0) r = (qmax - qc)/dq;
     205                        if (dq < 0.0) r = (qmin - qc)/dq;     
     206                   
     207                        phi = min( min(r*beta, 1.0), phi);   
     208                    }
     209                }
     210
     211
     212                //Update gradient, edge and vertex values using phi limiter
     213                x_gradient[k] = x_gradient[k]*phi;
     214                y_gradient[k] = y_gradient[k]*phi;
     215
     216                edge_values[k3+0] = qc + phi*dqa[0];
     217                edge_values[k3+1] = qc + phi*dqa[1];
     218                edge_values[k3+2] = qc + phi*dqa[2];
     219
     220
     221                vertex_values[k3+0] = edge_values[k3+1] + edge_values[k3+2] - edge_values[k3+0];
     222                vertex_values[k3+1] = edge_values[k3+2] + edge_values[k3+0] - edge_values[k3+1];
     223                vertex_values[k3+2] = edge_values[k3+0] + edge_values[k3+1] - edge_values[k3+2];
     224
     225        }
     226
     227        return 0;
     228
     229}
     230
     231
    137232
    138233
     
    542637
    543638
    544 /////////////////////////////////////////////////
    545 // Gateways to Python
     639//-----------------------------------------------------
     640// Python method Wrappers
     641//-----------------------------------------------------
     642
    546643PyObject *update(PyObject *self, PyObject *args) {
    547644  // FIXME (Ole): It would be great to turn this text into a Python DOC string
     
    9371034        Py_DECREF(domain);
    9381035
    939         //Allocate space for return vectors a and b (don't DECREF)
    940         //dimensions[0] = N;
    941         //a = (PyArrayObject *) PyArray_FromDims(1, dimensions, PyArray_DOUBLE);
    942         //b = (PyArrayObject *) PyArray_FromDims(1, dimensions, PyArray_DOUBLE);
    943 
    944         //FIXME: Odd that I couldn't use normal arrays
    945         //Allocate space for return vectors a and b (don't DECREF)
    946         //a = (double*) malloc(N * sizeof(double));
    947         //if (!a) return NULL;
    948         //b = (double*) malloc(N * sizeof(double));
    949         //if (!b) return NULL;
    950 
    951 
    952 /*      err = _compute_gradients(N, */
    953 /*                      (double*) centroids -> data, */
    954 /*                      (double*) centroid_values -> data, */
    955 /*                      (long*) number_of_boundaries -> data, */
    956 /*                      (long*) surrogate_neighbours -> data, */
    957 /*                      (double*) x_gradient -> data, */
    958 /*                      (double*) y_gradient -> data); */
    959 
    960 /*      if (err != 0) { */
    961 /*        PyErr_SetString(PyExc_RuntimeError, "Gradient could not be computed"); */
    962 /*        return NULL; */
    963 /*      } */
    964 
    9651036        err = _extrapolate_from_gradient(N,
    9661037                        (double*) centroids -> data,
     
    9931064
    9941065        return Py_BuildValue("");
     1066}
     1067
     1068
     1069PyObject *extrapolate_second_order_and_limit(PyObject *self, PyObject *args) {
     1070    /* Compute edge values using second order approximation and limit values
     1071       so that edge values are limited by the two corresponding centroid values
     1072       
     1073       Python Call:
     1074       extrapolate_second_order_and_limit(domain,quantity,beta)
     1075    */
     1076
     1077    PyObject *quantity, *domain;
     1078       
     1079    PyArrayObject
     1080        *domain_centroids,              //Coordinates at centroids
     1081        *domain_vertex_coordinates,     //Coordinates at vertices
     1082        *domain_number_of_boundaries,   //Number of boundaries for each triangle
     1083        *domain_surrogate_neighbours,   //True neighbours or - if one missing - self
     1084        *domain_neighbours,             //True neighbours, or if negative a link to boundary
     1085
     1086        *quantity_centroid_values,      //Values at centroids   
     1087        *quantity_vertex_values,        //Values at vertices
     1088        *quantity_edge_values,          //Values at edges
     1089        *quantity_x_gradient,           //x gradient
     1090        *quantity_y_gradient;           //y gradient
     1091   
     1092
     1093  // Local variables
     1094  int ntri;
     1095  double beta;
     1096  int err;
     1097   
     1098  // Convert Python arguments to C
     1099  if (!PyArg_ParseTuple(args, "OOd",
     1100                        &domain,
     1101                        &quantity,
     1102                        &beta)) {
     1103      PyErr_SetString(PyExc_RuntimeError,
     1104                      "quantity_ext.c: extrapolate_second_order_and_limit could not parse input");     
     1105      return NULL;
     1106  }
     1107
     1108       
     1109  // Get pertinent variables
     1110  domain_centroids              = get_consecutive_array(domain,   "centroid_coordinates");
     1111  domain_surrogate_neighbours   = get_consecutive_array(domain,   "surrogate_neighbours");
     1112  domain_number_of_boundaries   = get_consecutive_array(domain,   "number_of_boundaries");
     1113  domain_vertex_coordinates     = get_consecutive_array(domain,   "vertex_coordinates");
     1114  domain_neighbours             = get_consecutive_array(domain,   "neighbours");
     1115
     1116  quantity_centroid_values      = get_consecutive_array(quantity, "centroid_values");
     1117  quantity_vertex_values        = get_consecutive_array(quantity, "vertex_values");
     1118  quantity_edge_values          = get_consecutive_array(quantity, "edge_values");
     1119  quantity_x_gradient           = get_consecutive_array(quantity, "x_gradient");
     1120  quantity_y_gradient           = get_consecutive_array(quantity, "y_gradient");
     1121
     1122  ntri = quantity_centroid_values -> dimensions[0];
     1123
     1124
     1125
     1126  err = _compute_gradients(ntri,
     1127                           (double*) domain_centroids -> data,
     1128                           (double*) quantity_centroid_values -> data,
     1129                           (long*)   domain_number_of_boundaries -> data,
     1130                           (long*)   domain_surrogate_neighbours -> data,
     1131                           (double*) quantity_x_gradient -> data,
     1132                           (double*) quantity_y_gradient -> data);
     1133
     1134  if (err != 0) {
     1135      PyErr_SetString(PyExc_RuntimeError,
     1136                          "quantity_ext.c: Internal function _compute_gradient failed");
     1137      return NULL;
     1138  }
     1139
     1140
     1141  err = _extrapolate_and_limit_from_gradient(ntri, beta,
     1142                                             (double*) domain_centroids -> data,
     1143                                             (long*)   domain_neighbours -> data,
     1144                                             (double*) quantity_centroid_values -> data,
     1145                                             (double*) domain_vertex_coordinates -> data,
     1146                                             (double*) quantity_vertex_values -> data,
     1147                                             (double*) quantity_edge_values -> data,
     1148                                             (double*) quantity_x_gradient -> data,
     1149                                             (double*) quantity_y_gradient -> data);
     1150
     1151  if (err != 0) {
     1152      PyErr_SetString(PyExc_RuntimeError,
     1153                          "quantity_ext.c: Internal function _extrapolate_and_limit_from_gradient failed");
     1154      return NULL;
     1155  }
     1156
     1157
     1158  // Release
     1159  Py_DECREF(domain_centroids);
     1160  Py_DECREF(domain_surrogate_neighbours);
     1161  Py_DECREF(domain_number_of_boundaries);
     1162  Py_DECREF(domain_vertex_coordinates);
     1163
     1164  Py_DECREF(quantity_centroid_values);
     1165  Py_DECREF(quantity_vertex_values);
     1166  Py_DECREF(quantity_edge_values);
     1167  Py_DECREF(quantity_x_gradient);
     1168  Py_DECREF(quantity_y_gradient);
     1169
     1170  return Py_BuildValue("");
    9951171}
    9961172
     
    10461222        Py_DECREF(domain);
    10471223
    1048         //Allocate space for return vectors a and b (don't DECREF)
    1049         //dimensions[0] = N;
    1050         //a = (PyArrayObject *) PyArray_FromDims(1, dimensions, PyArray_DOUBLE);
    1051         //b = (PyArrayObject *) PyArray_FromDims(1, dimensions, PyArray_DOUBLE);
    1052 
    1053         //FIXME: Odd that I couldn't use normal arrays
    1054         //Allocate space for return vectors a and b (don't DECREF)
    1055         //a = (double*) malloc(N * sizeof(double));
    1056         //if (!a) return NULL;
    1057         //b = (double*) malloc(N * sizeof(double));
    1058         //if (!b) return NULL;
    1059 
    10601224
    10611225        err = _compute_gradients(N,
     
    10711235          return NULL;
    10721236        }
    1073 
    1074 /*      err = _extrapolate(N, */
    1075 /*                      (double*) centroids -> data, */
    1076 /*                      (double*) centroid_values -> data, */
    1077 /*                      (double*) vertex_coordinates -> data, */
    1078 /*                      (double*) vertex_values -> data, */
    1079 /*                      (double*) edge_values -> data, */
    1080 /*                      (double*) x_gradient -> data, */
    1081 /*                      (double*) y_gradient -> data); */
    1082 
    1083 
    1084 /*      if (err != 0) { */
    1085 /*        PyErr_SetString(PyExc_RuntimeError, */
    1086 /*                        "Internal function _extrapolate failed"); */
    1087 /*        return NULL; */
    1088 /*      } */
    10891237
    10901238
     
    15581706        {"extrapolate_from_gradient", extrapolate_from_gradient,
    15591707                METH_VARARGS, "Print out"},
     1708        {"extrapolate_second_order_and_limit", extrapolate_second_order_and_limit,
     1709                METH_VARARGS, "Print out"},
    15601710        {"interpolate_from_vertices_to_edges",
    15611711                interpolate_from_vertices_to_edges,
Note: See TracChangeset for help on using the changeset viewer.