source: trunk/anuga_work/development/2010-projects/anuga_1d/utilities/solver.h @ 8255

Last change on this file since 8255 was 8255, checked in by paul, 12 years ago

solver.h accidentally delete in last commit. Should have been moved from sqpipe to utilities

File size: 11.2 KB
Line 
1/**********************************************************
2Generic params class
3**********************************************************/
4struct params;
5
6// vtable
7struct params_vtable { 
8  struct params* (*destroy) (struct params *q);
9};
10
11// structure
12struct params {
13  struct params_vtable *vtable;
14 
15  double epsilon;
16  double cfl;
17};
18
19// Public API
20
21// Destruction
22struct params* params_destroy(struct params *q);
23
24// method declarations
25
26// method implementations
27struct params* params_destroy(struct params *q) {
28  return q->vtable->destroy(q);
29}
30/**********************************************************/
31
32
33/**********************************************************
34Generic quantity class
35**********************************************************/
36struct quantity;
37
38// vtable
39struct quantity_vtable {
40  double* (*flux_formula) (struct quantity *q, double normal, struct params *p, double *quantityflux);
41  double (*sound_speed) (struct quantity *q, struct params *p);
42  double (*get_conserved) (struct quantity *q, int k, double normal);
43  struct quantity* (*destroy) (struct quantity *q);
44};
45
46// structure
47struct quantity {
48  struct quantity_vtable *vtable;
49};
50
51// Public API
52// Destruction
53struct quantity* quantity_destroy(struct quantity *q);
54
55// method declarations
56double* quantity_flux_formula (struct quantity *q, double normal, struct params *p, double *quantityflux);
57double quantity_sound_speed (struct quantity *q, struct params *p);
58double quantity_get_conserved (struct quantity *q, int k, double normal);
59
60// method implementations
61double* quantity_flux_formula (struct quantity *q, double normal, struct params *p, double *quantityflux) {
62  return q->vtable->flux_formula(q, normal, p, quantityflux);
63}
64
65double quantity_sound_speed (struct quantity *q, struct params *p) {
66  return q->vtable->sound_speed(q, p);
67}
68
69double quantity_get_conserved (struct quantity *q, int k, double normal) {
70  return q->vtable->get_conserved(q, k, normal);
71}
72
73struct quantity* quantity_destroy(struct quantity *q) {
74  return q->vtable->destroy(q);
75}
76/**********************************************************/
77
78
79/**********************************************************
80Generic edge class
81**********************************************************/
82struct edge;
83
84// vtable
85struct edge_vtable{
86  double* (*flux_function) (struct edge *e, struct params *p, double *edgeflux, int num_eqns);
87  double (*extreme_sound_speeds) (struct edge *e, struct params *p);
88  struct edge* (*destroy) (struct edge *e);
89};
90
91// structure
92struct edge {
93  struct edge_vtable *vtable;
94  struct quantity *qin, *qout;
95  double normal;
96  double smin, smax;
97};
98
99// Public API
100// Destruction
101struct edge* edge_destroy(struct edge *e);
102
103// method declarations
104double* edge_flux_function (struct edge *e, struct params *p, double *edgeflux, int num_eqns);
105double edge_extreme_sound_speeds (struct edge *e, struct params *p);
106
107// method implementations
108double* edge_flux_function (struct edge *e, struct params *p, double *edgeflux, int num_eqns) {
109  return e->vtable->flux_function(e, p, edgeflux, num_eqns);
110}
111
112double edge_extreme_sound_speeds (struct edge *e, struct params *p) {
113  return e->vtable->extreme_sound_speeds(e, p);
114}
115
116struct edge* edge_destroy(struct edge *e) {
117  return e->vtable->destroy(e);
118}
119/**********************************************************/
120
121
122/**********************************************************
123Generic cell class
124**********************************************************/
125struct cell;
126
127// vtable
128struct cell_vtable{
129  double* (*flux_function) (struct cell *c, struct params *p, double *cellflux, int num_eqns);
130  double (*extreme_sound_speeds) (struct cell *c, struct params *p);
131  double* (*forcing_terms) (struct cell *c, struct params *p, double *cellforce);
132  struct cell* (*destroy) (struct cell *c);
133};
134
135// structure
136struct cell {
137  struct cell_vtable *vtable;
138  struct edge **edges;
139  int num_edges;
140};
141
142// Public API
143
144// Destruction
145struct cell* cell_destroy(struct cell *c);
146
147// method declarations
148double* cell_flux_function (struct cell *c, struct params *p, double *cellflux, int num_eqns);
149double cell_extreme_sound_speeds (struct cell *c, struct params *p);
150double* cell_forcing_terms (struct cell *c, struct params *p, double *cellforce);
151
152// method implementations
153double* cell_flux_function (struct cell *c, struct params *p, double *cellflux, int num_eqns) {
154  return c->vtable->flux_function(c, p, cellflux, num_eqns);
155}
156
157double cell_extreme_sound_speeds (struct cell *c, struct params *p) {
158  return c->vtable->extreme_sound_speeds(c, p);
159}
160
161double* cell_forcing_terms (struct cell *c, struct params *p, double *cellforce) {
162  return c->vtable->forcing_terms(c, p, cellforce);
163}
164
165struct cell* cell_destroy(struct cell *c) {
166  return c->vtable->destroy(c);
167}
168/**********************************************************/
169
170
171/**********************************************************
172Generic quantities class
173**********************************************************/
174struct quantities;
175
176// vtable
177struct quantities_vtable{
178  struct quantity* (*get_quantity) (struct quantities *qs, int i, struct quantity* q);
179  void (*update) (struct quantities *qs, double *flux, int k);
180  struct quantities* (*destroy) (struct quantities *qs);
181};
182
183// structure
184struct quantities {
185  struct quantities_vtable *vtable;
186};
187
188// Public API
189
190// Destruction
191struct quantities* quantities_destroy(struct quantities *qs);
192
193// method declarations
194struct quantity* quantities_get_quantity(struct quantities *qs, int i, struct quantity *q); 
195void quantities_update (struct quantities *qs, double *flux, int k);
196
197// method implementations
198struct quantity* quantities_get_quantity(struct quantities *qs, int i, struct quantity *q) {
199  return qs->vtable->get_quantity(qs, i, q);
200}
201
202void quantities_update (struct quantities *qs, double *flux, int k) {
203  return qs->vtable->update(qs, flux, k);
204}
205
206struct quantities* quantities_destroy(struct quantities *qs) {
207  return qs->vtable->destroy(qs);
208}
209/**********************************************************/
210
211/**********************************************************
212Generic domain class
213**********************************************************/
214struct domain;
215
216// vtable
217struct domain_vtable {
218  struct edge* (*new_edge) (struct domain *D);
219  struct cell* (*new_cell) (struct domain *D);
220  double (*compute_fluxes) (struct domain *D);
221  struct cell* (*get_cell) (struct domain *d, int i, struct cell *c); 
222  struct domain* (*destroy) (struct domain *D);
223};
224
225// structure
226struct domain {
227  struct domain_vtable *vtable;
228
229  struct quantities *vertex_values;
230  struct quantities *boundary_values;
231  struct quantities *explicit_update;
232  long* neighbours;
233  long* neighbour_vertices;
234  double* normals;
235  double* areas;
236  int number_of_elements;
237  int number_of_equations;
238  double *max_speed_array;
239  double timestep;
240  struct params *params;
241};
242
243// Public API
244// Destruction
245struct domain* domain_destroy(struct domain* D);
246
247// method declarations
248struct edge* domain_new_edge(struct domain *qs);
249struct cell* domain_new_cell(struct domain *qs);
250double domain_compute_fluxes (struct domain *D);
251struct cell* domain_get_cell(struct domain *d, int i, struct cell *c); 
252
253// method implementations
254struct edge* domain_new_edge(struct domain *qs) {
255  return qs->vtable->new_edge(qs);
256}
257
258struct cell* domain_new_cell(struct domain *qs) {
259  return qs->vtable->new_cell(qs);
260}
261
262double domain_compute_fluxes (struct domain *D) {
263  return D->vtable->compute_fluxes(D);
264}
265
266struct cell* domain_get_cell(struct domain *D, int i, struct cell *c) {
267  return D->vtable->get_cell(D, i, c);
268}
269
270struct domain* domain_destroy(struct domain* D) {
271  return D->vtable->destroy(D);
272}
273/**********************************************************/
274
275
276/**********************************************************
277Generic methods
278**********************************************************/
279// Declarations
280double domain_compute_fluxes_generic(struct domain *D);
281struct cell* sqpipe_domain_get_cell(struct domain *D, int i, struct cell *c);
282double* edge_flux_function_godunov (struct edge *c, struct params *p, double *edgeflux, int num_eqns);
283double* cell_flux_function_generic (struct cell *c, struct params *p, double *cellflux, int num_eqns);
284
285// Implementations
286
287// Computational function for flux computation
288// This iterates over cells.
289double domain_compute_fluxes_generic (struct domain *D) {
290  double flux[D->number_of_equations];
291  double max_speed;
292  int k, i;
293  struct cell *c;
294   
295  // pre-create a cell object to use in the loop
296  // so we need only allocate memory once
297  c = domain_new_cell(D);
298
299  for (k=0; k<D->number_of_elements; k++) {
300    c = domain_get_cell(D, k, c);
301   
302    // Compute sound speeds (this updates c) and update timestep
303    max_speed = cell_extreme_sound_speeds(c, D->params);
304    if (max_speed > D->params->epsilon) {                                   
305      D->timestep = min(D->timestep, 0.5*D->params->cfl * D->areas[k]/max_speed); 
306    }
307
308    // Compute flux
309    cell_flux_function(c, D->params, flux, D->number_of_equations);   
310    for (i=0; i<D->number_of_equations; i++) {
311      flux[i] /= D->areas[k];
312    }
313    quantities_update(D->explicit_update, flux, k);
314
315    //Keep track of maximal speeds
316    D->max_speed_array[k]=max_speed;
317  }
318 
319  cell_destroy(c);
320
321  return D->timestep;   
322}
323
324struct cell* domain_get_cell_generic(struct domain *D, int k, struct cell *c) {
325  int i, ki, n, m, nm;
326
327  for (i=0; i<c->num_edges; i++) {
328    ki = k*(c->num_edges) + i;
329    c->edges[i]->normal = D->normals[ki];     
330    n = D->neighbours[ki];
331
332    c->edges[i]->qin = quantities_get_quantity(D->vertex_values, ki, c->edges[i]->qin);
333
334    if (n<0) {
335      m = -n-1;
336      c->edges[i]->qout = quantities_get_quantity(D->boundary_values, m, c->edges[i]->qout);
337    } else {
338      m = D->neighbour_vertices[ki];
339      nm = n*2+m;
340      c->edges[i]->qout = quantities_get_quantity(D->vertex_values, nm, c->edges[i]->qout);
341    }
342  } 
343
344  return c;
345}
346
347
348// Generic Godunov flux computation method
349double* edge_flux_function_godunov (struct edge *e, struct params *p, double *edgeflux, int num_eqns) {
350  int i;
351  double flux_left[num_eqns], flux_right[num_eqns];
352  double denom;
353
354  // Flux contribution from left side of  edge
355  quantity_flux_formula(e->qin, e->normal, p, flux_left);
356
357  // Flux contribution from right side of edge
358  quantity_flux_formula(e->qout, e->normal, p, flux_right);
359
360  // Flux computation
361  denom = e->smax - e->smin;
362  if (denom < p->epsilon) {
363    for (i=0; i<num_eqns; i++) edgeflux[i] = 0.0;
364  } else {
365    for (i=0; i<num_eqns; i++) {
366      edgeflux[i] = e->smax*flux_left[i] - e->smin*flux_right[i];
367      edgeflux[i] += e->smax*e->smin * (quantity_get_conserved(e->qout, i, e->normal) - quantity_get_conserved(e->qin, i, e->normal));
368      edgeflux[i] /= denom;
369    }
370  }
371
372  return edgeflux;
373}
374
375double* cell_flux_function_generic (struct cell *c, struct params *p, double *cellflux, int num_eqns) {
376  int i, j;
377  double cellforce[num_eqns];
378  double flux[num_eqns];
379
380  // Compute forcing terms first
381  cell_forcing_terms(c, p, cellforce);
382  for (i=0; i<num_eqns; i++) {
383    cellflux[i] = -cellforce[i];
384  }
385
386  // Compute flux through each edge and append to flux
387  for (j=0; j<c->num_edges; j++) {
388    edge_flux_function(c->edges[j], p, flux, num_eqns);
389    for (i=0; i<num_eqns; i++) {
390      cellflux[i] -= flux[i];
391    }
392  }
393
394  return cellflux;
395}
396/**********************************************************/
Note: See TracBrowser for help on using the repository browser.