source: trunk/anuga_work/development/2010-projects/anuga_1d/sqpipe/sqpipe.h @ 8862

Last change on this file since 8862 was 8862, checked in by steve, 11 years ago

Code to run a pipe

File size: 17.0 KB
Line 
1/**********************************************************
2Pipe params class
3**********************************************************/
4
5struct sqpipe_params {
6  struct params super;
7
8  double g;
9  double h0;
10  double bulk_modulus;
11};
12
13// Construction
14void sqpipe_params_init(struct sqpipe_params *q);
15struct sqpipe_params* sqpipe_params_new();
16
17// Destruction
18struct params* sqpipe_params_destroy(struct params *q);
19
20// Methods
21
22// Implementation
23void sqpipe_params_init(struct sqpipe_params *q) {
24  static struct params_vtable vtable = {
25    &sqpipe_params_destroy
26  };
27  q->super.vtable = &vtable;
28 
29  ((struct params *)q)->cfl = 0.0; 
30  ((struct params *)q)->epsilon = 0.0;
31  q->g = 0.0;
32  q->h0 = 0.0;
33}
34
35struct sqpipe_params* sqpipe_params_new() {
36  struct sqpipe_params *p = malloc(sizeof(struct sqpipe_params));
37
38  sqpipe_params_init(p);
39
40  return p; 
41}
42
43struct params* sqpipe_params_destroy(struct params *q) {
44  free(q);
45  q = NULL;
46 
47  return q;
48}
49/**********************************************************/
50
51
52/**********************************************************
53Pipe quantity class
54This is a virtual class and should never be created.
55The inherting class needs to implement
56    init, new, flux_formula0, flux_formula1, sound_speed,
57    get_conserved
58**********************************************************/
59
60struct sqpipe_quantity {
61  struct quantity super;
62
63  double a;
64  double d;
65  double w;
66  double h;
67  double u;
68  double z; 
69  double b;
70  double t;
71  long state;
72};
73
74// Construction
75void sqpipe_quantity_init(struct sqpipe_quantity *q);
76struct sqpipe_quantity* sqpipe_quantity_new();
77
78// Destruction
79struct quantity* sqpipe_quantity_destroy(struct quantity *q);
80
81// Methods
82double* sqpipe_quantity_flux_formula (struct quantity *q, double normal, struct params *p, double *quantityflux);
83double sqpipe_quantity_sound_speed (struct quantity *q, struct params *p);
84double sqpipe_quantity_get_conserved (struct quantity *q, int k, double normal);
85
86// Helper methods
87double* sqpipe_quantity_free_surface_flux_formula (struct quantity *q, double normal, struct params *p, double *quantityflux);
88double* sqpipe_quantity_pressurised_flux_formula (struct quantity *q, double normal, struct params *p, double *quantityflux);
89double sqpipe_quantity_free_surface_sound_speed (struct quantity *q, struct params *p);
90double sqpipe_quantity_pressurised_sound_speed (struct quantity *q, struct params *p);
91
92// Implementation
93double* sqpipe_quantity_flux_formula (struct quantity *q, double normal, struct params *p, double *quantityflux) {
94  if (((struct sqpipe_quantity *)q)->state == 0) {
95    return sqpipe_quantity_free_surface_flux_formula(q, normal, p, quantityflux);
96  } else {
97    return sqpipe_quantity_pressurised_flux_formula(q, normal, p, quantityflux);
98  }
99}
100
101double sqpipe_quantity_sound_speed (struct quantity *q, struct params *p) {
102  if (((struct sqpipe_quantity *)q)->state == 0) {
103    return sqpipe_quantity_free_surface_sound_speed(q, p);
104  } else {
105    return sqpipe_quantity_pressurised_sound_speed(q, p);
106  }
107}
108
109double sqpipe_quantity_get_conserved (struct quantity *q, int k, double normal) {
110  struct sqpipe_quantity *p = (struct sqpipe_quantity*) q;
111  double c;
112 
113  switch (k) {
114  case 0:
115    c = p->a;
116    break;
117  case 1:
118    // This should be normal^2 p->d and normal is +/- 1
119    c = p->d;
120    break;
121  default:
122    c = 0;
123  }
124  return c;
125}
126
127
128// Flux formula taking into account the normal
129// Note u, d should be normal*u, normal*d but since normal is +/- 1
130// (normal*u) * (normal*d) = u*d
131double* sqpipe_quantity_free_surface_flux_formula (struct quantity *q, double normal, struct params *p, double *quantityflux) {
132  struct sqpipe_quantity *pq = (struct sqpipe_quantity*) q;
133  struct sqpipe_params *sp = (struct sqpipe_params *) p;
134
135  //quantityflux[0] = (normal * pq->u) * quantity_get_conserved(q, 0, normal);
136  //quantityflux[1] = normal * (pq->u * quantity_get_conserved(q, 1, normal) + 0.5 * sp->g * pq->h *pq->h);
137  quantityflux[0] = (normal * pq->u) * pq->a;
138  quantityflux[1] = normal * (pq->u * pq->d + 0.5 * sp->g * pq->h *pq->h);
139
140  return quantityflux;
141}
142
143double* sqpipe_quantity_pressurised_flux_formula (struct quantity *q, double normal, struct params *p, double *quantityflux) {
144  struct sqpipe_quantity *pq = (struct sqpipe_quantity*) q;
145  struct sqpipe_params *sp = (struct sqpipe_params *) p;
146 
147  quantityflux[0] = (normal * pq->u) * pq->a; 
148  quantityflux[1] = normal * (pq->u * pq->d + sp->bulk_modulus*(pq->h - pq->t) + 0.5 * sp->g * pq->t * pq->t);
149
150  return quantityflux;
151}
152
153double sqpipe_quantity_free_surface_sound_speed (struct quantity *q, struct params *p) {
154  struct sqpipe_quantity *sq = (struct sqpipe_quantity*) q;
155  struct sqpipe_params *sp = (struct sqpipe_params*) p; 
156
157  return sqrt(sp->g * sq->h);
158}
159
160double sqpipe_quantity_pressurised_sound_speed (struct quantity *q, struct params *p) {
161  return ((struct sqpipe_params *)p)->bulk_modulus;
162}
163
164void sqpipe_quantity_init(struct sqpipe_quantity *q) {
165  static struct quantity_vtable vtable = {
166    &sqpipe_quantity_flux_formula,
167    &sqpipe_quantity_sound_speed,
168    &sqpipe_quantity_get_conserved,
169    &sqpipe_quantity_destroy
170  };
171  q->super.vtable = &vtable;
172 
173  q->a = 0.0;
174  q->d = 0.0;
175  q->w = 0.0;
176  q->h = 0.0;
177  q->u = 0.0;
178  q->z = 0.0; 
179  q->b = 0.0;
180  q->t = 0.0;
181  q->state = 0;
182}
183
184struct sqpipe_quantity* sqpipe_quantity_new() {
185  struct sqpipe_quantity *p = malloc(sizeof(struct sqpipe_quantity));
186
187  return p; 
188}
189
190struct quantity* sqpipe_quantity_destroy(struct quantity *q) {
191  free(q);
192  q = NULL;
193 
194  return q;
195}
196/**********************************************************/
197
198
199/**********************************************************
200Pipe edge class
201This is a virtual class and should never be created.
202The inherting class needs to implement
203    init, new, flux_function
204**********************************************************/
205struct sqpipe_edge {
206  struct edge super;
207};
208
209// Construction
210void sqpipe_edge_init(struct sqpipe_edge *e);
211struct sqpipe_edge* sqpipe_edge_new();
212
213// Destruction
214struct edge* sqpipe_edge_destroy(struct edge *e);
215
216// Methods
217double sqpipe_edge_extreme_sound_speeds (struct edge *e, struct params *p);
218
219// Implementation
220double sqpipe_edge_extreme_sound_speeds (struct edge *e, struct params *p) {
221  double soundspeed_left, soundspeed_right, max_speed;
222  struct sqpipe_quantity *qin = (struct sqpipe_quantity*) e->qin;
223  struct sqpipe_quantity *qout = (struct sqpipe_quantity*) e->qout;
224
225  soundspeed_left = quantity_sound_speed(e->qin, p);
226  soundspeed_right = quantity_sound_speed(e->qout, p);
227
228  e->smax = max(e->normal * qin->u + soundspeed_left, e->normal * qout->u + soundspeed_right);
229  if (e->smax < 0.0) e->smax = 0.0;
230       
231  e->smin = min(e->normal * qin->u - soundspeed_left, e->normal * qout->u - soundspeed_right);
232  if (e->smin > 0.0) e->smin = 0.0;
233
234  if (e->smax - e->smin < p->epsilon) {
235    max_speed = 0.0;
236  } else {
237    max_speed = max(fabs(e->smin), fabs(e->smax));
238  }
239
240  return max_speed;
241}
242
243void sqpipe_edge_init(struct sqpipe_edge *e) {
244  static struct edge_vtable vtable = {
245    &edge_flux_function_godunov,
246    &sqpipe_edge_extreme_sound_speeds,
247    &sqpipe_edge_destroy
248  };
249  e->super.vtable = &vtable;
250
251  ((struct edge *)e)->qin = NULL;
252  ((struct edge *)e)->qout = NULL;
253  ((struct edge *)e)->normal = 0.0;
254  ((struct edge *)e)->smax = 0.0;
255  ((struct edge *)e)->smin = 0.0;
256}
257
258struct sqpipe_edge* sqpipe_edge_new() {
259  struct sqpipe_edge *p = malloc(sizeof(struct sqpipe_edge));
260
261  return p; 
262}
263
264struct edge* sqpipe_edge_destroy(struct edge *e) { 
265  e->qin = quantity_destroy(e->qin);
266  e->qout = quantity_destroy(e->qout);
267 
268  free(e);
269  e = NULL;
270 
271  return e;
272}
273/**********************************************************/
274
275/**********************************************************
276Pipe cell class
277This is a virtual class and should never be created.
278The inherting class needs to implement
279    init, new, flux_function, forcing_terms
280**********************************************************/
281struct sqpipe_cell {
282  struct cell super;
283 
284  long state;
285};
286
287// Construction
288void sqpipe_cell_init(struct sqpipe_cell *e);
289struct sqpipe_cell* sqpipe_cell_new();
290
291// Destruction
292struct cell* sqpipe_cell_destroy(struct cell *c);
293
294// Methods
295double sqpipe_cell_extreme_sound_speeds (struct cell *c, struct params *p);
296double* sqpipe_cell_forcing_terms (struct cell *c, struct params *p, double *cellforce);
297
298// Helper methods
299double* sqpipe_cell_free_surface_forcing_terms (struct cell *c, struct params *p, double *cellforce);
300double* sqpipe_cell_pressurised_forcing_terms (struct cell *c, struct params *p, double *cellforce);
301
302// Implementation
303double sqpipe_cell_extreme_sound_speeds (struct cell *c, struct params *p) {
304  int i;
305  // The compiler doesn't know c->num_edges is positive hence whether the
306  // loop will run. This throws the warning:
307  // ‘max_speed’ may be used uninitialized in this function
308  // and the same for tmp_max_speed
309  // We initiallise them to avoid the warning since we know nothing could
310  // possibly go wrong...
311  double max_speed = 0.0, tmp_max_speed = 0.0;
312
313  for (i=0; i<c->num_edges; i++) {
314    tmp_max_speed = edge_extreme_sound_speeds(c->edges[i], p);
315    max_speed = max(max_speed, tmp_max_speed);
316  }
317
318  return max_speed;
319}
320
321double* sqpipe_cell_forcing_terms (struct cell *c, struct params *p, double *cellforce) {
322  if (((struct sqpipe_cell *)c)->state == 0) {
323    return sqpipe_cell_free_surface_forcing_terms(c, p, cellforce);   
324  } else {
325    return sqpipe_cell_pressurised_forcing_terms(c, p, cellforce);
326  }
327}
328
329double* sqpipe_cell_free_surface_forcing_terms (struct cell *c, struct params *p, double *cellforce) {
330  struct sqpipe_quantity *qin = (struct sqpipe_quantity *) c->edges[0]->qout;
331  struct sqpipe_quantity *qout = (struct sqpipe_quantity *) c->edges[1]->qin;
332  struct sqpipe_params *sp = (struct sqpipe_params *) p;
333
334  cellforce[0] = 0.0; 
335  cellforce[1] = 0.5 * sp->g * (qout->h + qin->h) * (qout->z - qin->z);
336 
337  return cellforce;
338}
339
340double* sqpipe_cell_pressurised_forcing_terms (struct cell *c, struct params *p, double *cellforce) {
341  struct sqpipe_quantity *qin = (struct sqpipe_quantity *) c->edges[0]->qout;
342  struct sqpipe_quantity *qout = (struct sqpipe_quantity *) c->edges[1]->qin;
343  struct sqpipe_params *sp = (struct sqpipe_params *) p;
344
345  cellforce[0] = 0.0;
346  cellforce[1] = sp->bulk_modulus * (sp->g * (0.5*(qout->h + qin->h) - 0.5*(qout->t + qin->t)) * (qout->b - qin->b) + sp->g * (0.5*(qout->h + qin->h) - 0.5*(qout->t + qin->t)) * 0.5*(qout->b + qin->b) * (qout->t - qin->t) * 1/(0.5*(qout->t + qin->t)));
347
348  return cellforce;
349}
350
351
352void sqpipe_cell_init(struct sqpipe_cell *c) {
353  static struct cell_vtable vtable = {
354    &cell_flux_function_generic, 
355    &sqpipe_cell_extreme_sound_speeds,
356        &sqpipe_cell_forcing_terms,
357    &sqpipe_cell_destroy
358  };
359  c->super.vtable = &vtable;
360
361  // Can't set edges to NULL here since sqpipe_cell_new() has allocated memory
362  // If a cell is created without using cell_new(), then edges will be an
363  // unitialised pointer.
364  // Can't allocate memory here since init should not allocate memory
365  // The moral: Use cell_new() to create cells!
366
367  c->super.num_edges = 2;
368  ((struct sqpipe_cell *)c)->state = 0;
369}
370
371struct sqpipe_cell* sqpipe_cell_new() {
372  struct sqpipe_cell *c = malloc(sizeof(struct sqpipe_cell));
373
374  // Allocate memory for a length 2 array of pointers to edges
375  ((struct cell *)c)->edges = (struct edge  **) malloc(2 * sizeof(struct sqpipe_edge *));
376 
377  return c;
378}
379
380struct cell* sqpipe_cell_destroy(struct cell *c) { 
381  int i;
382
383  for (i=0; i<c->num_edges; i++) {
384    c->edges[i] = edge_destroy(c->edges[i]);
385  } 
386
387  free(c->edges);
388  c->edges = NULL;
389  free(c);
390  c = NULL;
391 
392  return c;
393}
394/**********************************************************/
395
396
397/**********************************************************
398Pipe quantities class
399This is a virtual class and should never be created.
400The inherting class needs to implement:
401    init, new, get_quantities
402**********************************************************/
403struct sqpipe_quantities {
404  struct quantities super;
405
406  double *a;
407  double *d;
408  double *w;
409  double *h;
410  double *u;
411  double *z; 
412  double *b;
413  double *t;
414};
415
416// Construction
417void sqpipe_quantities_init(struct sqpipe_quantities *q);
418struct sqpipe_quantities* sqpipe_quantities_new();
419
420// Destruction
421struct quantities* sqpipe_quantities_destroy(struct quantities *qs);
422
423// Methods
424struct quantity* sqpipe_quantities_get_quantity(struct quantities *qs, int i, struct quantity *q);
425void sqpipe_quantities_update (struct quantities *qs, double *flux, int k);
426
427// Implementation
428struct quantity* sqpipe_quantities_get_quantity(struct quantities *qs, int i, struct quantity *q) { 
429  struct sqpipe_quantities *ps = (struct sqpipe_quantities *) qs;
430  struct sqpipe_quantity *p = (struct sqpipe_quantity *) q;
431
432  p->a = ps->a[i];
433  p->d = ps->d[i];
434  p->w = ps->w[i];
435  p->h = ps->h[i];
436  p->u = ps->u[i]; 
437  p->z = ps->z[i];
438  p->b = ps->b[i];
439  p->t = ps->t[i];
440
441  return q;
442}
443
444void sqpipe_quantities_update (struct quantities *qs, double *flux, int k) {
445  struct sqpipe_quantities *ps = (struct sqpipe_quantities *) qs;
446  ps->a[k] = flux[0];
447  ps->d[k] = flux[1];
448}
449
450
451void sqpipe_quantities_init(struct sqpipe_quantities *q) {
452  static struct quantities_vtable vtable = {
453    &sqpipe_quantities_get_quantity,
454    &sqpipe_quantities_update,
455    &sqpipe_quantities_destroy
456  };
457  q->super.vtable = &vtable;
458
459
460  q->a = NULL;
461  q->d = NULL;
462  q->w = NULL;
463  q->h = NULL;
464  q->u = NULL;
465  q->z = NULL; 
466  q->b = NULL;
467  q->t = NULL;
468}
469
470struct sqpipe_quantities* sqpipe_quantities_new() {
471  struct sqpipe_quantities *p = malloc(sizeof(struct sqpipe_quantities));
472
473  return p; 
474}
475
476
477struct quantities* sqpipe_quantities_destroy(struct quantities *qs) {
478  free(qs);
479  qs = NULL;
480 
481  return qs;
482}
483/**********************************************************/
484
485
486/**********************************************************
487Pipe domain class
488This is a virtual class and should never be created.
489The inheriting class needs to implement:
490  init, new, compute_fluxes
491**********************************************************/
492struct sqpipe_domain {
493  struct domain super;
494  long *state;
495};
496
497// Construction
498void sqpipe_domain_init(struct sqpipe_domain *d);
499struct sqpipe_domain* sqpipe_domain_new();
500
501// Destruction
502struct domain* sqpipe_domain_destroy(struct domain *d);
503
504// Methods
505struct cell* sqpipe_domain_get_cell(struct domain *D, int k, struct cell *c);
506
507// Implementation
508struct cell* sqpipe_domain_get_cell(struct domain *D, int k, struct cell *c) {
509  struct sqpipe_cell *sc = (struct sqpipe_cell *) c;
510  struct sqpipe_domain *sD = (struct sqpipe_domain *) D;
511  int i, ki, n;
512  long state_in, state_out, state;
513 
514  // First get a generic cell
515  c = domain_get_cell_generic(D, k, c);
516
517  // Set state
518  // The state should be set to state_in for qin and state_out for qout
519  // Temporarily, I set the state of the edge, aribtrarily choosing
520  // pressurised for transition points
521  // This will be fixed when the flux is computed at the edge rather than
522  // at the quantity
523  sc->state = sD->state[k];
524  for (i = 0; i<c->num_edges; i++) {
525        // The inner state is that of this cell
526        state_in = sc->state;
527        // The outer state is that of the corresponding neighbour cell
528        ki = k*(c->num_edges) + i;
529        n = D->neighbours[ki];
530        state_out = sD->state[n];
531       
532        // If both in and out state are the same, choose that state
533        // Otherwise, choose pressurised
534        if (state_in == state_out) {
535                state = state_in;
536        } else {
537                state = 1;
538        }
539    ((struct sqpipe_quantity *)(c->edges[i]->qin))->state = state;     
540    ((struct sqpipe_quantity *)(c->edges[i]->qout))->state = state;
541  }
542 
543  return c;
544}
545
546
547void sqpipe_domain_init(struct sqpipe_domain *d) {
548  static struct domain_vtable vtable = {
549    NULL,
550    NULL,
551    &domain_compute_fluxes_cells_generic,
552    &sqpipe_domain_get_cell,
553    &sqpipe_domain_destroy
554  };
555  d->super.vtable = &vtable;
556
557  ((struct domain *)d)->number_of_equations = 2;
558
559  ((struct domain *)d)->vertex_values = NULL;
560  ((struct domain *)d)->boundary_values = NULL;
561  ((struct domain *)d)->explicit_update = NULL;
562  ((struct domain *)d)->neighbours = NULL;
563  ((struct domain *)d)->neighbour_vertices = NULL;
564  ((struct domain *)d)->normals = NULL;
565  ((struct domain *)d)->areas = NULL;
566  ((struct domain *)d)->number_of_elements = 0; 
567
568  ((struct domain *)d)->timestep = 0.0;
569  ((struct domain *)d)->max_speed_array = NULL;
570
571  d->state = NULL;
572  // Can't set params to NULL here since sqpipe_domain_new() has allocated
573  // memory
574  // If a domain is created without using domain_new(), then params will be an
575  // unitialised pointer.
576
577  // Can't allocate memory here since init should not allocate memory
578  // The moral: Use domain_new() to create domains! 
579}
580
581struct sqpipe_domain* sqpipe_domain_new() {
582  struct sqpipe_domain *p = malloc(sizeof(struct sqpipe_domain));
583
584  ((struct domain *)p)->params = (struct params *) sqpipe_params_new();
585
586  return p;
587}
588
589
590struct domain* sqpipe_domain_destroy(struct domain *D) {
591  D->vertex_values = quantities_destroy(D->vertex_values);
592  D->boundary_values = quantities_destroy(D->boundary_values);
593  D->explicit_update = quantities_destroy(D->explicit_update);
594  D->params = params_destroy(D->params);
595  free(D);
596  D = NULL;
597
598  return D;
599}
600/**********************************************************/
601
602
Note: See TracBrowser for help on using the repository browser.