source: branches/numpy/anuga/mesh_engine/mesh_engine_c_layer.c

Last change on this file was 6780, checked in by rwilson, 15 years ago

Changes to make legacy Numeric API work in numpy.

File size: 12.8 KB
Line 
1/* this appears to be necessary to run on Linux */
2
3#undef _STDLIB_H_
4#define _STDLIB_H_
5
6
7/*
8
9    This code interfaces pmesh directly with "triangle", a general       
10    purpose triangulation code. In doing so, Python numeric data structures
11     are passed to C for  use by "triangle" and the results are then         
12    converted back. This was accomplished using the Python/C API.           
13                                                                           
14    I. Arrays of points,edges,holes, and regions must normally be
15     created for proper triangulation. However, if there are no holes,
16     the  hole list need not be specified (however, a
17     measure of control over the shape of the convex hull is lost;
18     triangle decides).
19     
20     points array: [(x1,y1),(x2,y2),...] ( doubles)                 
21     edge array: [(Ea,Eb),(Ef,Eg),...] ( integers)                   
22     hole array: [(x1,y1),...]( doubles, one inside each hole region)
23     region array: [ (x1,y1,index,area),...] ( doubles)               
24     pointattribute array:[ (a1,a2..),...] (doubles)
25     mode: String - the commands sent to triangle
26         
27     This is all that is needed to accomplish an intial triangulation.       
28     A dictionary of the Triangle output is returned.
29           
30     I thought this function was leaking. That the returned data
31     structure didn't get garbage collected.  I decided this using 
32     gc.get_objects() and seeing the dic still hanging around.
33     I'm not so sure this means its leaking.  Check by looking at
34     the overall memory use.  Anyhow, I delete the lists that are
35     returned in the dic structre after they are used now, in alpha
36     shape and mesh_engine.
37
38         
39     Precondition
40     End list in the pointattributelist has to have the same length
41     
42                                                 */
43
44
45#ifdef SINGLE 
46#define REAL float
47#else 
48#define REAL double
49#endif
50
51#include "triangle.h"
52
53#ifndef _STDLIB_H_
54#ifndef _WIN32
55extern "C" void *malloc(); 
56extern "C" void free(); 
57#endif
58#endif 
59
60#include "Python.h"
61
62#include "util_ext.h"
63#include "numpy_shim.h"
64
65
66//#define PY_ARRAY_UNIQUE_SYMBOL API_YEAH
67
68#define PY_ARRAY_UNIQUE_SYMBOL API_YEAH
69//#define NO_IMPORT_ARRAY
70#include "numpy/arrayobject.h"
71#include <sys/types.h>
72
73 static PyObject *triang_genMesh(PyObject *self, PyObject *args){
74     
75  /* Mesh generation routine
76     pre-conditions:
77     mode must have a 'z' switch, to avoid segmentation faults
78     
79     shallow_water_ext.c gravity function
80  */
81   
82  struct triangulateio in,out;
83
84  struct triangulateio in_test;
85 
86  PyArrayObject *pointlist;
87  PyArrayObject *seglist;
88  PyArrayObject *holelist;
89  PyArrayObject *regionlist;
90  PyObject *mode;
91  PyArrayObject *pointattributelist;
92  PyArrayObject *segmarkerlist;
93  PyArrayObject *test;
94 
95 
96  PyArrayObject *gentrianglelist;
97  PyArrayObject *genpointlist;
98  PyArrayObject *genseglist;
99  PyArrayObject *genpointmarkerlist;
100  PyArrayObject *genpointattributelist;
101  PyArrayObject *gentriangleattributelist;
102  PyArrayObject *gensegmentlist;
103  PyArrayObject *gensegmentmarkerlist;
104  PyArrayObject *genneighborlist;
105  PyObject *R;
106
107  int dimensions[2];
108   
109  REAL Attr;
110  int i, j, iatt, n, write_here,N;
111  int a,b,c;
112  int marker;
113  int tuplesize;
114   
115  int index = 0;
116  double x,y;
117  PyObject *elems;
118  PyObject *pair;
119     
120  char *mod;
121   
122  if(!PyArg_ParseTuple(args,(char *)"OOOOOOO",&pointlist,&seglist,&holelist,&regionlist,&pointattributelist,&segmarkerlist,&mode)){
123    return NULL;
124  }
125
126  // check that numpy array objects arrays are C contiguous memory
127  CHECK_C_CONTIG(pointlist);
128  CHECK_C_CONTIG(seglist);
129  CHECK_C_CONTIG(holelist);
130  CHECK_C_CONTIG(regionlist);
131  CHECK_C_CONTIG(pointattributelist);
132  CHECK_C_CONTIG(segmarkerlist);
133 
134  /* Initialize  points */
135  in.numberofpoints =  pointlist-> dimensions[0]; 
136  in.pointlist = (double *) pointlist -> data;
137  in.pointmarkerlist = (int *)NULL; 
138 
139  /* Initialize and fill up region list */
140  in.numberofregions = regionlist-> dimensions[0]; 
141 
142  in.regionlist = (double *) regionlist -> data;
143 
144  /*Initialize segments and segment markers */
145  in.numberofsegments = seglist -> dimensions[0]; 
146  in.segmentlist = (int *) seglist -> data;
147  in.segmentmarkerlist = (int *) segmarkerlist -> data;
148  //in.segmentmarkerlist = (int *) NULL;
149 
150  /*Initialize triangles */
151  in.numberoftriangles = 0;
152  in.trianglelist = (int *)NULL;
153  in.numberoftriangleattributes = 0; 
154  in.triangleattributelist  = (REAL *)NULL; 
155  in.trianglearealist  = (REAL *)NULL; 
156  in.neighborlist = (int *)NULL;
157  in.numberofcorners = 0;
158     
159  /*Initialize holes */
160  in.numberofholes = holelist  -> dimensions[0];
161  if (in.numberofholes != 0) {
162    in.holelist =  (double *) holelist -> data; 
163  } else {
164    in.holelist = (REAL *)NULL;
165  }     
166 
167  /* Point attribute list */
168   /*printf ("in.pointattributelist -> dimensions[0] %i\n", pointattributelist -> dimensions[0]);
169  printf ("in.pointattributelist -> dimensions[1] %i\n", pointattributelist -> dimensions[1]); */
170  if (0 == pointattributelist -> dimensions[0]) {
171    in.numberofpointattributes = 0;
172    in.pointattributelist =  (double *) NULL;
173  } else {
174    if (0 == pointattributelist -> dimensions[1]) {
175    in.numberofpointattributes = 0;
176    in.pointattributelist =  (double *) NULL;
177    } else {
178      in.numberofpointattributes = pointattributelist -> dimensions[1];
179      in.pointattributelist =  (double *) pointattributelist -> data;
180    }
181  }
182   
183  /* DEBUGGING
184  printf(" ***  hello world\n" ); 
185 
186  printf ("numberofpoints %i\n", in.numberofpoints);
187  printf ("numberofpointattributes %i\n", in.numberofpointattributes);
188  for(i = 0; i < in.numberofpoints; i++) {
189    printf("(%f,%f)\n",in.pointlist[i* 2+ 0],in.pointlist[i* 2+ 1]);
190    for(j = 0; j < in.numberofpointattributes; j++) {
191      printf("point att (%f)\n",in.pointattributelist[i* in.numberofpointattributes + j]);
192    }
193   
194  }
195     
196  printf ("numberofregions %i\n", in.numberofregions);
197  for(i = 0; i < in.numberofregions; i++) {
198    printf("(%f,%f)  ",in.regionlist[i* 4+ 0],in.regionlist[i* 4+ 1]);
199    printf("index %f Area %f\n",in.regionlist[i* 4+ 2],in.regionlist[i* 4+ 3]);
200  }
201   
202  printf ("numberofsegments %i\n", in.numberofsegments);
203  for(i = 0; i < in.numberofsegments; i++) {
204      printf("(%i,%i)\n",in.segmentlist[i* 2+ 0],in.segmentlist[i* 2+ 1]);
205      printf("Segment marker (%i)\n",in.segmentmarkerlist[i + 0]);
206      }
207 
208 
209  printf ("numberofholess %i\n", in.numberofholes);
210  for(i = 0; i < in.numberofholes; i++) {
211    printf("(%f,%f)\n",in.holelist[i* 2+ 0],in.holelist[i* 2+ 1]);
212  }
213     
214      printf ("numberoftriangles %i\n", in.numberoftriangles);
215      for(i = 0; i < in.numberoftriangles; i++) {
216      printf("(%i,%i,%i)",in.trianglelist[i* 3+ 0],in.trianglelist[i* 3+ 1], in.trianglelist[i* 3+ 2]);
217      }
218  printf(" ***  see ya world\n" );       
219      */
220  /* set up the switch arguments to the triangulation routine */
221  mod = PyString_AS_STRING(mode);
222     
223         
224  out.pointlist = (REAL *)NULL;
225  out.pointmarkerlist = (int *)NULL;
226  //out.numberofpointattributes = in.numberofpointattributes;
227  out.pointattributelist = (REAL *)NULL;
228 
229  out.trianglelist = (int *)NULL;
230  out.triangleattributelist = (REAL *)NULL;                   
231  out.trianglearealist = (REAL *)NULL;                       
232  out.neighborlist = (int *)NULL;
233     
234  out.segmentlist = (int *)NULL;
235  out.segmentmarkerlist = (int *)NULL;
236     
237  out.edgelist = (int *)NULL;
238  out.edgemarkerlist = (int *)NULL;
239     
240  out.holelist = (REAL *)NULL;
241  out.regionlist = (REAL *)NULL;
242   
243 
244  triangulate(mod, &in, &out, (struct triangulateio *)NULL );
245 
246 
247   
248  /*
249    ------- Pass point numbers,coordinates and neighbors back to Python ------
250    we send back a dictionary:                                               
251    { index : [ coordinates, [connections], Attribute ] }
252  */ 
253 
254  /*
255 
256     to return numeric arrays, check how it is done in
257     abs quantity_ext.c compute_gradients
258     
259  PyArray_FromDims allolws you to create a numeric array with unitialized data.
260   The first argument is the size of the second argument (
261   the dimensions array).
262    The dimension array argument is just a 1D C array where each element of
263     the array is the size of that dimension.
264     (int dimensions[2] = { 4, 3 }; defines a 4 by 3 array.)
265     The third argument is just the desired type.
266  */
267 
268 
269  /* Add triangle list */
270  dimensions[0] = out.numberoftriangles;
271  dimensions[1] = 3;   
272  gentrianglelist = (PyArrayObject *) anuga_FromDimsAndData(2,
273                                            dimensions,
274                                            PyArray_INT, 
275                                            (char*) out.trianglelist); 
276   
277  /* Add pointlist */
278  dimensions[0] = out.numberofpoints;
279  dimensions[1] = 2;   
280  genpointlist = (PyArrayObject *) anuga_FromDimsAndData(2,
281                                         dimensions,
282                                         PyArray_DOUBLE, 
283                                         (char*) out.pointlist);
284                                           
285 
286  /* Add point marker list */
287  dimensions[0] = out.numberofpoints;
288  genpointmarkerlist = (PyArrayObject *) anuga_FromDimsAndData(1, 
289                                         dimensions, 
290                                         PyArray_INT,
291                                        (char*) out.pointmarkerlist);
292 
293  /* Add point attribute list */
294  dimensions[0] = out.numberofpoints;
295  dimensions[1] = out.numberofpointattributes;   
296  genpointattributelist = (PyArrayObject *) anuga_FromDimsAndData(2, 
297                                          dimensions, 
298                                          PyArray_DOUBLE,
299                                          (char*) out.pointattributelist);
300 
301 
302 
303  /* Add triangle attribute list */
304  dimensions[0] = out.numberoftriangles;
305  dimensions[1] = out.numberoftriangleattributes;   
306  gentriangleattributelist = (PyArrayObject *) anuga_FromDimsAndData(2, 
307                                           dimensions, 
308                                           PyArray_DOUBLE,
309                                          (char*)out.triangleattributelist);
310 
311  /* Add segment list */
312  dimensions[0] = out.numberofsegments;
313  dimensions[1] = 2;   
314  gensegmentlist = (PyArrayObject *) anuga_FromDimsAndData(2, 
315                                                    dimensions, 
316                                                    PyArray_INT,
317                                                    (char*)out.segmentlist);
318 
319 
320  /* Add segment marker list */
321  dimensions[0] = out.numberofsegments;
322  gensegmentmarkerlist = (PyArrayObject *) anuga_FromDimsAndData(1, 
323                                            dimensions, 
324                                            PyArray_INT,
325                                           (char*)out.segmentmarkerlist);
326 
327  /* Add triangle neighbor list */
328  if (out.neighborlist != NULL) {
329    dimensions[0] = out.numberoftriangles;
330    dimensions[1] = 3;   
331    genneighborlist = (PyArrayObject *) anuga_FromDimsAndData(2, 
332                                                 dimensions, 
333                                                 PyArray_INT,
334                                                 (char*)out.neighborlist);
335  }else{ 
336    dimensions[0] = 0;
337    dimensions[1] = 0;   
338    genneighborlist = (PyArrayObject *) anuga_FromDims(2, 
339                                                       dimensions, 
340                                                       PyArray_INT);
341  }
342 
343 
344  R = Py_BuildValue((char *)"OOOOOOOO"
345                    ,PyArray_Return(gentrianglelist)
346                    ,PyArray_Return(genpointlist)
347                    ,PyArray_Return(genpointmarkerlist)
348                    ,PyArray_Return(genpointattributelist)
349                    ,PyArray_Return(gentriangleattributelist)
350                    ,PyArray_Return(gensegmentlist)
351                    ,PyArray_Return(gensegmentmarkerlist)
352                    ,PyArray_Return(genneighborlist)
353                    );
354                   
355  Py_DECREF(gentrianglelist);
356  Py_DECREF(genpointlist);
357  Py_DECREF(genpointmarkerlist);
358  Py_DECREF(genpointattributelist);
359  Py_DECREF(gentriangleattributelist);
360  Py_DECREF(gensegmentlist);
361  Py_DECREF(gensegmentmarkerlist);
362  Py_DECREF(genneighborlist);
363 
364 
365  /* These memory blocks are passed into numeric arrays
366   so don't free them  */
367  /*
368  if(!out.trianglelist){   
369    free(out.trianglelist); out.trianglelist=NULL;
370   
371   
372  if(!out.pointlist){
373    free(out.pointlist);  out.pointlist=NULL;
374  } 
375 
376  if(!out.pointmarkerlist){   
377    free(out.pointmarkerlist); out.pointmarkerlist=NULL;
378  }
379 
380  if(!out.pointattributelist){   
381    free(out.pointattributelist); out.pointattributelist=NULL;
382  }   
383 
384  if(!out.triangleattributelist){   
385    free(out.triangleattributelist); out.triangleattributelist=NULL;
386  }
387  if(!out.segmentlist){
388    free(out.segmentlist); out.segmentlist =NULL;
389  }
390  if(!out.segmentmarkerlist){
391    free(out.segmentmarkerlist); out.segmentmarkerlist  =NULL;
392  }
393  if(!out.neighborlist){   
394    free(out.neighborlist); out.neighborlist=NULL;
395  }
396   */
397
398   
399 
400  /* Free in/out structure memory */
401 
402  if(!out.trianglearealist){   
403    free(out.trianglearealist); out.trianglearealist=NULL;
404  }
405  if(!out.edgelist){
406    free(out.edgelist);  out.edgelist=NULL;
407  }
408  if(!out.edgemarkerlist){
409    free(out.edgemarkerlist);  out.edgemarkerlist=NULL;
410  }
411  if(!out.holelist){
412    free(out.holelist); out.holelist=NULL;
413  }
414  if(!out.regionlist){
415    free(out.regionlist); out.regionlist=NULL;
416  }
417  return R;
418}
419
420/* end of my function*/
421 
422static PyMethodDef triang_methods[] = {
423  {(char *)"genMesh", triang_genMesh, 1, (char *)"Passes hull points to triangle.All arguments are lists.(<hull>,<seglist>,<holelist>,<regionlist>)-><hull>"}, 
424  {NULL,NULL}
425};
426
427void initmesh_engine_c_layer(){
428  Py_InitModule((char *)"mesh_engine_c_layer",triang_methods);
429 
430  import_array(); // Necessary for handling of NumPY structures
431}   
Note: See TracBrowser for help on using the repository browser.