1 | // Python - C extension for quantity 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 quantity.py |
---|
8 | // |
---|
9 | // |
---|
10 | // Ole Nielsen, GA 2004 |
---|
11 | |
---|
12 | #include "Python.h" |
---|
13 | #include "Numeric/arrayobject.h" |
---|
14 | #include "math.h" |
---|
15 | |
---|
16 | |
---|
17 | //FIXME: Should live in util_ext.c |
---|
18 | double max(double x, double y) { |
---|
19 | //Return maximum of two doubles |
---|
20 | |
---|
21 | if (x > y) return x; |
---|
22 | else return y; |
---|
23 | } |
---|
24 | |
---|
25 | double 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 | |
---|
33 | void _limit(int N, double beta, double* qc, double* qv, double* qmin, double* qmax) { |
---|
34 | |
---|
35 | int k, i, ki; |
---|
36 | double dq, phi, r; |
---|
37 | |
---|
38 | for (k=0; k<N; k++) { |
---|
39 | |
---|
40 | //Find the gradient limiter (phi) across vertices |
---|
41 | phi = 1.0; |
---|
42 | for (i=0; i<3; i++) { |
---|
43 | ki = k*3+i; |
---|
44 | r = 1.0; |
---|
45 | |
---|
46 | dq = qv[ki] - qc[k]; //Delta between vertex and centroid values |
---|
47 | |
---|
48 | if (dq > 0.0) r = (qmax[k] - qc[k])/dq; |
---|
49 | if (dq < 0.0) r = (qmin[k] - qc[k])/dq; |
---|
50 | |
---|
51 | phi = min( min(r*beta, 1.0), phi); |
---|
52 | } |
---|
53 | //Then update using phi limiter |
---|
54 | for (i=0; i<3; i++) { |
---|
55 | qv[ki] = qc[k] + phi*(qv[ki] - qc[k]); //FIXME: Could precompute dq (3 elements) |
---|
56 | } |
---|
57 | } |
---|
58 | |
---|
59 | |
---|
60 | /* |
---|
61 | #Diffences between centroids and maxima/minima |
---|
62 | dqmax = qmax - qc |
---|
63 | dqmin = qmin - qc |
---|
64 | |
---|
65 | #Deltas between vertex and centroid values |
---|
66 | dq = zeros(qv.shape, Float) |
---|
67 | for i in range(3): |
---|
68 | dq[:,i] = qv[:,i] - qc |
---|
69 | |
---|
70 | #Phi limiter |
---|
71 | for k in range(N): |
---|
72 | |
---|
73 | #Find the gradient limiter (phi) across vertices |
---|
74 | phi = 1.0 |
---|
75 | for i in range(3): |
---|
76 | r = 1.0 |
---|
77 | if (dq[k,i] > 0): r = dqmax[k]/dq[k,i] |
---|
78 | if (dq[k,i] < 0): r = dqmin[k]/dq[k,i] |
---|
79 | |
---|
80 | phi = min( min(r*beta, 1), phi ) |
---|
81 | |
---|
82 | #Then update using phi limiter |
---|
83 | for i in range(3): |
---|
84 | qv[k,i] = qc[k] + phi*dq[k,i] |
---|
85 | |
---|
86 | */ |
---|
87 | |
---|
88 | } |
---|
89 | |
---|
90 | // Gateway to Python |
---|
91 | //FIXME: DOES NOT WORK YET |
---|
92 | PyObject *limit(PyObject *self, PyObject *args) { |
---|
93 | |
---|
94 | PyObject *quantity; |
---|
95 | |
---|
96 | PyObject *Tmp; |
---|
97 | |
---|
98 | PyArrayObject |
---|
99 | *qv, //Conserved quantities at vertices |
---|
100 | *qc, //Conserved quantities at centroids |
---|
101 | *neighbours; |
---|
102 | |
---|
103 | int k, i, n, N; |
---|
104 | double beta; //Safety factor |
---|
105 | double *qmin, *qmax, qn; |
---|
106 | |
---|
107 | // Convert Python arguments to C |
---|
108 | if (!PyArg_ParseTuple(args, "O", &quantity)) |
---|
109 | return NULL; |
---|
110 | |
---|
111 | //Get safety factor beta |
---|
112 | Tmp = PyObject_GetAttrString(quantity, "beta"); |
---|
113 | beta = PyFloat_AsDouble(Tmp); |
---|
114 | Py_DECREF(Tmp); |
---|
115 | |
---|
116 | |
---|
117 | qc = (PyArrayObject*) PyObject_GetAttrString(quantity, "centroid_values"); |
---|
118 | qv = (PyArrayObject*) PyObject_GetAttrString(quantity, "vertex_values"); |
---|
119 | |
---|
120 | Tmp = PyObject_GetAttrString(quantity, "domain"); |
---|
121 | neighbours = (PyArrayObject*) PyObject_GetAttrString(Tmp, "neighbours"); |
---|
122 | Py_DECREF(Tmp); |
---|
123 | N = qc -> dimensions[0]; |
---|
124 | |
---|
125 | |
---|
126 | //Find min and max of this and neighbour's centroid values |
---|
127 | qmin = malloc(N * sizeof(double)); |
---|
128 | qmax = malloc(N * sizeof(double)); |
---|
129 | for (k=0; k<N; k++) { |
---|
130 | qmax[k] = qmin[k] = ((double*) qc -> data)[k]; |
---|
131 | for (i=0; i<3; i++) { |
---|
132 | n = ((int*) neighbours -> data)[k*3+i]; |
---|
133 | if (n >= 0) { |
---|
134 | qn = ((double*) qc -> data)[n]; //Neighbour's centroid value |
---|
135 | |
---|
136 | qmin[k] = min(qmin[k], qn); |
---|
137 | qmax[k] = max(qmax[k], qn); |
---|
138 | } |
---|
139 | } |
---|
140 | } |
---|
141 | |
---|
142 | // Call underlying routine |
---|
143 | //_limit(N, beta, (double*) qc -> data, (double*) qv -> data, qmin, qmax); |
---|
144 | |
---|
145 | free(qmin); |
---|
146 | free(qmax); |
---|
147 | return Py_BuildValue(""); |
---|
148 | } |
---|
149 | |
---|
150 | |
---|
151 | |
---|
152 | // Method table for python module |
---|
153 | static struct PyMethodDef MethodTable[] = { |
---|
154 | {"limit", limit, METH_VARARGS, "Print out"}, |
---|
155 | {NULL, NULL, 0, NULL} /* sentinel */ |
---|
156 | }; |
---|
157 | |
---|
158 | // Module initialisation |
---|
159 | void initquantity_ext(void){ |
---|
160 | Py_InitModule("quantity_ext", MethodTable); |
---|
161 | |
---|
162 | import_array(); //Necessary for handling of NumPY structures |
---|
163 | } |
---|
164 | |
---|