source: anuga_work/development/anuga_1d/channel_domain_ext.c @ 6038

Last change on this file since 6038 was 6038, checked in by wilson, 15 years ago

Adding files for Padarn to play with.

File size: 17.4 KB
RevLine 
[6038]1#include "Python.h"
2#include "Numeric/arrayobject.h"
3#include "math.h"
4#include <stdio.h>
5const double pi = 3.14159265358979;
6
7
8// Shared code snippets
9#include "util_ext.h"
10
11
12/* double max(double a, double b) { */
13/*      double z; */
14/*      z=(a>b)?a:b; */
15/*      return z;} */
16       
17/* double min(double a, double b) { */
18/*      double z; */
19/*      z=(a<b)?a:b; */
20/*      return z;} */
21
22
23// Function to obtain speed from momentum and depth.
24// This is used by flux functions
25// Input parameters uh and h may be modified by this function.
26double _compute_speed(double *uh, 
27                      double *h, 
28                      double epsilon, 
29                      double h0) {
30 
31  double u;
32 
33  if (*h < epsilon) {
34    *h = 0.0;  //Could have been negative
35     u = 0.0;
36  } else {
37    u = *uh/(*h + h0/ *h);   
38  }
39 
40
41  // Adjust momentum to be consistent with speed
42  *uh = u * *h;
43 
44  return u;
45}
46
47//-------------------------------------------------------------
48// New vel based code
49//-------------------------------------------------------------
50//Innermost flux function (using w=z+h)
51int _flux_function_vel(double *q_left, double *q_right,
52                       double normals, double g, double epsilon, double h0,
53                       double *edgeflux, double *max_speed) {
54   
55    int i;
56    double flux_left[2], flux_right[2];
57    double w_left, h_left, uh_left, z_left, u_left, soundspeed_left;
58    double w_right, h_right, uh_right, z_right, u_right, soundspeed_right;
59    double z, s_max, s_min, denom;
60   
61
62    w_left  = q_left[0];
63    uh_left = q_left[1]*normals;
64    z_left  = q_left[2];
65    h_left  = q_left[3];
66    u_left  = q_left[4]*normals;
67
68/*     printf("w_left  = %f \n",w_left); */
69/*     printf("uh_left = %f \n",uh_left); */
70/*     printf("z_left  = %f \n",z_left); */
71/*     printf("h_left  = %f \n",h_left); */
72/*     printf("u_left  = %f \n",u_left); */
73   
74    w_right  = q_right[0];
75    uh_right = q_right[1]*normals;
76    z_right  = q_right[2];
77    h_right  = q_right[3];
78    u_right  = q_right[4]*normals;             
79   
80    z = (z_left+z_right)/2.0;             
81   
82    soundspeed_left = sqrt(g*h_left);
83    soundspeed_right = sqrt(g*h_right);
84   
85    s_max = max(u_left+soundspeed_left, u_right+soundspeed_right);
86    if (s_max < 0.0) s_max = 0.0;
87   
88    s_min = min(u_left-soundspeed_left, u_right-soundspeed_right);
89    if (s_min > 0.0) s_min = 0.0;
90   
91   
92    // Flux formulas
93    flux_left[0] = u_left*h_left;
94    flux_left[1] = u_left*u_left*h_left + 0.5*g*h_left*h_left;
95   
96    flux_right[0] = u_right*h_right;
97    flux_right[1] = u_right*u_right*h_right + 0.5*g*h_right*h_right;
98   
99    // Flux computation
100    denom = s_max-s_min;
101    if (denom < epsilon) {
102        for (i=0; i<2; i++) edgeflux[i] = 0.0;
103        *max_speed = 0.0;
104    } else {
105        edgeflux[0] = s_max*flux_left[0] - s_min*flux_right[0];
106        edgeflux[0] += s_max*s_min*(w_right-w_left);
107        edgeflux[0] /= denom;
108        edgeflux[1] = s_max*flux_left[1] - s_min*flux_right[1];
109        edgeflux[1] += s_max*s_min*(uh_right-uh_left);
110        edgeflux[1] /= denom;
111        edgeflux[1] *= normals;
112       
113        // Maximal wavespeed
114        *max_speed = max(fabs(s_max), fabs(s_min));
115    } 
116    return 0;           
117}
118
119// Computational function for flux computation
120double _compute_fluxes_vel_ext(double cfl,
121                               double timestep,
122                               double epsilon,
123                               double g,
124                               double h0,
125                               long* neighbours,
126                               long* neighbour_vertices,
127                               double* normals,
128                               double* areas,
129                               double* stage_edge_values,
130                               double* xmom_edge_values,
131                               double* bed_edge_values,
132                               double* height_edge_values,
133                               double* velocity_edge_values,
134                               double* stage_boundary_values,
135                               double* xmom_boundary_values,
136                               double* bed_boundary_values,
137                               double* height_boundary_values,
138                               double* velocity_boundary_values,
139                               double* stage_explicit_update,
140                               double* xmom_explicit_update,
141                               int number_of_elements,
142                               double* max_speed_array) {
143               
144    double flux[2], ql[5], qr[5], edgeflux[2];
145    double max_speed, normal;
146    int k, i, ki, n, m, nm=0;
147   
148   
149    for (k=0; k<number_of_elements; k++) {
150        flux[0] = 0.0;
151        flux[1] = 0.0;
152       
153        for (i=0; i<2; i++) {
154            ki = k*2+i;
155           
156            ql[0] = stage_edge_values[ki];
157            ql[1] = xmom_edge_values[ki];
158            ql[2] = bed_edge_values[ki];
159            ql[3] = height_edge_values[ki];
160            ql[4] = velocity_edge_values[ki];
161           
162            n = neighbours[ki];
163            if (n<0) {
164                m = -n-1;
165                qr[0] = stage_boundary_values[m];
166                qr[1] = xmom_boundary_values[m];
167                qr[2] = bed_boundary_values[m];
168                qr[3] = height_boundary_values[m];
169                qr[4] = velocity_boundary_values[m];
170            } else {
171                m = neighbour_vertices[ki];
172                nm = n*2+m;
173                qr[0] = stage_edge_values[nm];
174                qr[1] = xmom_edge_values[nm];
175                qr[2] = bed_edge_values[nm];
176                qr[3] = height_edge_values[nm];
177                qr[4] = velocity_edge_values[nm];
178            }
179           
180            normal = normals[ki];
181            _flux_function_vel(ql, qr, normal, g, epsilon, h0, edgeflux, &max_speed);
182            flux[0] -= edgeflux[0];
183            flux[1] -= edgeflux[1];
184           
185            // Update timestep based on edge i and possibly neighbour n
186            if (max_speed > epsilon) {
187                // Original CFL calculation
188               
189                timestep = min(timestep, 0.5*cfl*areas[k]/max_speed); 
190                if (n>=0) {
191                    timestep = min(timestep, 0.5*cfl*areas[n]/max_speed); 
192                }
193            }
194        } // End edge i (and neighbour n)
195        flux[0] /= areas[k];
196        stage_explicit_update[k] = flux[0];
197        flux[1] /= areas[k];
198        xmom_explicit_update[k] = flux[1];
199       
200        //Keep track of maximal speeds
201        max_speed_array[k]=max_speed;
202    }
203    return timestep;   
204}
205
206//-------------------------------------------------------------
207// Old code
208//------------------------------------------------------------
209//Innermost flux function (using w=z+h)
210int _flux_function(double *q_left, double *q_right,
211        double z_left, double z_right,
212                   double normals, double g, double epsilon, double h0,
213                double *edgeflux, double *max_speed) {
214               
215                int i;
216                double ql[2], qr[2], flux_left[2], flux_right[2];
217                double z, w_left, h_left, uh_left, soundspeed_left, u_left;
218                double w_right, h_right, uh_right, soundspeed_right, u_right;
219                double s_max, s_min, denom;
220               
221                //printf("h0 = %f \n",h0);
222                ql[0] = q_left[0];
223                ql[1] = q_left[1];
224                ql[1] = ql[1]*normals;
225       
226                qr[0] = q_right[0];
227                qr[1] = q_right[1];
228                qr[1] = qr[1]*normals;
229         
230                z = (z_left+z_right)/2.0;                 
231                                   
232                //w_left = ql[0];
233                //h_left = w_left-z;
234                //uh_left = ql[1];
235               
236
237
238                // Compute speeds in x-direction
239                w_left = ql[0];         
240                h_left = w_left-z;
241                uh_left = ql[1];
242
243                u_left = _compute_speed(&uh_left, &h_left, epsilon, h0);
244
245                w_right = qr[0];
246                h_right = w_right-z;
247                uh_right = qr[1];
248
249                u_right = _compute_speed(&uh_right, &h_right, epsilon, h0);
250 
251                soundspeed_left = sqrt(g*h_left);
252                soundspeed_right = sqrt(g*h_right);
253               
254                s_max = max(u_left+soundspeed_left, u_right+soundspeed_right);
255                if (s_max < 0.0) s_max = 0.0;
256       
257                s_min = min(u_left-soundspeed_left, u_right-soundspeed_right);
258                if (s_min > 0.0) s_min = 0.0;
259               
260               
261                // Flux formulas
262                flux_left[0] = u_left*h_left;
263                flux_left[1] = u_left*uh_left + 0.5*g*h_left*h_left;
264
265                flux_right[0] = u_right*h_right;
266                flux_right[1] = u_right*uh_right + 0.5*g*h_right*h_right;
267
268                // Flux computation
269                denom = s_max-s_min;
270                if (denom < epsilon) {
271                        for (i=0; i<2; i++) edgeflux[i] = 0.0;
272                        *max_speed = 0.0;
273                } else {
274                        edgeflux[0] = s_max*flux_left[0] - s_min*flux_right[0];
275                        edgeflux[0] += s_max*s_min*(qr[0]-ql[0]);
276                        edgeflux[0] /= denom;
277                        edgeflux[1] = s_max*flux_left[1] - s_min*flux_right[1];
278                        edgeflux[1] += s_max*s_min*(qr[1]-ql[1]);
279                        edgeflux[1] /= denom;
280                        edgeflux[1] *= normals;
281   
282                // Maximal wavespeed
283        *max_speed = max(fabs(s_max), fabs(s_min));
284                } 
285    return 0;           
286        }
287               
288               
289       
290       
291// Computational function for flux computation
292double _compute_fluxes_ext(
293                           double cfl,
294                           double timestep,
295                           double epsilon,
296                           double g,
297                           double h0,
298                           long* neighbours,
299                           long* neighbour_vertices,
300                           double* normals,
301                           double* areas,
302                           double* stage_edge_values,
303                           double* xmom_edge_values,
304                           double* bed_edge_values,
305                           double* stage_boundary_values,
306                           double* xmom_boundary_values,
307                           double* stage_explicit_update,
308                           double* xmom_explicit_update,
309                           int number_of_elements,
310                           double* max_speed_array) {
311               
312                double flux[2], ql[2], qr[2], edgeflux[2];
313                double zl, zr, max_speed, normal;
314                int k, i, ki, n, m, nm=0;
315               
316               
317                for (k=0; k<number_of_elements; k++) {
318                        flux[0] = 0.0;
319                        flux[1] = 0.0;
320                       
321                        for (i=0; i<2; i++) {
322                                ki = k*2+i;
323                               
324                                ql[0] = stage_edge_values[ki];
325                                ql[1] = xmom_edge_values[ki];
326                                zl = bed_edge_values[ki];
327                               
328                                n = neighbours[ki];
329                                if (n<0) {
330                                        m = -n-1;
331                                        qr[0] = stage_boundary_values[m];
332                                        qr[1] = xmom_boundary_values[m];
333                                        zr = zl;
334                                } else {
335                                        m = neighbour_vertices[ki];
336                                        nm = n*2+m;
337                                        qr[0] = stage_edge_values[nm];
338                                        qr[1] = xmom_edge_values[nm];
339                                        zr = bed_edge_values[nm];                               
340                                }
341                               
342                                normal = normals[ki];
343                                _flux_function(ql, qr, zl, zr, normal, g, epsilon, h0, edgeflux, &max_speed);
344                                flux[0] -= edgeflux[0];
345                                flux[1] -= edgeflux[1];
346                               
347                                // Update timestep based on edge i and possibly neighbour n
348                                if (max_speed > epsilon) {
349                                    // Original CFL calculation
350                                   
351                                    timestep = min(timestep, 0.5*cfl*areas[k]/max_speed); 
352                                    if (n>=0) {
353                                        timestep = min(timestep, 0.5*cfl*areas[n]/max_speed); 
354                                    }
355                                }
356            } // End edge i (and neighbour n)
357                        flux[0] /= areas[k];
358                        stage_explicit_update[k] = flux[0];
359                        flux[1] /= areas[k];
360                        xmom_explicit_update[k] = flux[1];
361                       
362                        //Keep track of maximal speeds
363                        max_speed_array[k]=max_speed;
364                }
365                return timestep;       
366        }
367
368//=========================================================================
369// Python Glue
370//=========================================================================
371PyObject *compute_fluxes_ext(PyObject *self, PyObject *args) {
372 
373   PyObject
374        *domain,
375        *stage, 
376        *xmom, 
377        *bed;
378
379    PyArrayObject
380        *neighbours, 
381        *neighbour_vertices,
382        *normals, 
383        *areas,
384        *stage_vertex_values,
385        *xmom_vertex_values,
386        *bed_vertex_values,
387        *stage_boundary_values,
388        *xmom_boundary_values,
389        *stage_explicit_update,
390        *xmom_explicit_update,
391        *max_speed_array;
392   
393  double timestep, epsilon, g, h0, cfl;
394  int number_of_elements;
395
396   
397  // Convert Python arguments to C
398  if (!PyArg_ParseTuple(args, "dOOOO",
399                        &timestep,
400                        &domain,
401                        &stage,
402                        &xmom,
403                        &bed)) {
404      PyErr_SetString(PyExc_RuntimeError, "comp_flux_vel_ext.c: compute_fluxes_ext could not parse input");
405      return NULL;
406  }
407
408
409    epsilon           = get_python_double(domain,"epsilon");
410    g                 = get_python_double(domain,"g");
411    h0                = get_python_double(domain,"h0");
412    cfl               = get_python_double(domain,"CFL");
413 
414   
415    neighbours        = get_consecutive_array(domain, "neighbours");
416    neighbour_vertices= get_consecutive_array(domain, "neighbour_vertices"); 
417    normals           = get_consecutive_array(domain, "normals");
418    areas             = get_consecutive_array(domain, "areas");   
419    max_speed_array   = get_consecutive_array(domain, "max_speed_array");
420   
421    stage_vertex_values = get_consecutive_array(stage, "vertex_values");   
422    xmom_vertex_values  = get_consecutive_array(xmom, "vertex_values");   
423    bed_vertex_values   = get_consecutive_array(bed, "vertex_values");   
424
425    stage_boundary_values = get_consecutive_array(stage, "boundary_values");   
426    xmom_boundary_values  = get_consecutive_array(xmom, "boundary_values");   
427
428
429    stage_explicit_update = get_consecutive_array(stage, "explicit_update");   
430    xmom_explicit_update  = get_consecutive_array(xmom, "explicit_update");   
431
432
433
434    number_of_elements = stage_vertex_values -> dimensions[0];
435
436
437 
438    // Call underlying flux computation routine and update
439    // the explicit update arrays
440    timestep = _compute_fluxes_ext(
441        cfl,
442        timestep,
443        epsilon,
444        g,
445        h0,
446        (long*) neighbours -> data,
447        (long*) neighbour_vertices -> data,
448        (double*) normals -> data,
449        (double*) areas -> data,
450        (double*) stage_vertex_values -> data,
451        (double*) xmom_vertex_values -> data,
452        (double*) bed_vertex_values -> data,
453        (double*) stage_boundary_values -> data,
454        (double*) xmom_boundary_values -> data,
455        (double*) stage_explicit_update -> data,
456        (double*) xmom_explicit_update -> data,
457        number_of_elements,
458        (double*) max_speed_array -> data);
459
460
461  Py_DECREF(neighbours);
462  Py_DECREF(neighbour_vertices);
463  Py_DECREF(normals);
464  Py_DECREF(areas);
465  Py_DECREF(stage_vertex_values);
466  Py_DECREF(xmom_vertex_values);
467  Py_DECREF(bed_vertex_values);
468  Py_DECREF(stage_boundary_values);
469  Py_DECREF(xmom_boundary_values);
470  Py_DECREF(stage_explicit_update);
471  Py_DECREF(xmom_explicit_update);
472  Py_DECREF(max_speed_array);
473
474
475
476
477  // Return updated flux timestep
478  return Py_BuildValue("d", timestep);
479}
480
481
482//------------------------------------------------
483// New velocity based compute fluxes
484//------------------------------------------------
485PyObject *compute_fluxes_vel_ext(PyObject *self, PyObject *args) {
486 
487    PyObject
488        *domain,
489        *stage, 
490        *xmom, 
491        *bed,
492        *height,
493        *velocity;
494
495    PyArrayObject
496        *neighbours, 
497        *neighbour_vertices,
498        *normals, 
499        *areas,
500        *stage_vertex_values,
501        *xmom_vertex_values,
502        *bed_vertex_values,
503        *height_vertex_values,
504        *velocity_vertex_values,
505        *stage_boundary_values,
506        *xmom_boundary_values,
507        *bed_boundary_values,
508        *height_boundary_values,
509        *velocity_boundary_values,
510        *stage_explicit_update,
511        *xmom_explicit_update,
512        *max_speed_array;
513   
514  double timestep, epsilon, g, h0, cfl;
515  int number_of_elements;
516
517   
518  // Convert Python arguments to C
519  if (!PyArg_ParseTuple(args, "dOOOOOO",
520                        &timestep,
521                        &domain,
522                        &stage,
523                        &xmom,
524                        &bed,
525                        &height,
526                        &velocity)) {
527      PyErr_SetString(PyExc_RuntimeError, "comp_flux_vel_ext.c: compute_fluxes_vel_ext could not parse input");
528      return NULL;
529  }
530
531
532    epsilon           = get_python_double(domain,"epsilon");
533    g                 = get_python_double(domain,"g");
534    h0                = get_python_double(domain,"h0");
535    cfl               = get_python_double(domain,"CFL");
536 
537   
538    neighbours        = get_consecutive_array(domain, "neighbours");
539    neighbour_vertices= get_consecutive_array(domain, "neighbour_vertices"); 
540    normals           = get_consecutive_array(domain, "normals");
541    areas             = get_consecutive_array(domain, "areas");   
542    max_speed_array   = get_consecutive_array(domain, "max_speed_array");
543   
544    stage_vertex_values      = get_consecutive_array(stage,    "vertex_values");   
545    xmom_vertex_values       = get_consecutive_array(xmom,     "vertex_values");   
546    bed_vertex_values        = get_consecutive_array(bed,      "vertex_values");   
547    height_vertex_values     = get_consecutive_array(height,   "vertex_values");   
548    velocity_vertex_values   = get_consecutive_array(velocity, "vertex_values");   
549
550    stage_boundary_values     = get_consecutive_array(stage,     "boundary_values");   
551    xmom_boundary_values      = get_consecutive_array(xmom,      "boundary_values");   
552    bed_boundary_values       = get_consecutive_array(bed,       "boundary_values");   
553    height_boundary_values    = get_consecutive_array(height,    "boundary_values");   
554    velocity_boundary_values  = get_consecutive_array(velocity,  "boundary_values");   
555
556
557    stage_explicit_update = get_consecutive_array(stage, "explicit_update");   
558    xmom_explicit_update  = get_consecutive_array(xmom,  "explicit_update");   
559
560    number_of_elements = stage_vertex_values -> dimensions[0];
561 
562    // Call underlying flux computation routine and update
563    // the explicit update arrays
564    timestep = _compute_fluxes_vel_ext(cfl,
565                                       timestep,
566                                       epsilon,
567                                       g,
568                                       h0,
569                                       (long*) neighbours -> data,
570                                       (long*) neighbour_vertices -> data,
571                                       (double*) normals -> data,
572                                       (double*) areas -> data,
573                                       (double*) stage_vertex_values -> data,
574                                       (double*) xmom_vertex_values -> data,
575                                       (double*) bed_vertex_values -> data,
576                                       (double*) height_vertex_values -> data,
577                                       (double*) velocity_vertex_values -> data,
578                                       (double*) stage_boundary_values -> data,
579                                       (double*) xmom_boundary_values -> data,
580                                       (double*) bed_boundary_values -> data,
581                                       (double*) height_boundary_values -> data,
582                                       (double*) velocity_boundary_values -> data,
583                                       (double*) stage_explicit_update -> data,
584                                       (double*) xmom_explicit_update -> data,
585                                       number_of_elements,
586                                       (double*) max_speed_array -> data);
587   
588   
589    Py_DECREF(neighbours);
590    Py_DECREF(neighbour_vertices);
591    Py_DECREF(normals);
592    Py_DECREF(areas);
593    Py_DECREF(stage_vertex_values);
594    Py_DECREF(xmom_vertex_values);
595    Py_DECREF(bed_vertex_values);
596    Py_DECREF(height_vertex_values);
597    Py_DECREF(velocity_vertex_values);
598    Py_DECREF(stage_boundary_values);
599    Py_DECREF(xmom_boundary_values);
600    Py_DECREF(bed_boundary_values);
601    Py_DECREF(height_boundary_values);
602    Py_DECREF(velocity_boundary_values);
603    Py_DECREF(stage_explicit_update);
604    Py_DECREF(xmom_explicit_update);
605    Py_DECREF(max_speed_array);
606   
607   
608    // Return updated flux timestep
609    return Py_BuildValue("d", timestep);
610}
611
612
613
614//-------------------------------
615// Method table for python module
616//-------------------------------
617
618static struct PyMethodDef MethodTable[] = {
619  {"compute_fluxes_ext", compute_fluxes_ext, METH_VARARGS, "Print out"},
620  {"compute_fluxes_vel_ext", compute_fluxes_vel_ext, METH_VARARGS, "Print out"},
621  {NULL, NULL}
622};
623
624// Module initialisation
625void initcomp_flux_vel_ext(void){
626  Py_InitModule("comp_flux_vel_ext", MethodTable);
627  import_array();
628}
Note: See TracBrowser for help on using the repository browser.