Ignore:
Timestamp:
Jan 28, 2008, 6:14:47 PM (17 years ago)
Author:
steve
Message:

Added a C extension for the advection directory (gave up on using f2py!)

Location:
anuga_core/source/anuga/advection
Files:
1 added
3 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • anuga_core/source/anuga/advection/advection.py

    r4975 r4978  
    6666                                numproc=numproc)
    6767
    68 
     68        import Numeric
    6969        if velocity is None:
    70             self.velocity = [1,0]
     70            self.velocity = Numeric.array([1,0],'d')
    7171        else:
    72             self.velocity = velocity
     72            self.velocity = Numeric.array(velocity,'d')
    7373
    7474        #Only first is implemented for advection
     
    108108        return flux, max_speed
    109109
     110
     111
    110112    def compute_fluxes(self):
    111 
    112        
    113         self.compute_fluxes_ext()
    114 ##         try:
    115 ##             self.compute_fluxes_ext()
    116 ##         except:
    117 ##             self.compute_fluxes_python()
    118  
     113        """Compute all fluxes and the timestep suitable for all volumes
     114        in domain.
     115
     116        Compute total flux for each conserved quantity using "flux_function"
     117
     118        Fluxes across each edge are scaled by edgelengths and summed up
     119        Resulting flux is then scaled by area and stored in
     120        domain.explicit_update
     121
     122        The maximal allowable speed computed by the flux_function
     123        for each volume
     124        is converted to a timestep that must not be exceeded. The minimum of
     125        those is computed as the next overall timestep.
     126
     127        Post conditions:
     128        domain.explicit_update is reset to computed flux values
     129        domain.timestep is set to the largest step satisfying all volumes.
     130        """
     131
     132        import sys
     133        from Numeric import zeros, Float
     134        from anuga.config import max_timestep
     135
     136
     137        huge_timestep = float(sys.maxint)
     138        Stage = self.quantities['stage']
     139
     140        """
     141        print "======================================"
     142        print "BEFORE compute_fluxes"
     143        print "stage_update",Stage.explicit_update
     144        print "stage_edge",Stage.edge_values
     145        print "stage_bdry",Stage.boundary_values
     146        print "neighbours",self.neighbours
     147        print "neighbour_edges",self.neighbour_edges
     148        print "normals",self.normals
     149        print "areas",self.areas
     150        print "radii",self.radii
     151        print "edgelengths",self.edgelengths
     152        print "tri_full_flag",self.tri_full_flag
     153        print "huge_timestep",huge_timestep
     154        print "max_timestep",max_timestep
     155        print "velocity",self.velocity
     156        """
     157
     158        import advection_ext           
     159        self.timestep = advection_ext.compute_fluxes(self, Stage, huge_timestep, max_timestep)
     160
     161
     162
     163    def evolve(self,
     164               yieldstep = None,
     165               finaltime = None,
     166               duration = None,
     167               skip_initial_step = False):
     168
     169        """Specialisation of basic evolve method from parent class
     170        """
     171
     172        #Call basic machinery from parent class
     173        for t in Generic_domain.evolve(self,
     174                                       yieldstep=yieldstep,
     175                                       finaltime=finaltime,
     176                                       duration=duration,
     177                                       skip_initial_step=skip_initial_step):
     178
     179            #Pass control on to outer loop for more specific actions
     180            yield(t)
     181
     182
    119183
    120184
     
    207271        self.timestep = timestep
    208272
    209 
    210     def compute_fluxes_ext(self):
    211         """Compute all fluxes and the timestep suitable for all volumes
    212         in domain.
    213 
    214         Compute total flux for each conserved quantity using "flux_function"
    215 
    216         Fluxes across each edge are scaled by edgelengths and summed up
    217         Resulting flux is then scaled by area and stored in
    218         domain.explicit_update
    219 
    220         The maximal allowable speed computed by the flux_function
    221         for each volume
    222         is converted to a timestep that must not be exceeded. The minimum of
    223         those is computed as the next overall timestep.
    224 
    225         Post conditions:
    226         domain.explicit_update is reset to computed flux values
    227         domain.timestep is set to the largest step satisfying all volumes.
    228         """
    229 
    230         import sys
    231         from Numeric import zeros, Float
    232         from anuga.config import max_timestep
    233 
    234         ntri = len(self)
    235 
    236         timestep = max_timestep
    237 
    238         #Shortcuts
    239         Stage = self.quantities['stage']
    240 
    241         #Arrays
    242         neighbours      = self.neighbours
    243         neighbour_edges = self.neighbour_edges
    244         normals         = self.normals
    245         areas           = self.areas
    246         radii           = self.radii
    247         edgelengths     = self.edgelengths
    248         tri_full_flag   = self.tri_full_flag
    249 
    250         stage_edge      = Stage.edge_values
    251         stage_bdry      = Stage.boundary_values
    252         stage_update    = Stage.explicit_update
    253 
    254         huge_timestep = float(sys.maxint)
    255 
    256         v = self.velocity
    257 
    258         nbdry = len(stage_bdry)
    259 
    260         from advection_ext import compute_fluxes
    261 
    262         print "stage_update",stage_update
    263         print "stage_edge",stage_edge
    264         print "stage_bdry",stage_bdry
    265         print "neighbours",neighbours
    266         print "neighbour_edges",neighbour_edges
    267         print "normals",normals
    268         print "areas",areas
    269         print "radii",radii
    270         print "edgelengths",edgelengths
    271         print "tri_full_flag",tri_full_flag
    272         print "huge_timestep",huge_timestep
    273         print "max_timestep",max_timestep
    274         print "v",v
    275         print "ntri",ntri
    276         print "nbdry",nbdry
    277 
    278 
    279                
    280         timestep = compute_fluxes(stage_update,stage_edge,stage_bdry,
    281                                   neighbours,neighbour_edges,normals,
    282                                   areas,radii,edgelengths,
    283                                   tri_full_flag,
    284                                   huge_timestep,max_timestep,v,ntri,nbdry)
    285 
    286         print "stage_update",stage_update       
    287        
    288         #print 'timestep out2 =',timestep
    289 
    290         self.timestep = timestep
    291 
    292 
    293     def evolve(self,
    294                yieldstep = None,
    295                finaltime = None,
    296                duration = None,
    297                skip_initial_step = False):
    298 
    299         """Specialisation of basic evolve method from parent class
    300         """
    301 
    302         #Call basic machinery from parent class
    303         for t in Generic_domain.evolve(self,
    304                                        yieldstep=yieldstep,
    305                                        finaltime=finaltime,
    306                                        duration=duration,
    307                                        skip_initial_step=skip_initial_step):
    308 
    309             #Pass control on to outer loop for more specific actions
    310             yield(t)
  • anuga_core/source/anuga/advection/advection_ext.c

    r4975 r4978  
     1// Python - C extension module for advection.py
     2//
     3// To compile (Python2.X):
     4// use python ../utilities/compile.py
     5//
     6// See the module advection.py
     7//
     8//
     9// Steve Roberts, ANU 2008
     10
     11
     12#include "Python.h"
     13#include "Numeric/arrayobject.h"
    114#include "math.h"
    215#include "stdio.h"
    316
    4 void  print_double_array(char* name, double* array, int n, int m){
    5 
    6     int k,i,km;
    7 
    8     printf("%s = [",name);
    9     for (k=0; k<n; k++){
    10         km = m*k;
    11         printf("[");
    12         for (i=0; i<m ; i++){
    13             printf("%g ",array[km+i]);
    14         }
    15         if (k==(n-1))
    16             printf("]");
    17         else
    18             printf("]\n");
    19     }
    20     printf("]\n");
    21 }
    22 
    23 void  print_int_array(char* name, int* array, int n, int m){
    24 
    25     int k,i,km;
    26 
    27     printf("%s = [",name);
    28     for (k=0; k<n; k++){
    29         km = m*k;
    30         printf("[");
    31         for (i=0; i<m ; i++){
    32             printf("%i ",array[km+i]);
    33         }
    34         if (k==(n-1))
    35             printf("]");
    36         else
    37             printf("]\n");
    38     }
    39     printf("]\n");
    40 }
    41 
    42 
    43 double compute_fluxes(
    44                     double* stage_update,
    45                     double* stage_edge,
    46                     double* stage_bdry,
    47                     int* neighbours,
    48                     int* neighbour_edges,
    49                     double* normals,
    50                     double* areas,
    51                     double* radii,
    52                     double* edgelengths,
    53                     int*   tri_full_flag,
     17// Shared code snippets
     18#include "util_ext.h"
     19
     20
     21
     22double _compute_fluxes(
     23                    double* quantity_update,
     24                    double* quantity_edge,
     25                    double* quantity_bdry,
     26                    long*   domain_neighbours,
     27                    long*   domain_neighbour_edges,
     28                    double* domain_normals,
     29                    double* domain_areas,
     30                    double* domain_radii,
     31                    double* domain_edgelengths,
     32                    long*   domain_tri_full_flag,
     33                    double* domain_velocity,
    5434                    double  huge_timestep,
    5535                    double  max_timestep,
    56                     double* v,
    5736                    int ntri,
    5837                    int nbdry){
     38
     39 
    5940        //Loop
    6041
     
    7253        timestep = max_timestep;
    7354
    74 
    75         printf("======================================================\n");
    76         printf("INSIDE compute_fluxes\n");
    77 
    78 
    79         print_double_array( "stage_update",stage_update, ntri, 1);
    80         print_double_array( "stage_edge",stage_edge, ntri, 3);
    81         print_double_array( "stage_bdry",stage_bdry, nbdry, 1);
    82         print_int_array( "neighbours",neighbours, ntri, 3);
    83         print_int_array( "neighbour_edges",neighbour_edges, ntri, 3);
    84         print_double_array( "normals",normals, ntri, 6);
    85         print_double_array( "areas",areas, ntri, 1);
    86         print_double_array( "radii",radii, ntri, 1);
    87         print_double_array( "edgelengths",edgelengths, ntri, 3);
    88         print_int_array( "tri_full_flag",tri_full_flag, ntri, 1);
    89         printf("huge_timestep = %g\n",huge_timestep);
    90         printf("max_timestep = %g\n",max_timestep);
    91         print_double_array( "v",v, 2, 1);
    92         printf("ntri = %i\n",ntri);
    93         printf("nbdry = %i\n",nbdry);
    94 
    95 
    9655        for (k=0; k<ntri; k++){
    9756            optimal_timestep = huge_timestep;
     
    10160                k_i = k3+i;
    10261                //Quantities inside volume facing neighbour i
    103                 ql = stage_edge[k_i];
     62                ql = quantity_edge[k_i];
    10463
    10564
    10665                //Quantities at neighbour on nearest face
    107                 n = neighbours[k_i];
     66                n = domain_neighbours[k_i];
    10867                if (n < 0) {
    10968                    m = -n-1; //Convert neg flag to index
    110                     qr = stage_bdry[m];
     69                    qr = quantity_bdry[m];
    11170                } else {
    112                     m = neighbour_edges[k_i];
     71                    m = domain_neighbour_edges[k_i];
    11372                    n_m = 3*n+m;
    114                     qr = stage_edge[n_m];
     73                    qr = quantity_edge[n_m];
    11574                }
    11675
     
    11978                for (j=0; j<2; j++){
    12079                    k_i_j = 6*k+2*i+j;
    121                     normal[j] = normals[k_i_j];
     80                    normal[j] = domain_normals[k_i_j];
    12281                }
    12382
    12483
    12584                //Flux computation using provided function
    126                 normal_velocity = v[0]*normal[0] + v[1]*normal[1];
     85                normal_velocity = domain_velocity[0]*normal[0] + domain_velocity[1]*normal[1];
    12786
    12887                if (normal_velocity < 0) {
     
    13392
    13493                max_speed = fabs(normal_velocity);
    135                 flux = flux - edgeflux * edgelengths[k_i];
     94                flux = flux - edgeflux * domain_edgelengths[k_i];
    13695
    13796                //Update optimal_timestep
    138                 if (tri_full_flag[k] == 1) {
     97                if (domain_tri_full_flag[k] == 1) {
    13998                    if (max_speed != 0.0) {
    140                         optimal_timestep = (optimal_timestep>radii[k]/max_speed) ? radii[k]/max_speed : optimal_timestep;
     99                        optimal_timestep = (optimal_timestep>domain_radii[k]/max_speed) ?
     100                          domain_radii[k]/max_speed : optimal_timestep;
    141101                    }
    142102                }
     
    146106            //Normalise by area and store for when all conserved
    147107            //quantities get updated
    148             stage_update[k] = flux/areas[k];
     108            quantity_update[k] = flux/domain_areas[k];
    149109
    150110            timestep = (timestep>optimal_timestep) ? optimal_timestep : timestep;
    151111
    152112        }
    153 
    154         //printf("timestep out = %g\n",timestep);
    155 
    156 
    157 
    158         printf("INSIDE compute_fluxes, end \n");
    159 
    160         print_double_array( "stage_update",stage_update, ntri, 1);
    161 
    162         printf("FINISHED compute_fluxes\n");
    163         printf("======================================================\n");
    164 
    165113
    166114        return timestep;
    167115}
    168116
     117
     118//-----------------------------------------------------
     119// Python method Wrappers
     120//-----------------------------------------------------
     121
     122
     123
     124PyObject *compute_fluxes(PyObject *self, PyObject *args) {
     125  /*Compute all fluxes and the timestep suitable for all volumes
     126    in domain.
     127
     128    Fluxes across each edge are scaled by edgelengths and summed up
     129    Resulting flux is then scaled by area and stored in
     130    explicit_update for the conserved quantity stage.
     131
     132    The maximal allowable speed computed for each volume
     133    is converted to a timestep that must not be exceeded. The minimum of
     134    those is computed as the next overall timestep.
     135
     136    Python call:
     137    timestep = advection_ext.compute_fluxes(domain,quantity,huge_timestep,max_timestep)
     138
     139    Post conditions:
     140      domain.explicit_update is reset to computed flux values
     141      domain.timestep is set to the largest step satisfying all volumes.
     142
     143  */
     144
     145  PyObject *domain, *quantity;
     146  PyArrayObject
     147    * quantity_update,
     148    * quantity_edge,
     149    * quantity_bdry,
     150    * domain_neighbours,
     151    * domain_neighbour_edges,
     152    * domain_normals,
     153    * domain_areas,
     154    * domain_radii,
     155    * domain_edgelengths,
     156    * domain_tri_full_flag,
     157    * domain_velocity;
     158                 
     159
     160  // Local variables
     161  int ntri, nbdry;
     162  double huge_timestep, max_timestep;
     163  double timestep;
     164
     165
     166  // Convert Python arguments to C
     167  if (!PyArg_ParseTuple(args, "OOdd",
     168                        &domain,
     169                        &quantity,
     170                        &huge_timestep,
     171                        &max_timestep)) {
     172    PyErr_SetString(PyExc_RuntimeError, "advection_ext.c: compute_fluxes could not parse input");
     173    return NULL;
     174  }
     175
     176  quantity_edge          = get_consecutive_array(quantity, "edge_values");
     177  quantity_bdry          = get_consecutive_array(quantity, "boundary_values");
     178  quantity_update        = get_consecutive_array(quantity, "explicit_update");
     179  domain_neighbours      = get_consecutive_array(domain,   "neighbours");
     180  domain_neighbour_edges = get_consecutive_array(domain,   "neighbour_edges");
     181  domain_normals         = get_consecutive_array(domain,   "normals");
     182  domain_areas           = get_consecutive_array(domain,   "areas");
     183  domain_radii           = get_consecutive_array(domain,   "radii");
     184  domain_edgelengths     = get_consecutive_array(domain,   "edgelengths");
     185  domain_tri_full_flag   = get_consecutive_array(domain,   "tri_full_flag");
     186  domain_velocity        = get_consecutive_array(domain,   "velocity"); 
     187   
     188  ntri  = quantity_edge -> dimensions[0];
     189  nbdry = quantity_bdry -> dimensions[0];
     190
     191  timestep = _compute_fluxes((double*) quantity_update -> data,
     192                             (double*) quantity_edge -> data,
     193                             (double*) quantity_bdry -> data,
     194                             (long*)   domain_neighbours -> data,
     195                             (long*)   domain_neighbour_edges -> data,
     196                             (double*) domain_normals -> data,
     197                             (double*) domain_areas ->data,
     198                             (double*) domain_radii -> data,
     199                             (double*) domain_edgelengths -> data,
     200                             (long*)   domain_tri_full_flag -> data,
     201                             (double*) domain_velocity -> data,
     202                             huge_timestep,
     203                             max_timestep,
     204                             ntri,
     205                             nbdry);
     206
     207  // Release and return
     208  Py_DECREF(quantity_update);
     209  Py_DECREF(quantity_edge);
     210  Py_DECREF(quantity_bdry);
     211  Py_DECREF(domain_neighbours);
     212  Py_DECREF(domain_neighbour_edges);
     213  Py_DECREF(domain_normals);
     214  Py_DECREF(domain_areas);
     215  Py_DECREF(domain_radii);
     216  Py_DECREF(domain_edgelengths);
     217  Py_DECREF(domain_tri_full_flag);
     218  Py_DECREF(domain_velocity);
     219
     220
     221  return Py_BuildValue("d", timestep);
     222}
     223
     224
     225
     226//-------------------------------
     227// Method table for python module
     228//-------------------------------
     229static struct PyMethodDef MethodTable[] = {
     230  /* The cast of the function is necessary since PyCFunction values
     231   * only take two PyObject* parameters, and rotate() takes
     232   * three.
     233   */
     234
     235  {"compute_fluxes", compute_fluxes, METH_VARARGS, "Print out"},
     236  {NULL, NULL}
     237};
     238
     239// Module initialisation
     240void initadvection_ext(void){
     241  Py_InitModule("advection_ext", MethodTable);
     242  import_array(); // Necessary for handling of NumPY structures
     243}
  • anuga_core/source/anuga/advection/test_advection.py

    r4972 r4978  
    6060        U = -domain.quantities['stage'].explicit_update
    6161        R = -0.5/domain.areas[0]
    62 
    63         print 'U ', U
    64         print 'R ', R
    65        
    6662
    6763        assert U==R, '%s %s' %(U, R)
Note: See TracChangeset for help on using the changeset viewer.