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

Last change on this file since 8758 was 8377, checked in by steve, 13 years ago

Some changes to allow different compute fluxes

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