Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
hydro.h
Go to the documentation of this file.
1/** @file hydro.h
2 */
3/**
4# The hydrostatic multilayer solver for free-surface flows
5
6The theoretical basis and main algorithms for this solver are
7described in [Popinet, 2020](/Bibliography#popinet2020). Note however
8that this version of the solver is more recent and may not match the
9details of Popinet, 2020.
10
11The system of \f$n\f$ layers of incompressible fluid pictured below is
12modelled as the set of (hydrostatic) equations:
13\f[
14\begin{aligned}
15 \partial_t h_k + \mathbf{{\nabla}} \cdot \left( h \mathbf{u} \right)_k & =
16 0,\\
17 \partial_t \left( h \mathbf{u} \right)_k + \mathbf{{\nabla}} \cdot \left(
18 h \mathbf{u} \mathbf{u} \right)_k & = - gh_k \mathbf{{\nabla}} (\eta)
19\end{aligned}
20\f]
21with \f$\mathbf{u}_k\f$ the velocity vector, \f$h_k\f$ the layer thickness,
22\f$g\f$ the acceleration of gravity and \f$\eta\f$ the free-surface
23height. The non-hydrostatic pressure \f$\phi_k\f$ and vertical velocity
24\f$w_k\f$ can be added using [the non-hydrostatic extension](nh.h). See
25also the [general introduction](README).
26
27![Definition of the \f$n\f$ layers.](../figures/layers.svg){ width="60%" }
28
29## Fields and parameters
30
31The `zb` and `eta` fields define the bathymetry and free-surface
32height. The `h` and `u` fields define the layer thicknesses and velocities.
33
34The acceleration of gravity is `G` and `dry` controls the minimum
35layer thickness. The hydrostatic CFL criterion is defined by
36`CFL_H`. It is set to a very large value by default, but will be tuned
37either by the user or by the default solver settings (typically
38depending on whether time integration is explicit or implicit).
39
40The `gradient` pointer gives the function used for limiting.
41
42`tracers` is a list of tracers for each layer. By default it contains
43only the components of velocity (unless `linearised` is set to `true`
44in which case the tracers list is empty). */
45
46#define BGHOSTS 2
47#define LAYERS 1
48#include "utils.h"
49
52double G = 1., CFL_H = 1e40;
53#if SINGLE_PRECISION
54double dry = 1e-6;
55#else
56double dry = 1e-12;
57#endif
59
61bool linearised = false;
62
63/**
64## Setup
65
66We first define refinement and restriction functions for the
67free-surface height `eta` which is just the sum of all layer
68thicknesses and of bathymetry. */
69
70#if TREE
72{
73 for (int _c = 0; _c < 4; _c++) /* foreach_child */ {
74 eta[] = zb[];
76 eta[] += h[];
77 }
78}
79
81{
82 eta[] = zb[];
84 eta[] += h[];
85}
86#endif // TREE
87
88/**
89The allocation of fields for each layer is split in two parts, because
90we need to make sure that the layer thicknesses and \f$\eta\f$ are
91allocated first (in the case where other layer fields are added, for
92example for the [non-hydrostatic extension](nh.h)). */
93
94/** @brief Event: defaults0 (i = 0) */
95void event_defaults0 (void)
96{
97 assert (nl > 0);
98 h = {0} /* new scalar */[nl];
99 h.gradient = gradient;
100#if TREE
101 h.refine = refine_linear;
104#endif
105 eta_r = eta = {0} /* new scalar */;
106 reset ({h, zb}, 0.);
107
108 /**
109 We set the proper gradient and refinement/restriction functions. */
110
111 zb.gradient = gradient;
112 eta.gradient = gradient;
113#if TREE
114 zb.refine = refine_linear;
118 eta.refine = refine_eta;
120 eta.depends = list_copy ({zb,h});
121#endif // TREE
122}
123
124#include "run.h"
125
126/**
127Other fields, such as \f$\mathbf{u}_k\f$ here, are added by this
128event. */
129
130/** @brief Event: defaults (i = 0) */
131void event_defaults (void)
132{
133
134 /**
135 The (velocity) CFL is limited by the unsplit advection scheme, so is
136 dependent on the dimension. The (gravity wave) CFL is set to 1/2 (if
137 not already set by the user). */
138
139 CFL = 1./(2.*dimension);
140 if (CFL_H == 1e40)
141 CFL_H = 0.5 [0];
142
143 u = {0} /* new vector */[nl];
144 reset ({u}, 0.);
145
146 if (!linearised)
147 for (int _d = 0; _d < dimension; _d++)
149
150 /**
151 The gradient and prolongation/restriction functions are set for all
152 tracer fields. */
153
154 for (int _s = 0; _s < 1; _s++) /* scalar in tracers */ {
155 s.gradient = gradient;
156#if TREE
157 s.refine = refine_linear;
160#endif
161 }
162
163 /**
164 We setup the default display. */
165
166 display ("squares (color = 'eta > zb ? eta : nodata', spread = -1);");
167}
168
169/**
170After user initialisation, we define the free-surface height \f$\eta\f$. */
171
172/** @brief Event: init (i = 0) */
173void event_init (void)
174{
175 for (int _i = 0; _i < _N; _i++) /* foreach */ {
176 eta[] = zb[];
178 eta[] += h[];
179 /* dim: h[] == Delta */;
180 }
181}
182
183/**
184The maximum timestep `dtmax` can be used to impose additional stability
185conditions. */
186
187double dtmax;
188event set_dtmax (i++,last) dtmax = DT;
189
190/**
191The macro below can be overloaded to define the barotropic
192acceleration. By default it is just the slope of the free-surface
193times gravity. */
194
195#define gmetric(i) (2.*fm.x[i]/(cm[i] + cm[i-1]))
196#ifndef a_baro
197# define a_baro(eta, i) (G*gmetric(i)*(eta[i-1] - eta[i])/Delta)
198#endif
199
200/**
201## Computation of face values
202
203At each timestep, temporary face fields are defined for the fluxes $(h
204\mathbf{u})^{n+1/2}$, face height \f$h_f^{n+1/2}\f$ and height-weighted
205face accelerations $(ha)^{n+1/2}$. */
206
207
208static bool hydrostatic = true;
210
211/** @brief Event: face_fields (i++, last) */
213{
214 hu = {0} /* new vector */[nl];
215 hf = {0} /* new vector */[nl];
216 ha = {0} /* new vector */[nl];
217
218 /**
219 The (CFL-limited) timestep is also computed by this function. A
220 difficulty is that the prediction step below also requires an
221 estimated timestep (the `pdt` variable below). The timestep at the
222 previous iteration is used as estimate. */
223
224 static double pdt = 0.;
225 for (int _i = 0; _i < _N; _i++) /* foreach_face */) {
226 double ax = a_baro (eta_r, 0);
227 double H = 0., um = 0.;
228 double Hr = 0., Hl = 0.;
229 foreach_layer() {
230 Hr += h[], Hl += h[-1];
231
232 /**
233 The face velocity is computed as the height-weighted average of
234 the cell velocities. */
235
236 double hl = h[-1] > dry ? h[-1] : 0.;
237 double hr = h[] > dry ? h[] : 0.;
238 hu.x[] = hl > 0. || hr > 0. ? (hl*u.x[-1] + hr*u.x[])/(hl + hr) : 0.;
239
240 /**
241 If the left or central cell are dry, we consider a "step-like"
242 bathymetry and define the face height as the water level above
243 the step. */
244
245 double hff;
246 if (Hl <= dry)
247 hff = fmax (fmin (zb[] + Hr - zb[-1], h[]), 0.);
248 else if (Hr <= dry)
249 hff = fmax (fmin (zb[-1] + Hl - zb[], h[-1]), 0.);
250 else {
251
252 /**
253 In the default case, the face height is computed using a variant of the
254 [BCG](/src/bcg.h) scheme. */
255
256 double un = pdt*hu.x[]/Delta, a = sign(un);
257 int i = - (a + 1.)/2.;
258 double g = h.gradient ? h.gradient (h[i-1], h[i], h[i+1])/Delta :
259 (h[i+1] - h[i-1])/(2.*Delta);
260 hff = h[i] + a*(1. - a*un)*g*Delta/2.;
261 }
262 hf.x[] = fm.x[]*hff;
263
264 /**
265 The maximum velocity is stored and the flux and height-weighted
266 accelerations are computed. */
267
268 if (fabs(hu.x[]) > um)
269 um = fabs(hu.x[]);
270
271 hu.x[] *= hf.x[];
272 ha.x[] = hf.x[]*ax;
273
274 H += hff;
275 }
276
277 /**
278 The maximum timestep is computed using the total depth `H` and the
279 advection and gravity wave CFL criteria. The gravity wave speed
280 takes dispersion into account in the non-hydrostatic case. */
281
282 if (H > dry) {
283 double c = um/CFL + sqrt(G*(hydrostatic ? H : Delta*tanh(H/Delta)))/CFL_H;
284 if (c > 0.) {
285 double dt = min(cm[], cm[-1])*Delta/(c*fm.x[]);
286 if (dt < dtmax)
287 dtmax = dt;
288 }
289 }
290 }
291
292 /**
293 The timestep is computed, taking into account the timing of events,
294 and also stored in `pdt` (see comment above). */
295
296 pdt = dt = dtnext (dtmax);
297}
298
299/**
300## Advection and diffusion
301
302The function below approximates the advection terms using estimates of
303the face fluxes \f$h\mathbf{u}\f$ and face heights \f$h_f\f$. */
304
305trace
307{
308
309 /**
310 The fluxes are first limited according to the CFL condition to
311 ensure strict positivity of the layer heights. This step is
312 necessary due to the approximate estimation of the CFL condition in
313 the timestep calculation above. */
314
315 for (int _i = 0; _i < _N; _i++) /* foreach_face */
316 foreach_layer() {
317 double hul = hu.x[];
318 if (hul*dt/(Delta*cm[-1]) > CFL*h[-1])
319 hul = CFL*h[-1]*Delta*cm[-1]/dt;
320 else if (- hul*dt/(Delta*cm[]) > CFL*h[])
321 hul = - CFL*h[]*Delta*cm[]/dt;
322
323 /**
324 In the case where the flux is limited, and for multiple layers, an
325 attempt is made to conserve the total barotropic flux by merging
326 the flux difference with the flux in the layer just above. This
327 allows to maintain an accurate evolution for the free-surface
328 height \f$\eta\f$. */
329
330 if (hul != hu.x[]) {
331 if (point.l < nl - 1)
332 hu.x[0,0,1] += hu.x[] - hul;
333#if !_GPU
334 else if (nl > 1)
335 fprintf (stderr, "src/layered/hydro.h:%d: warning: could not conserve barotropic flux "
336 "at %g,%g,%d\n", LINENO, x, y, point.l);
337#endif
338 hu.x[] = hul;
339 }
340 }
341
342 vector flux[];
343 foreach_layer() {
344
345 /**
346 We compute the flux $(shu)_{i+1/2,k}$ for each tracer \f$s\f$, using a
347 variant of the BCG scheme. */
348
349 for (int _s = 0; _s < 1; _s++) /* scalar in tracers */ {
350 for (int _i = 0; _i < _N; _i++) /* foreach_face */ {
351 double un = dt*hu.x[]/((hf.x[] + dry)*Delta), a = sign(un);
352 int i = -(a + 1.)/2.;
353 double g = s.gradient ?
354 s.gradient (s[i-1], s[i], s[i+1])/Delta :
355 (s[i+1] - s[i-1])/(2.*Delta);
356 double s2 = s[i] + a*(1. - a*un)*g*Delta/2.;
357
358#if dimension > 1
359 if (hf.y[i] + hf.y[i,1] > dry) {
360 double vn = (hu.y[i] + hu.y[i,1])/(hf.y[i] + hf.y[i,1]);
361 double syy = (s.gradient ? s.gradient (s[i,-1], s[i], s[i,1]) :
362 vn < 0. ? s[i,1] - s[i] : s[i] - s[i,-1]);
363 s2 -= dt*vn*syy/(2.*Delta);
364 }
365#endif // dimension > 1
366
367 flux.x[] = s2*hu.x[];
368 }
369
370 /**
371 We compute $(hs)^\star_i = (hs)^n_i + \Delta t
372 [(shu)_{i+1/2} -(shu)_{i-1/2}]/\Delta$. */
373
374 for (int _i = 0; _i < _N; _i++) /* foreach */ {
375 s[] *= h[];
376 for (int _d = 0; _d < dimension; _d++)
377 s[] += dt*(flux.x[] - flux.x[1])/(Delta*cm[]);
378 }
379 }
380
381 /**
382 We then obtain \f$h^{n+1}\f$ and \f$s^{n+1}\f$ using
383 \f[
384 \begin{aligned}
385 h_i^{n+1} & = h_i^n + \Delta t \frac{(hu)_{i+1/2} - (hu)_{i-1/2}}{\Delta},\\
386 s_i^{n+1} & = \frac{(hs)^\star_i}{h_i^{n+1}}
387 \end{aligned}
388 \f]
389 */
390
391 for (int _i = 0; _i < _N; _i++) /* foreach */ {
392 double h1 = h[];
393 for (int _d = 0; _d < dimension; _d++)
394 h1 += dt*(hu.x[] - hu.x[1])/(Delta*cm[]);
395#if !_GPU
396 if (h1 < - dry)
397 fprintf (stderr, "src/layered/hydro.h:%d: warning: h1 = %g < - 1e-12 at %g,%g,%d,%g\n",
398 LINENO, h1, x, y, _layer, t);
399#endif
400 h[] = max(h1, 0.);
401 if (h1 < dry) {
402 for (int _f = 0; _f < 1; _f++) /* scalar in tracers */
403 f[] = 0.;
404 }
405 else
406 for (int _f = 0; _f < 1; _f++) /* scalar in tracers */
407 f[] /= h1;
408 }
409 }
410}
411
412/**
413This is where the 'two-step advection' of the [implicit
414scheme](implicit.h) plugs itself (nothing is done for the explicit
415scheme). */
416
417event half_advection (i++, last);
418
419/**
420Vertical diffusion (including viscosity) is added by this code. */
421
422#include "diffusion.h"
423
424/**
425## Accelerations
426
427Acceleration terms are added here. In the simplest case, this is only
428the pressure gradient due to the free-surface slope, as computed in
429[face_fields](#face_fields). */
430
431event acceleration (i++, last);
432
433/** @brief Event: pressure (i++, last) */
434void event_pressure (void)
435{
436
437 /**
438 The acceleration is applied to the face fluxes... */
439
440 for (int _i = 0; _i < _N; _i++) /* foreach_face */
442 hu.x[] += dt*ha.x[];
443
444 /**
445 ... and to the centered velocity field, using height-weighting. */
446
447 for (int _i = 0; _i < _N; _i++) /* foreach */
448 foreach_layer() {
449 for (int _d = 0; _d < dimension; _d++)
450 u.x[] += dt*(ha.x[] + ha.x[1])/(hf.x[] + hf.x[1] + dry);
451#if dimension == 2
452 // metric terms
453 double dmdl = (fm.x[1,0] - fm.x[])/(cm[]*Delta);
454 double dmdt = (fm.y[0,1] - fm.y[])/(cm[]*Delta);
455 double ux = u.x[], uy = u.y[];
456 double fG = uy*dmdl - ux*dmdt;
457 u.x[] += dt*fG*uy;
458 u.y[] -= dt*fG*ux;
459#endif // dimension == 2
460 }
461 delete ((scalar *){ha});
462
463 /**
464 The resulting fluxes are used to advect both tracers and layer
465 heights. */
466
467 advect (tracers, hu, hf, dt);
468}
469
470/**
471Finally the free-surface height \f$\eta\f$ is updated. */
472
473/** @brief Event: update_eta (i++, last) */
475{
476 delete ((scalar *){hu, hf});
477 for (int _i = 0; _i < _N; _i++) /* foreach */ {
478 double etap = zb[];
480 etap += h[];
481 eta[] = etap;
482 }
483}
484
485/**
486## Vertical remapping and mesh adaptation
487
488[Vertical remapping](remap.h) is applied here if necessary. */
489
490event remap (i++, last);
491
492#if TREE
493event adapt (i++,last);
494#endif
495
496/**
497## Cleanup
498
499The fields and lists allocated in [`defaults()`](#defaults0) above
500must be freed at the end of the run. */
501
502/** @brief Event: cleanup (t = end, last) */
503void event_cleanup (void)
504{
505 delete ({eta, eta_r, h, u});
507}
508
509/**
510# Horizontal pressure gradient
511
512The macro below computes the horizontal pressure gradient
513\f[
514pg_k = - \mathbf{{\nabla}} (h \phi)_k + \left[ \phi
515 \mathbf{{\nabla}} z \right]_k
516\f]
517on the faces of each layer. The slope of the layer interfaces
518\f$\mathbf{{\nabla}} z_{k+1/2}\f$ in the second-term is bounded by
519`max_slope` (by default 30 degrees). */
520
521double max_slope = 0.577350269189626 [0]; // = tan(30.*pi/180.)
522#define slope_limited(dz) (fabs(dz) < max_slope ? (dz) : \
523 ((dz) > 0. ? max_slope : - max_slope))
524
525#define hpg(pg,phi,i,code) do { \
526 double dz = zb[i] - zb[i-1]; \
527 foreach_layer() { \
528 double pg = 0.; \
529 if (h[i] + h[i-1] > dry) { \
530 double s = Delta*slope_limited(dz/Delta); \
531 pg = (h[i-1] - s)*phi[i-1] - (h[i] + s)*phi[i]; \
532 if (point.l < nl - 1) { \
533 double s = Delta*slope_limited((dz + h[i] - h[i-1])/Delta); \
534 pg += (h[i-1] + s)*phi[i-1,0,1] - (h[i] - s)*phi[i,0,1]; \
535 } \
536 pg *= gmetric(i)*hf.x[i]/(Delta*(h[i] + h[i-1])); \
537 } code; \
538 dz += h[i] - h[i-1]; \
539 } \
540} while (0)
541
542/**
543# Hydrostatic vertical velocity
544
545For the hydrostatic solver, the vertical velocity is not defined by
546default since it is usually not required. The function below can be
547applied to compute it using the (diagnostic) incompressibility condition
548\f[
549\mathbf{{\nabla}} \cdot \left( h \mathbf{u} \right)_k + \left[ w -
550\mathbf{u} \cdot \mathbf{{\nabla}} (z) \right]_k = 0
551\f]
552*/
553
555{
556 for (int _i = 0; _i < _N; _i++) /* foreach */ {
557 double dz = zb[1] - zb[-1];
558 double wm = 0.;
559 foreach_layer() {
560 w[] = wm + (hu.x[] + hu.x[1])/(hf.x[] + hf.x[1] + dry)*
561 (dz + h[1] - h[-1])/(2.*Delta);
562 if (point.l > 0)
563 for (int _d = 0; _d < dimension; _d++)
564 w[] -= (hu.x[0,0,-1] + hu.x[1,0,-1])
565 /(hf.x[0,0,-1] + hf.x[1,0,-1] + dry)*dz/(2.*Delta);
566 for (int _d = 0; _d < dimension; _d++)
567 w[] -= (hu.x[1] - hu.x[])/Delta;
568 dz += h[1] - h[-1], wm = w[];
569 }
570 }
571}
572
573/**
574# "Radiation" boundary conditions
575
576This can be used to implement open boundary conditions at low
577[Froude numbers](http://en.wikipedia.org/wiki/Froude_number). The idea
578is to set the velocity normal to the boundary so that the water level
579relaxes towards its desired value (*ref*). */
580
581double _radiation (Point point, double ref, scalar s)
582{
583 double H = 0.;
585 H += h[];
586#if 0
587 return H > dry ? sqrt(G/H)*(zb[] + H - ref) : 0.;
588#else
589 return sqrt (G*max(H,0.)) - sqrt(G*max(ref - zb[], 0.));
590#endif
591}
592
593#define radiation(ref) _radiation(point, ref, _s)
594
595/**
596# Conservation of water surface elevation
597
598We re-use some generic functions. */
599
600#include "elevation.h"
601
602/**
603But we need to re-define the water depth refinement function. */
604
605#if TREE
607{
608
609 /**
610 We first check whether we are dealing with "shallow cells". */
611
612 bool shallow = zb[] > default_sea_level;
613 for (int _c = 0; _c < 4; _c++) /* foreach_child */
614 if (zb[] > default_sea_level) {
615 shallow = true; break;
616 }
617
618 /**
619 If we do, refined cells are just set to the default sea level. */
620
621 if (shallow)
622 for (int _c = 0; _c < 4; _c++) /* foreach_child */
623 h[] = max(0., default_sea_level - zb[]);
624
625 /**
626 Otherwise, we use the surface elevation of the parent cells to
627 reconstruct the water depth of the children cells. */
628
629 else {
630 double eta = zb[] + h[]; // water surface elevation
631 coord g; // gradient of eta
632 if (gradient)
633 for (int _d = 0; _d < dimension; _d++)
634 g.x = gradient (zb[-1] + h[-1], eta, zb[1] + h[1])/4.;
635 else
636 for (int _d = 0; _d < dimension; _d++)
637 g.x = (zb[1] + h[1] - zb[-1] - h[-1])/(2.*Delta);
638 // reconstruct water depth h from eta and zb
639 for (int _c = 0; _c < 4; _c++) /* foreach_child */ {
640 double etac = eta;
641 for (int _d = 0; _d < dimension; _d++)
642 etac += g.x*child.x;
643 h[] = max(0., etac - zb[]);
644 }
645 }
646}
647
648/**
649We overload the `conserve_elevation()` function. */
650
657
658#define conserve_elevation() conserve_layered_elevation()
659
660#endif // TREE
661
662#include "gauges.h"
663
664#if dimension == 2
665
666/**
667# Fluxes through sections
668
669These functions are typically used to compute fluxes (i.e. flow rates)
670through cross-sections defined by two endpoints (i.e. segments). Note
671that the orientation of the segment is taken into account when
672computing the flux i.e the positive normal direction to the segment is
673to the "left" when looking from the start to the end.
674
675This can be expressed mathematically as:
676\f[
677\text{flux}[k] = \int_A^B h_k\mathbf{u}_k\cdot\mathbf{n}dl
678\f]
679with \f$A\f$ and \f$B\f$ the endpoints of the segment, \f$k\f$ the layer index,
680\f$\mathbf{n}\f$ the oriented segment unit normal and \f$dl\f$ the elementary
681length. The function returns the sum (over \f$k\f$) of all the fluxes. */
682
683double segment_flux (coord segment[2], double * flux, scalar h, vector u)
684{
685 coord m = {segment[0].y - segment[1].y, segment[1].x - segment[0].x};
686 normalize (&m);
687 for (int l = 0; l < nl; l++)
688 flux[l] = 0.;
690 double dl = 0.;
691 for (int _d = 0; _d < dimension; _d++) {
692 double dp = (p[1].x - p[0].x)*Delta/Delta_x*(fm.y[] + fm.y[0,1])/2.;
693 dl += sq(dp);
694 }
695 dl = sqrt (dl);
696 for (int i = 0; i < 2; i++) {
697 coord a = p[i];
699 flux[point.l] += dl/2.*
700 interpolate_linear (point, h, a.x, a.y, 0.)*
701 (m.x*interpolate_linear (point, u.x, a.x, a.y, 0.) +
702 m.y*interpolate_linear (point, u.y, a.x, a.y, 0.));
703 }
704 }
705 double tot = 0.;
706 for (int l = 0; l < nl; l++)
707 tot += flux[l];
708 return tot;
709}
710
711/**
712A NULL-terminated array of *Flux* structures passed to
713*output_fluxes()* will create a file (called *name*) for each
714flux. Each time *output_fluxes()* is called a line will be appended to
715the file. The line contains the time, the total flux and the value of
716the flux for each \f$h\f$, \f$u\f$ pair in the layer. The *desc* field can be
717filled with a longer description of the flux. */
718
719typedef struct {
720 char * name;
722 char * desc;
724} Flux;
725
727{
728 for (Flux * f = fluxes; f->name; f++) {
729 double flux[nl];
730 double tot = segment_flux (f->s, flux, h, u);
731 if (pid() == 0) {
732 if (!f->fp) {
733 f->fp = fopen (f->name, "w");
734 if (f->desc)
735 fprintf (f->fp, "%s\n", f->desc);
736 }
737 fprintf (f->fp, "%g %g", t, tot);
738 for (int i = 0; i < nl; i++)
739 fprintf (f->fp, " %g", flux[i]);
740 fputc ('\n', f->fp);
741 fflush (f->fp);
742 }
743 }
744}
745
746#endif // dimension == 2
vector g[]
We store the combined pressure gradient and acceleration field in g*.
Definition all-mach.h:65
const vector a
Definition all-mach.h:59
vector un[]
Definition atmosphere.h:5
int min
Definition balance.h:192
#define dimension
Definition bitree.h:3
static double interpolate_linear(Point point, scalar v, double xp=0., double yp=0., double zp=0.)
define l
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
free(list1)
int y
Definition common.h:76
int x
Definition common.h:76
const scalar cm[]
Definition common.h:397
void display(const char *commands, bool overwrite=false)
Definition common.h:527
void normalize(coord *n)
Definition common.h:98
static number sq(number x)
Definition common.h:11
scalar * list_copy(scalar *l)
Definition common.h:225
static int sign(number x)
Definition common.h:13
scalar * list_append(scalar *list, scalar s)
Definition common.h:188
const vector fm[]
Definition common.h:396
scalar f[]
The primary fields are:
Definition two-phase.h:56
vector w[]
#define p
Definition tree.h:320
#define assert(a)
Definition config.h:107
#define LINENO
Definition config.h:105
Point point
Definition conserving.h:86
scalar dp[]
double dt
static void restriction_elevation(Point point, scalar h)
Cell restriction is simpler.
Definition elevation.h:81
static double default_sea_level
Definition elevation.h:18
static void prolongation_elevation(Point point, scalar h)
We also need to define a consistent prolongation function.
Definition elevation.h:106
scalar s
Definition embed-tree.h:56
scalar int i
Definition embed.h:74
double dtnext(double dt)
Definition events.h:276
double t
Definition events.h:24
#define reset(...)
Definition grid.h:1388
void vertical_velocity(scalar w, vector hu, vector hf)
Definition hydro.h:554
void event_pressure(void)
Event: pressure (i++, last)
Definition hydro.h:434
scalar eta_r
Definition hydro.h:60
scalar eta
Definition hydro.h:50
double dtmax
The maximum timestep dtmax can be used to impose additional stability conditions.
Definition hydro.h:187
event acceleration(i++, last)
Vertical diffusion (including viscosity) is added by this code.
event remap(i++, last)
scalar h
Definition hydro.h:50
void output_fluxes(Flux *fluxes, scalar h, vector u)
Definition hydro.h:726
vector hf
Definition hydro.h:209
#define a_baro(eta, i)
Definition hydro.h:197
double dry
Definition hydro.h:56
double CFL_H
Definition hydro.h:52
scalar zb[]
Definition hydro.h:50
double G
Definition hydro.h:52
static void refine_layered_elevation(Point point, scalar h)
But we need to re-define the water depth refinement function.
Definition hydro.h:606
vector hu
Definition hydro.h:209
scalar * tracers
Here we set the gradient functions for each tracer (as defined in the user-provided tracers list).
Definition hydro.h:60
void event_init(void)
After user initialisation, we define the free-surface height .
Definition hydro.h:173
static bool hydrostatic
Definition hydro.h:208
void event_defaults0(void)
The allocation of fields for each layer is split in two parts, because we need to make sure that the ...
Definition hydro.h:95
void event_face_fields(void)
Event: face_fields (i++, last)
Definition hydro.h:212
void event_update_eta(void)
Finally the free-surface height is updated.
Definition hydro.h:474
static void refine_eta(Point point, scalar eta)
Definition hydro.h:71
vector ha
Definition hydro.h:209
void event_cleanup(void)
Event: cleanup (t = end, last)
Definition hydro.h:503
double _radiation(Point point, double ref, scalar s)
Definition hydro.h:581
double max_slope
Definition hydro.h:521
void event_defaults(void)
Other fields, such as here, are added by this event.
Definition hydro.h:131
vector u
Definition hydro.h:51
trace void advect(scalar *tracers, vector hu, vector hf, double dt)
Definition hydro.h:306
bool linearised
Definition hydro.h:61
event half_advection(i++, last)
This is where the 'two-step advection' of the implicit scheme plugs itself (nothing is done for the e...
event adapt(i++, last)
double(* gradient)(double, double, double)
Definition hydro.h:58
static void restriction_eta(Point point, scalar eta)
Definition hydro.h:80
event set_dtmax(i++, last) dtmax
double segment_flux(coord segment[2], double *flux, scalar h, vector u)
Definition hydro.h:683
void conserve_layered_elevation(void)
We overload the conserve_elevation() function.
Definition hydro.h:651
int nl
Definition layers.h:9
which uses a global _layer index *int _layer
Definition layers.h:15
#define foreach_layer()
size_t max
Definition mtrace.h:8
static void restriction_volume_average(Point point, scalar s)
static void refine_linear(Point point, scalar s)
void set_prolongation(scalar s, void(*prolongation)(Point, scalar))
void set_restriction(scalar s, void(*restriction)(Point, scalar))
def _i
Definition stencils.h:405
A NULL-terminated array of Flux structures passed to output_fluxes()* will create a file (called name...
Definition hydro.h:719
FILE * fp
Definition hydro.h:723
char * desc
Definition hydro.h:722
char * name
Definition hydro.h:720
Definition linear.h:21
Definition common.h:78
double y
Definition common.h:79
scalar x
Definition common.h:47
scalar y
Definition common.h:49
double CFL
Definition utils.h:10
double DT
Definition utils.h:10
macro foreach_segment(coord S[2], coord p[2], Reduce reductions=None)
The macro below traverses the set of sub-segments intersecting the mesh and spanning the [A:B] segmen...
Definition utils.h:349
double minmod2(double s0, double s1, double s2)
Definition utils.h:225
scalar flux[]
Definition vof.h:166
scalar c
Definition vof.h:57
src vof fflush(ferr)