Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
multilayer.h
Go to the documentation of this file.
1
/** @file multilayer.h
2
*/
3
/**
4
# Multilayer Saint-Venant system with mass exchanges
5
6
<div class="message">
7
Note that the [multilayer solver](layered/hydro.h) provides the same
8
functionality and should be prefered for most applications.</div>
9
10
The [Saint-Venant system](saint-venant.h) is extended to multiple
11
layers following [Audusse et al, 2011](references.bib#audusse2011) as
12
\f[
13
\partial_th + \partial_x\sum_{l=0}^{nl-1}h_lu_l = 0
14
\f]
15
with
16
\f[
17
h_l = \mathrm{layer}_lh
18
\f]
19
with \f$\mathrm{layer}_l\f$ the relative thickness of the layers satisfying
20
\f[
21
\mathrm{layer}_l >= 0,\;\sum_{l=0}^{nl - 1}\mathrm{layer}_l = 1.
22
\f]
23
The momentum equation in each layer is thus
24
\f[
25
\partial_t(h\mathbf{u}_l) + \nabla\cdot\left(h\mathbf{u}_l\otimes\mathbf{u}_l +
26
\frac{gh^2}{2}\mathbf{I}\right) =
27
- gh\nabla z_b + \frac{1}{\mathrm{layer}_l}\left[\mathbf{u}_{l+1/2}G_{l+1/2} -
28
\mathbf{u}_{l-1/2}G_{l-1/2}
29
+ \nu\left(\frac{u_{l+1} - u_l}{h_{l+1/2}} -
30
\frac{u_{l} - u_{l-1}}{h_{l-1/2}}\right)\right]
31
\f]
32
where \f$G_{l+1/2}\f$ is the relative vertical transport velocity between
33
layers and the second term corresponds to viscous friction between
34
layers.
35
36
These last two terms are the only difference with the [one layer
37
system](saint-venant.h).
38
39
The horizontal velocity in each layer is stored in *ul* and the
40
vertical velocity between layers in *wl*. */
41
42
vector
*
ul
=
NULL
;
43
scalar
*
wl
=
NULL
;
44
double
*
layer
;
45
46
/**
47
The index of the layer is set as a field attribute. */
48
49
attribute
{
50
int
l
;
51
}
52
53
/**
54
## Viscous friction between layers
55
56
Boundary conditions on the top and bottom layers need to be added to close the
57
system for the viscous stresses. We chose to impose a Neumann condition on the
58
top boundary i.e.
59
\f[
60
\partial_z u |_t = \dot{u}_t
61
\f]
62
and a Navier slip condition on the bottom i.e.
63
\f[
64
u|_b = u_b + \lambda_b \partial_z u|_b
65
\f]
66
By default the viscosity is zero and we impose free-slip on the top
67
boundary and no-slip on the bottom boundary i.e. \f$\dot{u}_t = 0\f$,
68
\f$\lambda_b = 0\f$, \f$u_b = 0\f$. */
69
70
double
nu
= 0.;
71
const
scalar
lambda0
[] = 0,
dut0
[] = 0,
u_b0
[] = 0;
72
const
scalar
lambda_b
=
lambda0
,
dut
=
dut0
,
u_b
=
u_b0
;
73
// fixme: should be able to replace the two lines above with:
74
// const scalar lambda_b[] = 0, dut[] = 0, u_b[] = 0;
75
76
/**
77
For stability, we discretise the viscous friction term implicitly as
78
\f[
79
\frac{(hu_l)_{n + 1} - (hu_l)_{\star}}{\Delta t} =
80
\frac{\nu}{\mathrm{layer}_l} \left( \frac{u_{l + 1} - u_l}{h_{l + 1 / 2}} -
81
\frac{u_l - u_{l - 1}}{h_{l - 1 / 2}} \right)_{n + 1}
82
\f]
83
which can be expressed as the linear system
84
\f[
85
\mathbf{Mu}_{n + 1} = \mathrm{rhs}
86
\f]
87
where \f$\mathbf{M}\f$ is a
88
[tridiagonal matrix](https://en.wikipedia.org/wiki/Tridiagonal_matrix).
89
The lower, principal and upper diagonals are *a*, *b* and *c* respectively. */
90
91
void
vertical_viscosity
(
Point
point
,
double
h
,
vector
*
ul
,
double
dt
)
92
{
93
if
(
nu
) {
94
double
a
[
nl
],
b
[
nl
],
c
[
nl
], rhs[
nl
];
95
for
(
int
_d
= 0;
_d
<
dimension
;
_d
++) {
96
97
/**
98
The *rhs* of the tridiagonal system is \f$h_lu_l = h\mathrm{layer}_lu_l\f$. */
99
100
int
l
= 0;
101
for
(
int
_u
= 0;
_u
< 1;
_u
++)
/* vector in ul */
102
rhs[
l
] =
h
*
layer
[
l
]*
u
.x[],
l
++;
103
104
/**
105
The lower, principal and upper diagonals \f$a\f$, \f$b\f$ and \f$c\f$ are given by
106
\f[
107
a_{l > 0} = - \left( \frac{\nu \Delta t}{h_{l - 1 / 2}} \right)_{n + 1}
108
\f]
109
\f[
110
c_{l < \mathrm{nl} - 1} = - \left( \frac{\nu \Delta t}{h_{l + 1 / 2}}
111
\right)_{n + 1}
112
\f]
113
\f[
114
b_{0 < l < \mathrm{nl} - 1} = \mathrm{layer}_l h_{n + 1} - a_l - c_l
115
\f]
116
*/
117
118
for
(
l
= 1;
l
<
nl
- 1;
l
++) {
119
a
[
l
] = - 2.*
nu
*
dt
/(
h
*(
layer
[
l
-1] +
layer
[
l
]));
120
c
[
l
] = - 2.*
nu
*
dt
/(
h
*(
layer
[
l
] +
layer
[
l
+1]));
121
b
[
l
] =
layer
[
l
]*
h
-
a
[
l
] -
c
[
l
];
122
}
123
124
/**
125
For the top layer the boundary conditions give the (ghost)
126
boundary value
127
\f[
128
u_{\mathrm{nl}} = u_{\mathrm{nl} - 1} + \dot{u}_t h_{\mathrm{nl} - 1},
129
\f]
130
which gives the diagonal coefficient and right-hand-side
131
\f[
132
b_{\mathrm{nl} - 1} = \mathrm{layer}_{\mathrm{nl} - 1} h_{n + 1}
133
- a_{\mathrm{nl} - 1}
134
\f]
135
\f[
136
\mathrm{rhs}_{\mathrm{nl} - 1} = \mathrm{layer}_{\mathrm{nl} - 1}
137
(hu_{\mathrm{nl} - 1})_{\star} + \nu \Delta t \dot{u}_t
138
\f]
139
*/
140
141
a
[
nl
-1] = - 2.*
nu
*
dt
/(
h
*(
layer
[
max
(0,
nl
-2)] +
layer
[
nl
-1]));
142
b
[
nl
-1] =
layer
[
nl
-1]*
h
-
a
[
nl
-1];
143
rhs[
nl
-1] +=
nu
*
dt
*
dut
[];
144
145
/**
146
For the bottom layer, the boundary conditions give the (ghost)
147
boundary value \f$u_{- 1}\f$
148
\f[
149
u_{- 1} = \frac{2 h_0}{2 \lambda_b + h_0} u_b + \frac{2 \lambda_b - h_0}{2
150
\lambda_b + h_0} u_0,
151
\f]
152
which gives the diagonal coefficient and right-hand-side
153
\f[
154
b_0 = \mathrm{layer}_0 h_{n + 1} - c_0 +
155
\frac{2 \nu \Delta t}{2 \lambda_b + h_0}
156
\f]
157
\f[
158
\mathrm{rhs}_0 = \mathrm{layer}_0 (hu_0)_{\star} + \frac{2 \nu \Delta t}{2
159
\lambda_b + h_0} u_b
160
\f]
161
*/
162
163
c
[0] = - 2.*
dt
*
nu
/(
h
*(
layer
[0] +
layer
[
min
(1,
nl
-1)]));
164
b
[0] =
layer
[0]*
h
-
c
[0] + 2.*
nu
*
dt
/(2.*
lambda_b
[] +
h
*
layer
[0]);
165
rhs[0] += 2.*
nu
*
dt
/(2.*
lambda_b
[] +
h
*
layer
[0])*
u_b
[];
166
167
/**
168
We can now solve the tridiagonal system using the [Thomas
169
algorithm](https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm). */
170
171
for
(
l
= 1;
l
<
nl
;
l
++) {
172
b
[
l
] -=
a
[
l
]*
c
[
l
-1]/
b
[
l
-1];
173
rhs[
l
] -=
a
[
l
]*rhs[
l
-1]/
b
[
l
-1];
174
}
175
vector
u
=
ul
[
nl
-1];
176
u
.
x
[] =
a
[
nl
-1] = rhs[
nl
-1]/
b
[
nl
-1];
177
for
(
l
=
nl
- 2;
l
>= 0;
l
--) {
178
u
=
ul
[
l
];
179
u
.
x
[] =
a
[
l
] = (rhs[
l
] -
c
[
l
]*
a
[
l
+1])/
b
[
l
];
180
}
181
}
182
}
183
}
184
185
/**
186
## Fluxes between layers
187
188
The relative vertical velocity between layers \f$l\f$ and \f$l+1\f$ is defined
189
as (eq. (2.22) of [Audusse et al, 2011](references.bib#audusse2011))
190
\f[
191
G_{l+1/2} = \sum_{j=0}^{l}(\mathrm{div}_j + \mathrm{layer}_j\mathrm{dh})
192
\f]
193
with
194
\f[
195
\mathrm{div}_l = \nabla\cdot(h_l\mathbf{u}_l)
196
\f]
197
\f[
198
\mathrm{dh} = - \sum_{l=0}^{nl-1} \mathrm{div}_l
199
\f]
200
*/
201
202
void
vertical_fluxes
(
vector
*
evolving
,
vector
*
updates
,
203
scalar
*
divl
,
scalar
dh
)
204
{
205
for
(
int
_i
= 0;
_i
<
_N
;
_i
++)
/* foreach */
{
206
double
Gi
= 0.,
sumjl
= 0.;
207
for
(
int
l
= 0;
l
<
nl
- 1;
l
++) {
208
scalar
div
=
divl
[
l
];
209
Gi
+=
div
[] +
layer
[
l
]*
dh
[];
210
sumjl
+=
layer
[
l
];
211
scalar
w
=
div
;
212
w
[] =
dh
[]*
sumjl
-
Gi
;
213
for
(
int
_d
= 0;
_d
<
dimension
;
_d
++) {
214
215
/**
216
To compute the vertical advection term, we need an estimate of
217
the velocity at \f$l+1/2\f$. This is obtained using simple
218
upwinding according to the sign of the interface velocity
219
\f$\mathrm{Gi} = G_{l+1/2}\f$ and the values of the velocity in
220
the \f$l\f$ and \f$l+1\f$ layers. Note that the inequality of
221
upwinding is consistent with equs. (5.110) of [Audusse et al,
222
2011](references.bib#audusse2011) and (77) of [Audusse et al,
223
2011b](references.bib#audusse2011b) but not with eq. (2.23) of
224
[Audusse et al, 2011](references.bib#audusse2011). */
225
226
scalar
ub
=
evolving
[
l
].x,
ut
=
evolving
[
l
+ 1].x;
227
double
ui
=
Gi
< 0. ?
ub
[] :
ut
[];
228
229
/**
230
The flux at \f$l+1/2\f$ is then added to the updates of the bottom
231
layer and substracted from the updates of the top layer. */
232
233
double
flux
=
Gi
*
ui
;
234
scalar
du_b
=
updates
[
l
].x,
du_t
=
updates
[
l
+ 1].x;
235
du_b
[] +=
flux
/
layer
[
l
];
236
du_t
[] -=
flux
/
layer
[
l
+ 1];
237
238
/**
239
To compute the vertical velocity we use the definition of the
240
mass flux term (eq. 2.13 of [Audusse et
241
al, 2011](references.bib#audusse2011)):
242
\f[
243
\mathrm{w}(\mathbf{x},z_{l+1/2}) =
244
\partial_t z_{l+1/2} - G_{l+1/2} + \mathbf{u}_{l+1/2}
245
\cdot \nabla z_{l+1/2}
246
\f]
247
We can write the vertical position of the interface as:
248
\f[
249
z_{l+1/2} = z_{b} + \sum_{j=0}^{l} h_{j}
250
\f]
251
so that the vertical velocity is:
252
\f[
253
\mathrm{w}(\mathbf{x},z_{l+1/2}) =
254
\mathrm{dh}\sum_{j=0}^{l}\mathrm{layer}_{j} - G_{l+1/2} +
255
\mathbf{u}_{l+1/2} \cdot \left[\nabla z_{b} + \nabla h
256
\sum_{j=0}^{l}\mathrm{layer}_{j}\right]
257
\f]
258
*/
259
260
w
[] +=
ui
*((
zb
[1] -
zb
[-1]) + (
h
[1] -
h
[-1])*
sumjl
)/(2.*
Delta
);
261
}
262
}
263
}
264
}
u
#define u
Definition
advection.h:30
a
const vector a
Definition
all-mach.h:59
zb
scalar zb[]
Definition
atmosphere.h:6
h
scalar h[]
Definition
atmosphere.h:6
min
int min
Definition
balance.h:192
dimension
#define dimension
Definition
bitree.h:3
l
define l
Definition
cartesian-common.h:8
x
int x
Definition
common.h:76
w
vector w[]
Definition
compressible.h:51
evolving
scalar * evolving
The generic time-integration scheme in predictor-corrector.h needs to know which fields are updated i...
Definition
conservation.h:55
point
Point point
Definition
conserving.h:86
dt
double dt
Definition
predictor-corrector.h:18
dh
double dh
Definition
heights.h:331
nl
int nl
Definition
layers.h:9
max
size_t max
Definition
mtrace.h:8
b
size *double * b
Definition
multigrid-mpi.h:96
layer
double * layer
Definition
multilayer.h:44
lambda_b
const scalar lambda_b
Definition
multilayer.h:72
vertical_fluxes
void vertical_fluxes(vector *evolving, vector *updates, scalar *divl, scalar dh)
Definition
multilayer.h:202
dut0
const scalar dut0[]
Definition
multilayer.h:71
u_b0
const scalar u_b0[]
Definition
multilayer.h:71
wl
scalar * wl
Definition
multilayer.h:43
lambda0
const scalar lambda0[]
Definition
multilayer.h:71
attribute
attribute
The index of the layer is set as a field attribute.
Definition
multilayer.h:49
vertical_viscosity
void vertical_viscosity(Point point, double h, vector *ul, double dt)
For stability, we discretise the viscous friction term implicitly as.
Definition
multilayer.h:91
nu
double nu
Definition
multilayer.h:70
u_b
const scalar u_b
Definition
multilayer.h:72
ul
vector * ul
Definition
multilayer.h:42
dut
const scalar dut
Definition
multilayer.h:72
_i
def _i
Definition
stencils.h:405
Point
Definition
linear.h:21
scalar
Definition
common.h:44
vector
Definition
common.h:46
vector::x
scalar x
Definition
common.h:47
flux
scalar flux[]
Definition
vof.h:166
c
scalar c
Definition
vof.h:57
multilayer.h
Generated by
1.9.8