Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
diffusion.h
Go to the documentation of this file.
1/** @file diffusion.h
2 */
3/**
4# Vertical diffusion
5
6We consider the vertical diffusion of a tracer \f$s\f$ with a diffusion
7coefficient \f$D\f$ for the multilayer solver.
8
9For stability, we discretise the vertical diffusion equation implicitly as
10\f[
11\frac{(hs_l)^{n + 1} - (hs_l)^{\star}}{\Delta t} =
12D \left( \frac{s_{l + 1} - s_l}{h_{l + 1 / 2}} -
13\frac{s_l - s_{l - 1}}{h_{l - 1 / 2}} \right)^{n + 1}
14\f]
15which can be expressed as the linear system
16\f[
17\mathbf{Ms}^{n + 1} = \mathrm{rhs}
18\f]
19where \f$\mathbf{M}\f$ is a
20[tridiagonal matrix](https://en.wikipedia.org/wiki/Tridiagonal_matrix).
21The lower, principal and upper diagonals are *a*, *b* and *c* respectively.
22
23Boundary conditions on the top and bottom layers need to be added to close the
24system. We chose to impose a Neumann condition on the free-surface i.e.
25\f[
26\partial_z s |_t = \dot{s}_t
27\f]
28and a Navier slip condition on the bottom i.e.
29\f[
30s|_b = s_b + \lambda_b \partial_z s|_b
31\f] */
32
33void vertical_diffusion (Point point, scalar h, scalar s, double dt, double D,
34 double dst, double s_b, double lambda_b)
35{
36 double a[nl], b[nl], c[nl], rhs[nl];
37
38 /**
39 The *rhs* of the tridiagonal system is \f$h_l s_l\f$. */
40
42 rhs[point.l] = s[]*h[];
43
44 /**
45 The lower, principal and upper diagonals \f$a\f$, \f$b\f$ and \f$c\f$ are given by
46 \f[
47 a_{l > 0} = - \left( \frac{D \Delta t}{h_{l - 1 / 2}} \right)^{n + 1}
48 \f]
49 \f[
50 c_{l < \mathrm{nl} - 1} = - \left( \frac{D \Delta t}{h_{l + 1 / 2}}
51 \right)^{n + 1}
52 \f]
53 \f[
54 b_{0 < l < \mathrm{nl} - 1} = h_l^{n + 1} - a_l - c_l
55 \f]
56 */
57
58 for (int l = 1; l < nl - 1; l++) {
59 a[l] = - 2.*D*dt/(h[0,0,l-1] + h[0,0,l]);
60 c[l] = - 2.*D*dt/(h[0,0,l] + h[0,0,l+1]);
61 b[l] = h[0,0,l] - a[l] - c[l];
62 }
63
64 /**
65 For the top layer the boundary conditions give the (ghost)
66 boundary value
67 \f[
68 s_{\mathrm{nl}} = s_{\mathrm{nl} - 1} + \dot{s}_t h_{\mathrm{nl} - 1},
69 \f]
70 which gives the diagonal coefficient and right-hand-side
71 \f[
72 b_{\mathrm{nl} - 1} = h_{\mathrm{nl} - 1}^{n + 1}
73 - a_{\mathrm{nl} - 1}
74 \f]
75 \f[
76 \mathrm{rhs}_{\mathrm{nl} - 1} =
77 (hs)_{\mathrm{nl} - 1}^{\star} + D \Delta t \dot{s}_t
78 \f]
79 */
80
81 a[nl-1] = - 2.*D*dt/(h[0,0,nl-2] + h[0,0,nl-1]);
82 b[nl-1] = h[0,0,nl-1] - a[nl-1];
83 rhs[nl-1] += D*dt*dst;
84
85 /**
86 For the bottom layer a third-order discretisation of the Navier slip
87 condition gives
88 \f[
89 \begin{aligned}
90 b_0 & = h_0 + 2 \Delta t D \left( \frac{1}{h_0 + h_1} + \frac{h^2_1 + 3
91 h_0 h_1 + 3 h^2_0}{\det} \right),\\
92 c_0 & = - 2 \Delta t D \left( \frac{1}{h_0 + h_1} + \frac{h^2_0}{\det}
93 \right),\\
94 \text{rhs}_0 & = (hs_0)^{\star} + 2 \Delta t D s_b \frac{h^2_1 + 3 h_0
95 h_1 + 2 h^2_0}{\det},\\
96 \det & = h_0 (h_0 + h_1)^2 + 2\lambda (3\,h_0 h_1 + 2\,h_0^2 + h_1^2),
97 \end{aligned}
98 \f]
99 */
100
101 double den = h[]*sq(h[] + h[0,0,1])
102 + 2.*lambda_b*(3.*h[]*h[0,0,1] + 2.*sq(h[]) + sq(h[0,0,1]));
103 b[0] = h[] + 2.*dt*D*(1./(h[] + h[0,0,1]) +
104 (sq(h[0,0,1]) + 3.*h[]*h[0,0,1] + 3.*sq(h[]))/den);
105 c[0] = - 2.*dt*D*(1./(h[] + h[0,0,1]) + sq(h[])/den);
106 rhs[0] += 2.*dt*D*s_b*(sq(h[0,0,1]) + 3.*h[]*h[0,0,1] + 2.*sq(h[0]))/den;
107
108 if (nl == 1) {
109 b[0] += c[0];
110 rhs[0] += (- c[0]*h[] - D*dt) * dst;
111 }
112
113 /**
114 We can now solve the tridiagonal system using the [Thomas
115 algorithm](https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm). */
116
117 for (int l = 1; l < nl; l++) {
118 b[l] -= a[l]*c[l-1]/b[l-1];
119 rhs[l] -= a[l]*rhs[l-1]/b[l-1];
120 }
121 a[nl-1] = rhs[nl-1]/b[nl-1];
122 s[0,0,nl-1] = a[nl-1];
123 for (int l = nl - 2; l >= 0; l--)
124 s[0,0,l] = a[l] = (rhs[l] - c[l]*a[l+1])/b[l];
125}
126
127/**
128# Viscous friction between layers
129
130By default the viscosity is zero and we impose free-slip on the
131free-surface and no-slip on the bottom boundary
132i.e. \f$\dot{\mathbf{u}}_t = 0\f$, \f$\mathbf{\lambda}_b = 0\f$, \f$\mathbf{u}_b
133= 0\f$. */
134
135double nu = 0.;
136const vector lambda_b[] = {0,0,0}, dut[] = {0,0,0}, u_b[] = {0,0,0};
137
138/**
139In the [layered solver](hydro.h), vertical viscosity is applied to the
140velocity field just after advection, but before the pressure
141gradient/acceleration term is applied. To take the pressure gradient
142into account, we first apply the acceleration of the previous
143timestep, apply vertical viscosity and then substract the previous
144acceleration. */
145
146/** @brief Event: viscous_term (i++,last) */
148{
149 if (nu > 0.) {
150 for (int _i = 0; _i < _N; _i++) /* foreach */ {
152 for (int _d = 0; _d < dimension; _d++)
153 u.x[] += dt*(ha.x[] + ha.x[1])/(hf.x[] + hf.x[1] + dry);
154 for (int _d = 0; _d < dimension; _d++)
156 dut.x[], u_b.x[], lambda_b.x[]);
158 for (int _d = 0; _d < dimension; _d++)
159 u.x[] -= dt*(ha.x[] + ha.x[1])/(hf.x[] + hf.x[1] + dry);
160 }
161 }
162}
163
164/**
165## Horizontal diffusion
166
167This approximates
168\f[
169h \partial_t s = D \nabla \cdot (h \nabla s)
170\f]
171with \f$D\f$ the diffusion coefficient. Note that metric terms linked to
172the slope of the layers are not taken into account. Note also that the
173time discretisation is explicit so that the timestep must be limited
174(manually) by \f$\min(\Delta^2/D)\f$. */
175
176void horizontal_diffusion (scalar * list, double D, double dt)
177{
178 if (D > 0.) {
180 foreach_layer() {
181 for (int _i = 0; _i < _N; _i++) /* foreach */ {
182 scalar s, d2s;
183 for (s,d2s in list,d2sl) {
184 double a = 0.;
185 for (int _d = 0; _d < dimension; _d++)
186 a += (hf.x[]*fm.x[]/(cm[-1] + cm[])*(s[-1] - s[]) +
187 hf.x[1]*fm.x[1]/(cm[1] + cm[])*(s[1] - s[]));
188 d2s[] = 2.*a/(cm[]*sq(Delta));
189 }
190 }
191 for (int _i = 0; _i < _N; _i++) /* foreach */
192 if (h[] > dry) {
193 scalar s, d2s;
194 for (s,d2s in list,d2sl)
195 s[] += dt*D*d2s[]/h[];
196 }
197 }
198 delete (d2sl);
199 free (d2sl);
200 }
201}
202
203/**
204### Time-implicit integration
205
206When the timestep constraint due to explicit time integration is too
207strong, one can use the time-implicit version below. The diffusion equation
208\f[
209h \partial_t s = D \nabla \cdot (h \nabla s)
210\f]
211is discretised implicitly as
212\f[
213h \frac{s^{n + 1} - s^n}{\Delta t} = \nabla \cdot (Dh \nabla s^{n + 1})
214\f]
215which can be reordered as
216\f[
217\nabla \cdot (\Delta tDh \nabla s^{n + 1}) - hs^{n + 1} = - hs^n
218\f]
219i.e. a Poisson--Helmoltz equation of the form
220\f[
221\nabla \cdot (\alpha \nabla s^{n + 1}) + \lambda s^{n + 1} = b
222\f]
223which is solved using the [multigrid Poisson--Helmholz solver](/src/poisson.h#user-interface).
224
225The function returns convergence statistics for the multigrid solver. */
226
227#include "poisson.h"
228
229trace
231{
232 mgstats mg = {0};
233 if (D > 0.) {
234 scalar b[], lambda[];
235 vector alpha[];
236 foreach_layer() {
237 for (int _i = 0; _i < _N; _i++) /* foreach_face */
238 alpha.x[] = 2.*dt*D*hf.x[]*fm.x[]/(cm[-1] + cm[]);
239 for (int _i = 0; _i < _N; _i++) /* foreach */
240 lambda[] = - cm[]*h[];
241 for (int _s = 0; _s < 1; _s++) /* scalar in list */ {
242 for (int _i = 0; _i < _N; _i++) /* foreach */
243 b[] = lambda[]*s[];
244 mg = poisson (s, b, alpha, lambda);
245 }
246 }
247 }
248 return mg;
249}
250
251/**
252## References
253
254~~~bib
255@hal{popinet2020, hal-02365730}
256
257@hal{devita2019, hal-02295398}
258~~~
259*/
#define u
Definition advection.h:30
const vector alpha
Definition all-mach.h:47
const vector a
Definition all-mach.h:59
scalar h[]
Definition atmosphere.h:6
#define dimension
Definition bitree.h:3
scalar * list_clone(scalar *l)
define l
free(list1)
define VT _attribute[s.i] v y scalar * list
Definition cartesian.h:276
int x
Definition common.h:76
const scalar cm[]
Definition common.h:397
static number sq(number x)
Definition common.h:11
const vector fm[]
Definition common.h:396
Point point
Definition conserving.h:86
double dt
scalar s
Definition embed-tree.h:56
double dry
Definition entrainment.h:30
vector D[]
The linear system can be inverted with the multigrid Poisson solver.
vector hf
Definition hydro.h:209
vector ha
Definition hydro.h:209
const vector lambda_b[]
Definition diffusion.h:136
void horizontal_diffusion(scalar *list, double D, double dt)
Definition diffusion.h:176
const vector dut[]
Definition diffusion.h:136
void event_viscous_term(void)
In the layered solver, vertical viscosity is applied to the velocity field just after advection,...
Definition diffusion.h:147
const vector u_b[]
Definition diffusion.h:136
trace mgstats implicit_horizontal_diffusion(scalar *list, double D, double dt)
Definition diffusion.h:230
void vertical_diffusion(Point point, scalar h, scalar s, double dt, double D, double dst, double s_b, double lambda_b)
Definition diffusion.h:33
double nu
Definition diffusion.h:135
int nl
Definition layers.h:9
#define foreach_layer()
int dst
size *double * b
def _i
Definition stencils.h:405
Definition linear.h:21
Information about the convergence of the solver is returned in a structure.
Definition poisson.h:112
scalar x
Definition common.h:47
#define poisson(...)
Finally, we overload the poisson() function called by [two-phase.h]() with our new function.
Definition thermal.h:243
#define lambda
scalar c
Definition vof.h:57