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

Last change on this file since 9641 was 9641, checked in by steve, 9 years ago

Finding MICROSOFT compiler bugs

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