source: inundation/pymetis/pymetis/metis.c @ 3414

Last change on this file since 3414 was 3414, checked in by jack, 18 years ago

Added pymetis to the scons scripts

File size: 3.3 KB
Line 
1#include <Python.h>
2#include <Numeric/arrayobject.h>
3
4/* This must be the same as the metis idxtype */
5typedef int idxtype;
6
7#include "bridge.h"
8
9static PyObject * metis_partMeshNodal(PyObject *, PyObject *);
10
11static PyMethodDef methods[] = {
12  {"partMeshNodal", metis_partMeshNodal, METH_VARARGS, "METIS_PartMeshNodal"},
13  {NULL, NULL, 0, NULL}
14};
15
16PyMODINIT_FUNC initmetis(void){
17  (void) Py_InitModule("metis", methods);
18
19  import_array();
20}
21
22/* Run the metis METIS_PartMeshNodal function
23 * expected args:
24 * ne: number of elements
25 * nn: number of nodes
26 * elmnts: element array
27 * etype: type of mesh elements:
28 ** 1 - triangle
29 ** 2 - tetrahedra
30 ** 3 - hexahedra
31 ** 4 - quadrilaterals
32 * nparts: number of partitions
33 * returns:
34 * edgecut: number of cut edges
35 * epart: partitioning of the elements
36 * npart: partitioning of the nodes.
37 *
38 * Note that while the metis data file format indexes verticies from 1,
39 * the library calls (including this one) use vericies indexed from 0.
40 * Unsure if this is because of the num_flag option, perhaps calling
41 * from a FORTRAN program will have 1-indexed verticies?
42 */
43static PyObject * metis_partMeshNodal(PyObject * self, PyObject * args){
44  int i;
45  int malloc_elem_c_arr = 0;
46  int ne;
47  int nn;
48  int etype;
49  int nparts;
50  int edgecut;
51  int numflag = 0; // The metis routine requires an int * for numflag.
52  int dims[1]; // PyArray_FromDimsAndData needs an int[] of array sizes.
53
54  PyObject * elements;
55  PyArrayObject * elem_arr;
56  PyArrayObject * epart_pyarr;
57  PyArrayObject * npart_pyarr;
58
59  /* These are all of the metis idxtype */
60  idxtype * elem_c_arr;
61  idxtype * epart;
62  idxtype * npart;
63  if(!PyArg_ParseTuple(args, "iiOii", &ne, &nn, &elements, &etype, &nparts))
64    return NULL;
65
66  elem_arr = (PyArrayObject *) PyArray_ContiguousFromObject(elements, PyArray_NOTYPE, 1, 1);
67
68  if(!elem_arr)
69    return NULL;
70
71  /* x86_64 will create arrays of longs and they need to be
72   * converted to arrays of idxtype for metis to work on them.
73   */
74  if(elem_arr->descr->type_num == PyArray_LONG){
75    elem_c_arr = (idxtype *)malloc(*(elem_arr->dimensions) * sizeof(idxtype));
76    malloc_elem_c_arr = 1;
77    if(!elem_c_arr)
78        return NULL;
79    for(i = 0 ; i < *(elem_arr->dimensions) ; i++){
80      elem_c_arr[i] = (idxtype)(((long *)elem_arr->data)[i]);
81      if(elem_c_arr[i] != ((long *)elem_arr->data)[i]){ /* i.e. downcast failed */
82        free(elem_c_arr);
83        Py_DECREF(elem_arr);
84        return NULL;
85      }
86    }
87  }else
88    elem_c_arr = (idxtype *)elem_arr->data;
89
90  epart = (idxtype *)malloc(ne * sizeof(idxtype));
91  if(epart == NULL){
92    if(malloc_elem_c_arr) free(elem_c_arr);
93    Py_DECREF(elem_arr);
94    return NULL;
95  }
96  npart = (idxtype *)malloc(nn * sizeof(idxtype));
97  if(npart == NULL){
98    if(malloc_elem_c_arr) free(elem_c_arr);
99    free(epart);
100    Py_DECREF(elem_arr);
101    return NULL;
102  }
103  bridge_partMeshNodal(&ne, &nn, elem_c_arr, &etype, &numflag, &nparts, &edgecut, epart, npart);
104
105  dims[0] = ne;
106  epart_pyarr = (PyArrayObject *)PyArray_FromDimsAndData(1, dims, PyArray_INT, (char *)epart);
107  dims[0] = nn;
108  npart_pyarr = (PyArrayObject *)PyArray_FromDimsAndData(1, dims, PyArray_INT, (char *)npart);
109
110 
111  if(malloc_elem_c_arr) free(elem_c_arr);
112  Py_DECREF(elem_arr);
113
114  return Py_BuildValue("iOO", edgecut, (PyObject *)epart_pyarr, (PyObject *)npart_pyarr);
115}
Note: See TracBrowser for help on using the repository browser.