Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
saint-venant-implicit.h
Go to the documentation of this file.
1/** @file saint-venant-implicit.h
2 */
3/**
4# A semi-implicit Saint-Venant solver
5
6<div class="message">
7Note that the [multilayer solver](layered/hydro.h) provides the same
8functionality and should be prefered for most applications.</div>
9
10We solve the [Saint-Venant equations](saint-venant.h) semi-implicitly
11to lift the timestep restriction due to gravity waves. This is just a
12particular application of the "all Mach" semi-implicit solver. We will
13use the Bell-Collela-Glaz advection scheme to transport mass and
14momentum. */
15
16#include "all-mach.h"
17#include "tracer.h"
18
19/**
20In addition to the momentum \f$\mathbf{q}=h\mathbf{u}\f$ defined by the
21all Mach solver, we will need the fluid depth *h* (i.e. the density
22\f$\rho\f$) and the topography *zb*. Both the momentum \f$\mathbf{q}\f$ and
23mass \f$h\f$ are advected tracers. The acceleration of gravity is
24*G*. *dry* is the fluid depth below which a cell is considered
25"dry". */
26
27scalar zb[], h[], * tracers = {q,h};
28double G = 1.;
29double dry = 1e-4;
30
31/**
32We need fields to store the (varying) state fields \f$\rho c^2\f$,
33\f$\alpha\f$ and the acceleration \f$\mathbf{a}\f$. */
34
37
38/** @brief Event: defaults (i = 0) */
39void event_defaults (void) {
40 rho = h;
41 alpha = alphav;
42 a = av;
43 rhoc2 = rhoc2v;
44
45 /**
46 We set limiting for *q*, *h*. */
47
48 for (int _s = 0; _s < 1; _s++) /* scalar in {q,h} */
49 s.gradient = minmod2;
50
51 /**
52 As well as default values. */
53
54 for (int _i = 0; _i < _N; _i++) /* foreach */
55 h[] = 1.;
56
57 /**
58 On trees, we ensure that limiting is also applied to prolongation. */
59
60 #if TREE
61 for (int _s = 0; _s < 1; _s++) /* scalar in {q,h} */
62 s.prolongation = refine_linear;
63 #endif
64
65 /**
66 We setup the default display. */
67
68 display ("squares (color = 'h > 0 ? zb + h : nodata', spread = -1);");
69}
70
71/**
72After user initialisation we set the initial pressure and apply
73boundary conditions. The boundary conditions for \f$\rho=h\f$ and
74\f$\mathbf{q}\f$ are already applied by the [all Mach
75solver](all-mach.h). */
76
77/** @brief Event: init (i = 0) */
78void event_init (void) {
79 for (int _i = 0; _i < _N; _i++) /* foreach */ {
80 p[] = G*sq(h[])/2.;
81 /* dim: h[] == Delta */;
82 }
83}
84
85/**
86By default the timestep is only limited by the CFL condition on the
87advection velocity field. We add the option to define an "acoustic CFL
88number" which takes into account the speed of gravity waves. */
89
90double CFLa = HUGE;
91
92/** @brief Event: stability (i++) */
93void event_stability (void) {
94 if (CFLa < HUGE)
95 foreach (reduction (min:dtmax))
96 if (h[] > dry) {
97 double dt = CFLa*Delta/sqrt(G*h[]);
98 if (dt < dtmax)
99 dtmax = dt;
100 }
101}
102
103/**
104The properties of the fluid are given by the "Saint-Venant equation of
105state" i.e. \f$p = gh^2/2\f$, \f$\rho c^2 = gh^2\f$. */
106
107/** @brief Event: properties (i++) */
108void event_properties (void) {
109 for (int _i = 0; _i < _N; _i++) /* foreach */ {
110 rhoc2v[] = G*sq(max(h[],dry));
111 ps[] = rhoc2v[]/2.;
112 }
113
114 /**
115 The specific volume \f$\alpha=1/\rho\f$ is constructed by averaging,
116 taking into account dry states. */
117
118 for (int _i = 0; _i < _N; _i++) /* foreach_face */ {
119 if ((h[] > dry && h[-1] > dry) ||
120 (h[] > dry && h[] + zb[] >= zb[-1]) ||
121 (h[-1] > dry && h[-1] + zb[-1] >= zb[]))
122 alphav.x[] = 2./(max(h[],dry) + max(h[-1],dry));
123 else
124 alphav.x[] = 0.;
125 }
126}
127
128/**
129## Topographic source term
130
131The acceleration due to the topography is \f$- g\nabla z_b\f$. On regular
132Cartesian grids we can simply do */
133
134#if !TREE
135/** @brief Event: acceleration (i++) */
136void event_acceleration (void) {
137 for (int _i = 0; _i < _N; _i++) /* foreach_face */
138 if (alpha.x[])
139 av.x[] -= G*(zb[] - zb[-1])/Delta;
140}
141#else // TREE
142
143/**
144On trees things are a bit more complicated due to the necessity to
145verify the "lake-at-rest" condition. For a lake, the pressure gradient
146must balance the topographic source term i.e.
147\f[
148\frac{1}{h}\nabla p = a = -g\nabla z_b
149\f]
150with \f$a\f$ the acceleration. Using the equation of state and introducing
151\f[
152\eta = z_b + h
153\f]
154the elevation of the free surface (constant for a lake at rest), we get
155\f[
156\frac{1}{2h}\nabla gh^2 = -g\nabla (\eta - h) = g\nabla h
157\f]
158This identity is obviously verified mathematically, however it is not
159necessarily verified by the discrete gradient operator. In the case of
160Cartesian meshes it is simple to show that the naive discrete gradient
161operator we used above verifies this identity. For tree meshes
162this is not generally the case due to the prolongation operator used
163to fill ghost cells at refinement boundaries. Rather than trying to
164redefine the prolongation operator, we discretise the topographic
165source term as
166\f[
167a = -g\nabla z_b = -g \nabla\eta + \frac{g}{2h}\nabla h^2
168\f]
169This is strictly identical mathematically, however if we now use the
170same discrete operator to estimate \f$\nabla p\f$ and \f$\nabla h^2\f$, the
171*discrete* lake-at-rest condition becomes
172\f[ \nabla\eta = 0 \f]
173which is much easier to verify.
174
175To do so, we define the following restriction and prolongation
176operators for \f$\eta\f$. The main idea is to avoid using the elevation of
177dry cells. Restriction is done by averaging the elevation of wet
178cells. */
179
181{
182 double sum = 0., n = 0.;
183 for (int _c = 0; _c < 4; _c++) /* foreach_child */
184 if (h[] > dry) {
185 sum += s[];
186 n++;
187 }
188 s[] = n > 0 ? sum/n : nodata;
189}
190
191/**
192Prolongation uses linear interpolation with a cell-centered gradient
193computed from simple finite-differences of wet cells. */
194
196{
197 coord g;
198 for (int _d = 0; _d < dimension; _d++) {
199 if (h[] > dry) {
200 if (h[1] > dry && h[-1] > dry)
201 g.x = (s[1] - s[-1])/2.;
202 else if (h[1] > dry)
203 g.x = s[1] - s[];
204 else if (h[-1] > dry)
205 g.x = s[] - s[-1];
206 else
207 g.x = 0.;
208 }
209 else
210 g.x = 0.;
211 }
212 double sc = s[];
213 for (int _c = 0; _c < 4; _c++) /* foreach_child */ {
214 s[] = sc;
215 for (int _d = 0; _d < dimension; _d++)
216 s[] += child.x*g.x/4.;
217 }
218}
219
220/**
221One can check that the prolongation values constructed using these
222functions verify \f$\eta = constant\f$ for a lake-at-rest. */
223
224/** @brief Event: acceleration (i++) */
226
227 /**
228 To compute the acceleration due to topography, we first compute
229 \f$\eta\f$ and \f$h^2\f$. */
230
231 scalar eta[], h2[];
232 for (int _i = 0; _i < _N; _i++) /* foreach */ {
233 h2[] = sq(h[]);
234 eta[] = zb[] + h[];
235 }
236
237 /**
238 We then make sure that \f$\eta\f$ uses our restriction/prolongation
239 functions. \f$h^2\f$ uses the same prolongation functions as \f$p\f$ by
240 default. */
241
242 eta.prolongation = eta_prolongation;
243 eta.restriction = eta_restriction;
244
245 /**
246 We then compute the acceleration as
247 \f[
248 a = -g \nabla\eta + g \frac{\alpha}{2}\nabla h^2
249 \f]
250 */
251
252 for (int _i = 0; _i < _N; _i++) /* foreach_face */
253 if (alpha.x[])
254 av.x[] += G*(eta[-1] - eta[] + alpha.x[]/2.*(h2[] - h2[-1]))/Delta;
255}
256
257#endif // TREE
258
259/**
260The utility functions in *elevation.h* need to know which gradient we
261are using. */
262
264
265#include "elevation.h"
266#include "gauges.h"
vector g[]
We store the combined pressure gradient and acceleration field in g*.
Definition all-mach.h:65
const scalar rhoc2
Definition all-mach.h:58
double dtmax
The timestep is computed using the CFL condition on the face velocity field.
Definition all-mach.h:105
vector q[]
The primitive variables are the momentum , pressure , density , (face) specific volume ,...
Definition all-mach.h:44
scalar ps[]
The equation of state is defined by the pressure field ps and .
Definition all-mach.h:57
const vector alpha
Definition all-mach.h:47
const vector a
Definition all-mach.h:59
int min
Definition balance.h:192
#define dimension
Definition bitree.h:3
int x
Definition common.h:76
void display(const char *commands, bool overwrite=false)
Definition common.h:527
#define nodata
Definition common.h:7
#define HUGE
Definition common.h:6
static number sq(number x)
Definition common.h:11
#define p
Definition tree.h:320
Point point
Definition conserving.h:86
else return n
Definition curvature.h:101
double dt
scalar s
Definition embed-tree.h:56
scalar eta
Definition hydro.h:50
double * sum
#define rho(f)
The density and viscosity are defined using arithmetic averages by default.
Definition momentum.h:45
size_t max
Definition mtrace.h:8
static void refine_linear(Point point, scalar s)
void event_acceleration(void)
One can check that the prolongation values constructed using these functions verify for a lake-at-re...
void event_stability(void)
Event: stability (i++)
vector av[]
double dry
scalar h[]
scalar rhoc2v[]
We need fields to store the (varying) state fields , and the acceleration .
scalar zb[]
In addition to the momentum defined by the all Mach solver, we will need the fluid depth h (i....
double G
void event_init(void)
After user initialisation we set the initial pressure and apply boundary conditions.
void eta_prolongation(Point point, scalar s)
Prolongation uses linear interpolation with a cell-centered gradient computed from simple finite-diff...
void eta_restriction(Point point, scalar s)
On trees things are a bit more complicated due to the necessity to verify the "lake-at-rest" conditio...
void event_defaults(void)
Event: defaults (i = 0)
void event_properties(void)
The properties of the fluid are given by the "Saint-Venant equation of state" i.e.
double CFLa
By default the timestep is only limited by the CFL condition on the advection velocity field.
double(* gradient)(double, double, double)
The utility functions in elevation.h need to know which gradient we are using.
scalar * tracers
Here we set the gradient functions for each tracer (as defined in the user-provided tracers list).
vector alphav[]
def _i
Definition stencils.h:405
Definition linear.h:21
Definition common.h:78
scalar x
Definition common.h:47
double minmod2(double s0, double s1, double s2)
Definition utils.h:225