Changeset 8568


Ignore:
Timestamp:
Sep 9, 2012, 9:02:28 PM (13 years ago)
Author:
steve
Message:

C version of pmesh2domain

Location:
trunk/anuga_core/source/anuga/abstract_2d_finite_volumes
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/anuga_core/source/anuga/abstract_2d_finite_volumes/pmesh2domain.py

    r8567 r8568  
    160160
    161161
    162 def pmesh_dict_to_tag_dict(mesh_dict):
     162def pmesh_dict_to_tag_dict_old(mesh_dict):
    163163    """ Convert the pmesh dictionary (mesh_dict) description of boundary tags
    164164    to a dictionary of tags, indexed with volume id and face number.
     
    166166
    167167    triangles = mesh_dict['triangles']
    168     sides = calc_sides(triangles)
     168
     169    triangles = num.array(triangles,num.int)
     170
     171    sides = {}
     172    for id, triangle in enumerate(triangles):
     173        a = triangle[0]
     174        b = triangle[1]
     175        c = triangle[2]
     176
     177        sides[a,b] = 3*id+2 #(id, face)
     178        sides[b,c] = 3*id+0 #(id, face)
     179        sides[c,a] = 3*id+1 #(id, face)
     180
    169181    tag_dict = {}
    170182    for seg, tag in map(None, mesh_dict['segments'], mesh_dict['segment_tags']):
     
    182194    return tag_dict
    183195
     196def pmesh_dict_to_tag_dict(mesh_dict):
     197    """ Convert the pmesh dictionary (mesh_dict) description of boundary tags
     198    to a dictionary of tags, indexed with volume id and face number.
     199    """
     200
     201    triangles = mesh_dict['triangles']
     202    segments = mesh_dict['segments']
     203    segment_tags = mesh_dict['segment_tags']
     204
     205    triangles = num.array(triangles,num.int)
     206    segments = num.array(segments,num.int)
     207    tag_dict = {}
     208
     209    #print triangles
     210    #print segments
     211    #print segment_tags
     212
     213    from pmesh2domain_ext import build_boundary_dictionary
     214
     215    tag_dict = build_boundary_dictionary(triangles, segments, segment_tags, tag_dict)
     216   
     217    return tag_dict
     218
    184219
    185220def calc_sides_old(triangles):
     
    201236    return sides
    202237
    203 def calc_sides_old2(triangles):
    204     '''Build dictionary mapping from sides (2-tuple of points)
    205     to left hand side neighbouring triangle
    206     '''
    207 
    208     sides = {}
    209 
    210     for id, triangle in enumerate(triangles):
    211         a = int(triangle[0])
    212         b = int(triangle[1])
    213         c = int(triangle[2])
    214 
    215         sides[a,b] = (id, 2) #(id, face)
    216         sides[b,c] = (id, 0) #(id, face)
    217         sides[c,a] = (id, 1) #(id, face)
    218 
    219     return sides
     238
    220239
    221240def calc_sides_zip(triangles):
     
    242261    return sides
    243262
    244 def calc_sides(triangles):
     263def calc_sides_c(triangles):
    245264    '''Build dictionary mapping from sides (2-tuple of points)
    246265    to left hand side neighbouring triangle
  • trunk/anuga_core/source/anuga/abstract_2d_finite_volumes/pmesh2domain_ext.c

    r8567 r8568  
     1#include <stdio.h>   /* gets */
     2#include <stdlib.h>  /* atoi, malloc */
     3#include <string.h>  /* strcpy */
     4
     5
     6
    17#include "Python.h"
    28#include "numpy/arrayobject.h"
    3 #include <stdio.h>
    4 #include "util_ext.h"
     9#include "math.h"
     10
     11//Shared code snippets
     12
     13#include "util_ext.h" /* in utilities */
     14#include "uthash.h"     /* in utilities */
     15
     16
    517
    618#define DDATA(p) ((double*)(((PyArrayObject *)p)->data))
    719#define IDATA(p) ((long*)(((PyArrayObject *)p)->data))
     20#define CDATA(p) ((char*)(((PyArrayObject *)p)->data))
    821#define LENDATA(p) ((long)(((PyArrayObject *)p)->dimensions[0]))
    922
    10 
    11 
    12 static PyObject *SidesDictionaryConstruct( PyObject *self, PyObject *args )
    13 {
    14         int i, ok, numTriangle;
    15         long a,b,c;
    16         long *triangles;
    17         PyObject *pyobj_key;
    18         PyObject *pyobj_sides;
    19         PyArrayObject *pyobj_triangles;
    20 
    21 
    22         ok = PyArg_ParseTuple( args, "OO", &pyobj_triangles, &pyobj_sides );
    23         if( !ok ){
    24                 report_python_error(AT, "could not parse input arguments");
    25                 return NULL;
    26         }
    27 
    28 
    29         numTriangle = LENDATA( pyobj_triangles );
    30         triangles = IDATA( pyobj_triangles );
    31 
    32         /*
    33         for id, triangle in enumerate(triangles):
    34            a = int(triangle[0])
    35            b = int(triangle[1])
    36            c = int(triangle[2])
    37 
    38            sides[a,b] = 3*id+2 #(id, face)
    39            sides[b,c] = 3*id+0 #(id, face)
    40            sides[c,a] = 3*id+1 #(id, face)
    41          */
    42 
    43         //printf("numTriangle %d\n",numTriangle);
    44 
    45         for(i=0; i<numTriangle; i++){
    46             a = triangles[i*3+0];
    47             b = triangles[i*3+1];
    48             c = triangles[i*3+2];
    49 
    50             // sides[a,b] = (id, 2) #(id, face)
    51             pyobj_key = PyTuple_New( 2 );
    52             PyTuple_SetItem( pyobj_key, 0, PyInt_FromLong( a ) );
    53             PyTuple_SetItem( pyobj_key, 1, PyInt_FromLong( b ) );
    54            
    55             PyDict_SetItem( pyobj_sides, pyobj_key, PyInt_FromLong( 3*i+2 ) );
    56 
    57             Py_DECREF(pyobj_key);
    58            
    59             // sides[b,c] = (id, 0) #(id, face)
    60             pyobj_key = PyTuple_New( 2 );
    61             PyTuple_SetItem( pyobj_key, 0, PyInt_FromLong( b ) );
    62             PyTuple_SetItem( pyobj_key, 1, PyInt_FromLong( c ) );
    63            
    64             PyDict_SetItem( pyobj_sides, pyobj_key, PyInt_FromLong( 3*i+0 ) );
    65 
    66             Py_DECREF(pyobj_key);
    67 
    68            
    69             // sides[c,a] = (id, 1) #(id, face)
    70             pyobj_key = PyTuple_New( 2 );
    71             PyTuple_SetItem( pyobj_key, 0, PyInt_FromLong( c ) );
    72             PyTuple_SetItem( pyobj_key, 1, PyInt_FromLong( a ) );
    73                      
    74             PyDict_SetItem( pyobj_sides, pyobj_key, PyInt_FromLong( 3*i+1 ) );
    75 
    76             Py_DECREF(pyobj_key);
    77 
    78 
    79         }
    80 
    81         return Py_BuildValue("O", pyobj_sides);
    82 }
     23//==============================================================================
     24// hashtable code from uthash. Look at copyright info in "uthash.h in the
     25// utilities directory
     26//==============================================================================
     27
     28typedef struct {
     29    int i;
     30    int j;
     31} segment_key_t;
     32
     33typedef struct {
     34    segment_key_t key; /* key of form i , j */
     35    int vol_id; /* id of vol containing this segement */
     36    int edge_id; /* edge_id of segement in this vol */
     37    UT_hash_handle hh; /* makes this structure hashable */
     38} segment_t;
     39
     40segment_t *segment_table = NULL;
     41
     42void add_segment(segment_key_t key, int vol_id, int edge_id) {
     43    segment_t *s;
     44
     45    s = (segment_t*) malloc(sizeof (segment_t));
     46    memset(s, 0, sizeof (segment_t));
     47    s->key.i = key.i;
     48    s->key.j = key.j;
     49    s->vol_id = vol_id;
     50    s->edge_id = edge_id;
     51    HASH_ADD(hh, segment_table, key, sizeof (segment_key_t), s); /* key: name of key field */
     52}
     53
     54segment_t *find_segment(segment_key_t key) {
     55    segment_t *s=0;
     56
     57    HASH_FIND(hh, segment_table, &key, sizeof (segment_key_t), s); /* s: output pointer */
     58    return s;
     59}
     60
     61void delete_segment(segment_t *segment) {
     62    HASH_DEL(segment_table, segment); /* user: pointer to deletee */
     63    free(segment);
     64}
     65
     66void delete_all() {
     67    segment_t *current_segment, *tmp;
     68
     69    HASH_ITER(hh, segment_table, current_segment, tmp) {
     70        HASH_DEL(segment_table, current_segment); /* delete it (segment_table advances to next) */
     71        free(current_segment); /* free it */
     72    }
     73}
     74
     75void print_segments() {
     76    segment_t *s;
     77
     78    for (s = segment_table; s != NULL; s = (segment_t*) (s->hh.next)) {
     79        printf("segment key i %d j %d vol_id %d  edge_id %d\n",
     80                s->key.i, s->key.j, s->vol_id, s->edge_id);
     81    }
     82}
     83
     84int vol_id_sort(segment_t *a, segment_t *b) {
     85    return (a->vol_id - b->vol_id);
     86}
     87
     88int key_sort(segment_t *a, segment_t *b) {
     89    return (a->key.i - b->key.i);
     90}
     91
     92void sort_by_vol_id() {
     93    HASH_SORT(segment_table, vol_id_sort);
     94}
     95
     96void sort_by_key() {
     97    HASH_SORT(segment_table, key_sort);
     98}
     99
     100
     101//==============================================================================
     102// Python method Wrapper
     103//==============================================================================
     104
     105PyObject *build_boundary_dictionary(PyObject *self, PyObject *args) {
     106
     107    /*
     108     * Update neighbours array using triangles array
     109     *
     110     * N is number of nodes (vertices)
     111     * triangle nodes defining triangles
     112     * neighbour across edge_id
     113     * neighbour_segments edge_id of segment in neighbouring triangle
     114     * number_of_boundaries
     115     */
     116
     117    PyArrayObject *pyobj_segments;
     118    PyArrayObject *pyobj_triangles;
     119
     120    PyObject *pyobj_segment_tags; // List of strings
     121    PyObject *pyobj_tag_dict;
     122    PyObject *pyobj_key;
     123    PyObject *pyobj_tag;
     124
     125    long *triangles;
     126    long *segments;
     127
     128    int M; // Number of triangles (calculated from triangle array)
     129    int N; // Number of segments (calculated from segments array)
     130    int err = 0;
     131
     132    int k;
     133    int k3;
     134    int k2;
     135    int a,b,c;
     136    int vol_id;
     137    int edge_id;
     138    int len_tag;
     139    char *string;
     140    segment_t *s;
     141    segment_key_t key;
     142
     143    // Convert Python arguments to C
     144    if (!PyArg_ParseTuple(args, "OOOO",
     145            &pyobj_triangles,
     146            &pyobj_segments,
     147            &pyobj_segment_tags,
     148            &pyobj_tag_dict
     149            )) {
     150        PyErr_SetString(PyExc_RuntimeError,
     151                "pmesh2domain.c: build_boundary_dictionary could not parse input");
     152        return NULL;
     153    }
     154
     155    M = LENDATA(pyobj_triangles);
     156    N = LENDATA(pyobj_segments);
     157
     158    triangles = IDATA(pyobj_triangles);
     159    segments  = IDATA(pyobj_segments);
     160
     161    //--------------------------------------------------------------------------
     162    // Step 1:
     163    // Populate hashtable. We use a key based on the node_ids of the
     164    // two nodes defining the segment
     165    //--------------------------------------------------------------------------
     166    for (k = 0; k < M; k++) {
     167
     168        // Run through triangles
     169        k3 = 3 * k;
     170
     171        a = triangles[k3 + 0];
     172        b = triangles[k3 + 1];
     173        c = triangles[k3 + 2];
     174
     175
     176
     177        // Add segments to hashtable
     178
     179        //----------------------------------------------------------------------
     180        // Segment a,b
     181        //----------------------------------------------------------------------
     182        key.i = a;
     183        key.j = b;
     184        vol_id = k;
     185        edge_id = 2;
     186
     187        // Error if duplicates
     188        s = find_segment(key);
     189
     190        //printf("k = %d segment %d %d \n",k,a,b);
     191        if (s) {
     192            err = 1;
     193            break;
     194        }
     195        // Otherwise add segment
     196        add_segment(key, vol_id, edge_id);
     197
     198        //----------------------------------------------------------------------
     199        // segment b,c
     200        //----------------------------------------------------------------------
     201        key.i = b;
     202        key.j = c;
     203        vol_id = k;
     204        edge_id = 0;
     205
     206        // Error if duplicates
     207        s = find_segment(key);
     208        //printf("k = %d segment %d %d \n",k,b,c);
     209        if (s) {
     210            err = 1;
     211            break;
     212        }
     213        // Otherwise add segment
     214        add_segment(key, vol_id, edge_id);
     215
     216        //----------------------------------------------------------------------
     217        // segment c,a
     218        //----------------------------------------------------------------------
     219        key.i = c;
     220        key.j = a;
     221        vol_id = k;
     222        edge_id = 1;
     223
     224        // Error if duplicates
     225        s = find_segment(key);
     226
     227        //printf("k = %d segment %d %d \n",k,c,a);
     228        if (s) {
     229            err = 1;
     230            break;
     231        }
     232        // Otherwise add segment
     233        add_segment(key, vol_id, edge_id);
     234
     235    }
     236
     237    //printf("err %d \n",err);
     238    //--------------------------------------------------------------------------
     239    // return with an error code if duplicate key found
     240    // Clean up hashtable
     241    //--------------------------------------------------------------------------
     242    if (err) {
     243        //printf("Duplicate Keys:\n");
     244        //printf("key.i %d key.j %d vol_id %d edge_id %d \n",
     245        //       s->key.i, s->key.j,s->vol_id,s->edge_id);
     246        //printf("key.i %d key.j %d vol_id %d edge_id %d \n",
     247        //       key.i,key.j,vol_id,edge_id);
     248        delete_all();
     249        PyErr_SetString(PyExc_RuntimeError,
     250                "pmesh2domain.c: build_boundary_dictionary Duplicate segments");
     251        return NULL;
     252    }
     253
     254
     255    //--------------------------------------------------------------------------
     256    //Step 2:
     257    //Go through segments. Those with null tags are added to pyobj_tag_dict
     258    //--------------------------------------------------------------------------
     259
     260
     261    for (k = 0; k < N; k++) {
     262
     263        k2 = 2*k;
     264        a = segments[k2+0];
     265        b = segments[k2+1];
     266
     267        // pyobj_tag should be a string
     268        pyobj_tag = PyList_GetItem(pyobj_segment_tags, (Py_ssize_t) k );
     269
     270        string = PyString_AsString(pyobj_tag);
     271
     272        len_tag = strlen(string);
     273
     274        //printf("segment %d %d len %d, tag %s \n",a,b,len_tag, string);
     275
     276        key.i = a;
     277        key.j = b;
     278        s = find_segment(key);
     279        if ( s &&  len_tag>0 ) {
     280            vol_id  = s->vol_id;
     281            edge_id = s->edge_id;
     282
     283            pyobj_key = PyTuple_New(2);
     284            PyTuple_SetItem(pyobj_key, 0, PyInt_FromLong( vol_id ));
     285            PyTuple_SetItem(pyobj_key, 1, PyInt_FromLong( edge_id ));
     286
     287            PyDict_SetItem(pyobj_tag_dict, pyobj_key, pyobj_tag );
     288        }
     289
     290        key.i = b;
     291        key.j = a;
     292        s = find_segment(key);
     293        if ( s &&  len_tag>0 ) {
     294            vol_id  = s->vol_id;
     295            edge_id = s->edge_id;
     296
     297            pyobj_key = PyTuple_New(2);
     298            PyTuple_SetItem(pyobj_key, 0, PyInt_FromLong( vol_id ));
     299            PyTuple_SetItem(pyobj_key, 1, PyInt_FromLong( edge_id ));
     300
     301            PyDict_SetItem(pyobj_tag_dict, pyobj_key, pyobj_tag );
     302        }
     303
     304    }
     305
     306    delete_all(); /* free any structures */
     307
     308    return Py_BuildValue("O", pyobj_tag_dict);
     309}
     310
     311
     312//==============================================================================
     313// Structures to allow calling from python
     314//==============================================================================
     315
     316static PyObject *build_sides_dictionary(PyObject *self, PyObject *args) {
     317    long i, numTriangle;
     318    int ok;
     319    long a, b, c;
     320    long *triangles;
     321    PyObject *pyobj_key;
     322    PyObject *pyobj_sides;
     323    PyArrayObject *pyobj_triangles;
     324
     325
     326    ok = PyArg_ParseTuple(args, "OO", &pyobj_triangles, &pyobj_sides);
     327    if (!ok) {
     328        report_python_error(AT, "could not parse input arguments");
     329        return NULL;
     330    }
     331
     332
     333    numTriangle = LENDATA(pyobj_triangles);
     334    triangles = IDATA(pyobj_triangles);
     335
     336
     337
     338    for (i = 0; i < numTriangle; i++) {
     339        a = triangles[i * 3 + 0];
     340        b = triangles[i * 3 + 1];
     341        c = triangles[i * 3 + 2];
     342
     343        // sides[a,b] = (id, 2) #(id, face)
     344        pyobj_key = PyTuple_New(2);
     345        PyTuple_SetItem(pyobj_key, 0, PyInt_FromLong(a));
     346        PyTuple_SetItem(pyobj_key, 1, PyInt_FromLong(b));
     347
     348        PyDict_SetItem(pyobj_sides, pyobj_key, PyInt_FromLong(3 * i + 2));
     349
     350        Py_DECREF(pyobj_key);
     351
     352        // sides[b,c] = (id, 0) #(id, face)
     353        pyobj_key = PyTuple_New(2);
     354        PyTuple_SetItem(pyobj_key, 0, PyInt_FromLong(b));
     355        PyTuple_SetItem(pyobj_key, 1, PyInt_FromLong(c));
     356
     357        PyDict_SetItem(pyobj_sides, pyobj_key, PyInt_FromLong(3 * i + 0));
     358
     359        Py_DECREF(pyobj_key);
     360
     361
     362        // sides[c,a] = (id, 1) #(id, face)
     363        pyobj_key = PyTuple_New(2);
     364        PyTuple_SetItem(pyobj_key, 0, PyInt_FromLong(c));
     365        PyTuple_SetItem(pyobj_key, 1, PyInt_FromLong(a));
     366
     367        PyDict_SetItem(pyobj_sides, pyobj_key, PyInt_FromLong(3 * i + 1));
     368
     369        Py_DECREF(pyobj_key);
     370
     371
     372    }
     373
     374    return Py_BuildValue("O", pyobj_sides);
     375}
     376
    83377
    84378static PyMethodDef MF_module_methods[] = {
    85         {"sides_dictionary_construct", SidesDictionaryConstruct, METH_VARARGS},
    86         {NULL, NULL}    //sentinel
    87 };
    88 
    89 void initpmesh2domain_ext( )
    90 {
    91         (void) Py_InitModule("pmesh2domain_ext", MF_module_methods);
    92 
    93         import_array();
    94 }
     379{"build_boundary_dictionary", build_boundary_dictionary, METH_VARARGS},
     380{"build_sides_dictionary", build_sides_dictionary, METH_VARARGS},
     381                {NULL, NULL} //sentinel
     382            };
     383
     384void initpmesh2domain_ext() {
     385    (void) Py_InitModule("pmesh2domain_ext", MF_module_methods);
     386
     387    import_array();
     388}
Note: See TracChangeset for help on using the changeset viewer.