source: inundation/ga/storm_surge/pyvolution/util_ext.c @ 195

Last change on this file since 195 was 195, checked in by ole, 20 years ago
File size: 5.4 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 "Numeric/arrayobject.h"
14#include "math.h"
15
16
17int _gradient(double x0, double y0, 
18              double x1, double y1, 
19              double x2, double y2, 
20              double *q0, double *q1, double *q2, 
21              double *a, double *b, 
22              int N) {
23
24  double det;
25  int i;
26 
27  det = (y2-y0)*(x1-x0) - (y1-y0)*(x2-x0);
28 
29  for (i=0; i<N; i++) {
30    a[i] = (y2-y0)*(q1[i]-q0[i]) - (y1-y0)*(q2[i]-q0[i]);
31    a[i] /= det;
32
33    b[i] = (x1-x0)*(q2[i]-q0[i]) - (x2-x0)*(q1[i]-q0[i]);
34    b[i] /= det;
35  } 
36
37  return 0;
38}
39
40
41
42// Computational function for rotation
43int _rotate(double *q, double *r, double *normal, int direction) {
44  /*Rotate the momentum component q (q[1], q[2])
45    from x,y coordinates to coordinates based on normal vector.
46   
47    To rotate in opposite direction, call rotate with direction=1
48    Result is returned in r
49   
50    q and r are assumed to have three components each*/
51
52
53  double n0, n1, q1, q2;
54 
55  //Determine normal and direction
56  n0 = normal[0];
57  if (direction == 1) {
58    n1 = normal[1];   
59  } else {
60    n1 = -normal[1];
61  }
62
63  //Shorthands
64  q1 = q[1];  //uh momentum
65  q2 = q[2];  //vh momentum
66
67  //Rotate
68  r[0] = q[0];
69  r[1] = n0*q1 + n1*q2;
70  r[2] = n0*q2 - n1*q1;
71
72  return 0;
73} 
74
75
76
77// Gateway to Python
78PyObject *gradient(PyObject *self, PyObject *args) {
79  //
80  // a,b = gradient(x0, y0, x1, y1, x2, y2, q0, q1, q2)
81  //
82 
83  double x0, y0, x1, y1, x2, y2;
84  PyObject *Q0, *Q1, *Q2, *result;
85  PyArrayObject *q0, *q1, *q2, *a, *b;
86  int dimensions[1];
87  int N;
88
89 
90  // Convert Python arguments to C 
91  if (!PyArg_ParseTuple(args, "ddddddOOO", &x0, &y0, &x1, &y1, &x2, &y2,
92                        &Q0, &Q1, &Q2)) 
93    return NULL;
94
95  //Input check
96  if PyArray_Check(Q0) {
97    q0 = (PyArrayObject *) 
98      PyArray_ContiguousFromObject(Q0, PyArray_DOUBLE, 0, 0);
99  } else {
100    PyErr_SetString(PyExc_TypeError, "q0 must be a numeric array");
101    return NULL;
102  }
103   
104  if PyArray_Check(Q1) {
105    q1 = (PyArrayObject *) 
106      PyArray_ContiguousFromObject(Q1, PyArray_DOUBLE, 0, 0);
107  } else {
108    PyErr_SetString(PyExc_TypeError, "q1 must be a numeric array");
109    return NULL;
110  }
111 
112  if PyArray_Check(Q2) {
113    q2 = (PyArrayObject *) 
114      PyArray_ContiguousFromObject(Q2, PyArray_DOUBLE, 0, 0);
115  } else {
116    PyErr_SetString(PyExc_TypeError, "q2 must be a numeric array");
117    return NULL;
118  } 
119   
120  //Allocate space for return vectors a and b 
121 
122  N = q0 -> dimensions[0];
123  dimensions[0] = N;
124  a = (PyArrayObject *) PyArray_FromDims(1, dimensions, PyArray_DOUBLE);
125  b = (PyArrayObject *) PyArray_FromDims(1, dimensions, PyArray_DOUBLE); 
126
127 
128  // Call underlying routine
129  _gradient(x0, y0, x1, y1, x2, y2, 
130            (double *) q0 -> data, 
131            (double *) q1 -> data, 
132            (double *) q2 -> data,
133            (double *) a -> data, 
134            (double *) b-> data, N);
135
136  Py_DECREF(q0);
137  Py_DECREF(q1);
138  Py_DECREF(q2);   
139             
140  // Return arrays a and b
141  result = Py_BuildValue("OO", a, b);
142  Py_DECREF(a);
143  Py_DECREF(b); 
144  return result;
145}
146
147
148// Gateway to Python
149PyObject *rotate(PyObject *self, PyObject *args, PyObject *kwargs) {
150  //
151  // r = rotate(q, normal, direction=0)
152  //
153  // Where q is assumed to be a Float numeric array of length 3 and
154  // normal a Float numeric array of length 2.
155
156  //FIXME: Input checks and unit tests
157 
158  PyObject *Q, *Normal;
159  PyArrayObject *q, *r, *normal;
160 
161  static char *argnames[] = {"q", "normal", "direction", NULL};
162  int dimensions[1];
163  int N, direction=0;
164
165  // Convert Python arguments to C 
166  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i", argnames, 
167                                   &Q, &Normal, &direction)) 
168    return NULL; 
169
170  //Input checks (convert sequenced into numeric arrays)
171 
172  q = (PyArrayObject *) 
173    PyArray_ContiguousFromObject(Q, PyArray_DOUBLE, 0, 0);
174  normal = (PyArrayObject *) 
175    PyArray_ContiguousFromObject(Normal, PyArray_DOUBLE, 0, 0);
176 
177  //Allocate space for return vector r (don't DECREF)
178  N = q -> dimensions[0];
179  dimensions[0] = N;
180  r = (PyArrayObject *) PyArray_FromDims(1, dimensions, PyArray_DOUBLE);
181
182  //Rotate
183  _rotate((double *) q -> data,
184          (double *) r -> data,
185          (double *) normal -> data,     
186          direction);     
187
188  //Build result and DECREF r - returning r directly causes memory leak
189  //result = Py_BuildValue("O", r);       
190  //Py_DECREF(r);
191 
192  //return result;
193  return PyArray_Return(r);
194}   
195
196
197// Method table for python module
198//static struct PyMethodDef MethodTable[] = {
199//  {"gradient", gradient, METH_VARARGS}, 
200//  {NULL, NULL}
201//};
202
203
204
205// Method table for python module
206static struct PyMethodDef MethodTable[] = {
207  /* The cast of the function is necessary since PyCFunction values
208   * only take two PyObject* parameters, and rotate() takes
209   * three.
210   */
211 
212  {"rotate", (PyCFunction)rotate, METH_VARARGS | METH_KEYWORDS, "Print out"}, 
213  {"gradient", gradient, METH_VARARGS, "Print out"},   
214  {NULL, NULL, 0, NULL}   /* sentinel */
215};
216
217
218
219// Module initialisation   
220void initutil_ext(void){
221  Py_InitModule("util_ext", MethodTable);
222 
223  import_array();     //Necessary for handling of NumPY structures 
224}
225
Note: See TracBrowser for help on using the repository browser.