source: trunk/anuga_core/source/anuga/utilities/util_ext.h @ 7886

Last change on this file since 7886 was 7886, checked in by steve, 14 years ago

Copied sudi's directory

File size: 8.5 KB
Line 
1// Python - C extension for finite_volumes util module.
2//
3// To compile (Python2.3):
4//  gcc -c util_ext.c -I/usr/include/python2.3 -o util_ext.o -Wall -O
5//  gcc -shared util_ext.o  -o util_ext.so     
6//
7// See the module util.py
8//
9//
10// Ole Nielsen, GA 2004
11       
12#include "Python.h"     
13#include "numpy/arrayobject.h"
14#include "math.h"
15
16
17double max(double x, double y) { 
18  //Return maximum of two doubles
19 
20  if (x > y) return x;
21  else return y;
22}
23
24
25double min(double x, double y) { 
26  //Return minimum of two doubles
27 
28  if (x < y) return x;
29  else return y;
30}
31
32
33double sign(double x) {
34  //Return sign of a double
35
36  if (x>0.0) return 1.0;
37  else if (x<0.0) return -1.0;
38  else return 0.0;
39}
40
41int _gradient(double x0, double y0, 
42              double x1, double y1, 
43              double x2, double y2, 
44              double q0, double q1, double q2, 
45              double *a, double *b) {
46             
47  /*Compute gradient (a,b) based on three points (x0,y0), (x1,y1) and (x2,y2)
48  with values q0, q1 and q2.
49 
50  Extrapolation formula (q0 is selected as an arbitrary origin)
51    q(x,y) = q0 + a*(x-x0) + b*(y-y0)                    (1)
52 
53  Substituting the known values for q1 and q2 into (1) yield the
54  equations for a and b
55 
56      q1-q0 = a*(x1-x0) + b*(y1-y0)                      (2)
57      q2-q0 = a*(x2-x0) + b*(y2-y0)                      (3)     
58     
59  or in matrix form
60 
61  /               \  /   \   /       \ 
62  |  x1-x0  y1-y0 |  | a |   | q1-q0 |
63  |               |  |   | = |       |
64  |  x2-x0  y2-y0 |  | b |   | q2-q0 |
65  \               /  \   /   \       /
66   
67  which is solved using the standard determinant technique   
68     
69  */
70             
71
72  double det;
73 
74  det = (y2-y0)*(x1-x0) - (y1-y0)*(x2-x0);
75
76  *a = (y2-y0)*(q1-q0) - (y1-y0)*(q2-q0);
77  *a /= det;
78
79  *b = (x1-x0)*(q2-q0) - (x2-x0)*(q1-q0);
80  *b /= det;
81
82  return 0;
83}
84
85
86int _gradient2(double x0, double y0, 
87               double x1, double y1, 
88               double q0, double q1, 
89               double *a, double *b) {
90  /*Compute gradient (a,b) between two points (x0,y0) and (x1,y1)
91  with values q0 and q1 such that the plane is constant in the direction
92  orthogonal to (x1-x0, y1-y0).
93 
94  Extrapolation formula
95    q(x,y) = q0 + a*(x-x0) + b*(y-y0)                    (1)
96 
97  Substituting the known values for q1 into (1) yields an
98  under determined  equation for a and b
99      q1-q0 = a*(x1-x0) + b*(y1-y0)                      (2)
100     
101     
102  Now add the additional requirement that the gradient in the direction
103  orthogonal to (x1-x0, y1-y0) should be zero. The orthogonal direction
104  is given by the vector (y0-y1, x1-x0).
105 
106  Define the point (x2, y2) = (x0 + y0-y1, y0 + x1-x0) on the orthognal line.
107  Then we know that the corresponding value q2 should be equal to q0 in order
108  to obtain the zero gradient, hence applying (1) again   
109      q0 = q2 = q(x2, y2) = q0 + a*(x2-x0) + b*(y2-y0)
110                          = q0 + a*(x0 + y0-y1-x0) + b*(y0 + x1-x0 - y0)
111                          = q0 + a*(y0-y1) + b*(x1-x0)
112                         
113  leads to the orthogonality constraint
114     a*(y0-y1) + b*(x1-x0) = 0                           (3)
115     
116  which closes the system and yields
117 
118  /               \  /   \   /       \ 
119  |  x1-x0  y1-y0 |  | a |   | q1-q0 |
120  |               |  |   | = |       |
121  |  y0-y1  x1-x0 |  | b |   |   0   |
122  \               /  \   /   \       /
123   
124  which is solved using the standard determinant technique   
125     
126  */
127
128  double det, xx, yy, qq;
129 
130  xx = x1-x0;
131  yy = y1-y0;
132  qq = q1-q0;
133   
134  det = xx*xx + yy*yy;  //FIXME  catch det == 0
135  *a = xx*qq/det;
136  *b = yy*qq/det;
137       
138  return 0;
139}
140
141
142void _limit_old(int N, double beta, double* qc, double* qv, 
143            double* qmin, double* qmax) { 
144
145  //N are the number of elements
146  int k, i, k3;
147  double dq, dqa[3], phi, r;
148 
149  //printf("INSIDE\n");
150  for (k=0; k<N; k++) {
151    k3 = k*3;
152   
153    //Find the gradient limiter (phi) across vertices 
154    phi = 1.0;
155    for (i=0; i<3; i++) {   
156      r = 1.0;
157     
158      dq = qv[k3+i] - qc[k];    //Delta between vertex and centroid values
159      dqa[i] = dq;              //Save dq for use in the next loop
160     
161      if (dq > 0.0) r = (qmax[k] - qc[k])/dq;
162      if (dq < 0.0) r = (qmin[k] - qc[k])/dq;     
163 
164 
165      phi = min( min(r*beta, 1.0), phi);   
166    }
167   
168    //Then update using phi limiter
169    for (i=0; i<3; i++) {   
170      qv[k3+i] = qc[k] + phi*dqa[i];
171    }
172  }
173}
174
175
176void  print_double_array(char* name, double* array, int n, int m){
177
178    int k,i,km;
179
180    printf("%s = [",name);
181    for (k=0; k<n; k++){
182        km = m*k;
183        printf("[");
184        for (i=0; i<m ; i++){
185            printf("%g ",array[km+i]);
186        }
187        if (k==(n-1))
188            printf("]");
189        else
190            printf("]\n");
191    }
192    printf("]\n");
193}
194
195void  print_int_array(char* name, int* array, int n, int m){
196
197    int k,i,km;
198
199    printf("%s = [",name);
200    for (k=0; k<n; k++){
201        km = m*k;
202        printf("[");
203        for (i=0; i<m ; i++){
204            printf("%i ",array[km+i]);
205        }
206        if (k==(n-1))
207            printf("]");
208        else
209            printf("]\n");
210    }
211    printf("]\n");
212}
213
214
215void  print_long_array(char* name, long* array, int n, int m){
216
217    int k,i,km;
218
219    printf("%s = [",name);
220    for (k=0; k<n; k++){
221        km = m*k;
222        printf("[");
223        for (i=0; i<m ; i++){
224          printf("%i ",(int) array[km+i]);
225        }
226        if (k==(n-1))
227            printf("]");
228        else
229            printf("]\n");
230    }
231    printf("]\n");
232}
233
234void print_numeric_array(PyArrayObject *x) { 
235  int i, j;
236  for (i=0; i<x->dimensions[0]; i++) { 
237    for (j=0; j<x->dimensions[1]; j++) {
238      printf("%f ", *(double*) (x->data + i*x->strides[0] + j*x->strides[1]));
239    }
240    printf("\n"); 
241  }
242  printf("\n");   
243}
244
245void print_numeric_vector(PyArrayObject *x) { 
246  int i;
247  for (i=0; i<x->dimensions[0]; i++) {
248    printf("%f ", *(double*) (x->data + i*x->strides[0])); 
249  }
250  printf("\n"); 
251}
252
253PyArrayObject *get_consecutive_array(PyObject *O, char *name) {
254  PyArrayObject *A, *B;
255 
256
257  //Get array object from attribute
258 
259  /*
260  //FIXME: THE TEST DOESN't WORK
261  printf("Err = %d\n", PyObject_HasAttrString(O, name));
262  if (PyObject_HasAttrString(O, name) == 1) {
263    B = (PyArrayObject*) PyObject_GetAttrString(O, name);
264    if (!B) return NULL;
265  } else {
266    return NULL;
267    }
268  */
269   
270  B = (PyArrayObject*) PyObject_GetAttrString(O, name);
271
272  //printf("B = %p\n",(void*)B);
273  if (!B) {
274    printf("util_ext.h: get_consecutive_array could not obtain python object");
275    printf(" %s\n",name);
276    fflush(stdout);
277    PyErr_SetString(PyExc_RuntimeError, "util_ext.h: get_consecutive_array could not obtain python object");
278    return NULL;
279  }     
280 
281  //Convert to consecutive array
282  A = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*) B, 
283                                                    B -> descr -> type, 0, 0);
284 
285  Py_DECREF(B); //FIXME: Is this really needed??
286 
287  if (!A) {
288    printf("util_ext.h: get_consecutive_array could not obtain array object");
289    printf(" %s \n",name);
290    fflush(stdout);
291    PyErr_SetString(PyExc_RuntimeError, "util_ext.h: get_consecutive_array could not obtain array");
292    return NULL;
293  }
294
295
296  return A;
297}
298
299double get_python_double(PyObject *O, char *name) {
300  PyObject *TObject;
301  #define BUFFER_SIZE 80
302  char buf[BUFFER_SIZE];
303  double tmp;
304  int n;
305 
306
307  //Get double from attribute
308  TObject = PyObject_GetAttrString(O, name);
309  if (!TObject) {
310        n =  snprintf(buf, BUFFER_SIZE, "util_ext.h: get_python_double could not obtain double %s.\n", name);
311        //printf("name = %s",name);
312    PyErr_SetString(PyExc_RuntimeError, buf);
313
314    return 0.0;
315  } 
316 
317  tmp = PyFloat_AsDouble(TObject);
318 
319  Py_DECREF(TObject);
320 
321  return tmp;
322}
323
324
325
326
327int get_python_integer(PyObject *O, char *name) {
328  PyObject *TObject;
329  #define BUFFER_SIZE 80
330  char buf[BUFFER_SIZE];
331  long tmp;
332  int n;
333 
334
335  //Get double from attribute
336  TObject = PyObject_GetAttrString(O, name);
337  if (!TObject) {
338        n =  snprintf(buf, BUFFER_SIZE, "util_ext.h: get_python_integer could not obtain double %s.\n", name);
339        //printf("name = %s",name);
340    PyErr_SetString(PyExc_RuntimeError, buf);
341    return 0;
342  } 
343 
344  tmp = PyInt_AsLong(TObject);
345 
346  Py_DECREF(TObject);
347 
348  return tmp;
349}
350
351
352PyObject *get_python_object(PyObject *O, char *name) {
353  PyObject *Oout;
354
355  Oout = PyObject_GetAttrString(O, name);
356  if (!Oout) {
357    PyErr_SetString(PyExc_RuntimeError, "util_ext.h: get_python_object could not obtain object");
358    return NULL;
359  }
360
361  return Oout;
362
363}
364
365
366// check that numpy array objects are C contiguous memory
367#define CHECK_C_CONTIG(varname) if (!PyArray_ISCONTIGUOUS(varname)) { \
368                                    char msg[1024]; \
369                                    sprintf(msg, \
370                                            "%s(): file %s, line %d: " \
371                                            "'%s' object is not C contiguous memory", \
372                                             __func__, __FILE__, __LINE__, #varname); \
373                                    PyErr_SetString(PyExc_RuntimeError, msg); \
374                                    return NULL; \
375                                }
Note: See TracBrowser for help on using the repository browser.