source: trunk/anuga_work/anuga_cuda/src/anuga_HMPP/util_ext.h @ 9329

Last change on this file since 9329 was 9017, checked in by steve, 12 years ago

Adding in Zhe (John) Weng's anuga_cuda code as obtained from googlecode https://code.google.com/p/anuga-cuda

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
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.