Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
hydro-tension.h
Go to the documentation of this file.
1/** @file hydro-tension.h
2 */
3/**
4# Multilayer solver with surface tension
5
6This file adds surface tension to the [multilayer
7solver](/src/layered/README) i.e. the Laplace pressure applied on the free surface as
8\f[
9(\mathbf{T_{liquid}} - \mathbf{T_{gas}}) \cdot \mathbf{n} = - \rho \sigma \kappa\mathbf{n}
10\f]
11with \f$T\f$, the stress tensors respectively in the gas and in the
12liquid, \f$\rho \sigma\f$ the surface tension coefficient, and \f$\kappa\f$ the
13curvature of the free-surface.
14
15Note that this file is also compatible with the [implicit free-surface
16extension](/src/layered/implicit.h) and with the [non-hydrostatic
17extension](/src/layered/nh.h). In both cases the Laplace pressure term
18is treated implicitly and does not restrict the timestep.
19
20The default surface tension coefficient \f$\sigma\f$ is constant and equal to
21unity. */
22
23const scalar sigma[] = 1.;
24
25/**
26## Laplace pressure
27
28The Laplace pressure corresponds to a barotropic pressure \f$\phi(x) = -
29\rho \sigma \kappa\f$ that is added to the hydrostatic equations (term
30in blue).
31\f[
32\begin{aligned}
33 \partial_t h_k + \mathbf{{\nabla}} \cdot \left( h \mathbf{u} \right)_k & =
34 0,\\
35 \partial_t \left( h \mathbf{u} \right)_k + \mathbf{{\nabla}} \cdot \left(
36 h \mathbf{u} \mathbf{u} \right)_k & = - gh_k \mathbf{{\nabla}} (\eta)
37 \color{blue} + h_k \mathbf{{\nabla}} (\sigma \kappa)
38\end{aligned}
39\f]
40
41### Implementation
42
43We will need auxilliary fields containing the "non-linear surface
44tension coefficients", which are
45\f[
46\sigma_n = \frac{\sigma}{n}
47\f]
48in one dimension and
49\f[
50\begin{aligned}
51\sigma_x & = \sigma \frac{1 + (\partial_y\eta)^2}{n} \\
52\sigma_y & = \sigma \frac{1 + (\partial_x\eta)^2}{n} \\
53\sigma_n & = - 2 \sigma \frac{\partial_x\eta \partial_y\eta}{n}
54\end{aligned}
55\f]
56in two dimensions, with
57\f[
58n = (1 + |\mathbf{\nabla}\eta|^2)^{3/2}
59\f]
60*/
61
63#if dimension > 1
65#endif
66
67/**
68We overload the default definition of the barotropic acceleration in
69[hydro.h](/src/layered/hydro.h) which becomes
70\f[
71\mathbf{a}_\text{baro} = - g \mathbf{{\nabla}} (\eta)
72 \color{blue} + \mathbf{{\nabla}} (\sigma \kappa)
73\f]
74where \f$\sigma \kappa\f$ is computed as
75\f[
76\sigma \kappa = \sigma_n \frac{\partial^2\eta}{\partial x^2}
77\f]
78in two dimensions and
79\f[
80\sigma \kappa = \sigma_x \frac{\partial^2\eta}{\partial x^2} +
81 \sigma_y \frac{\partial^2\eta}{\partial y^2} +
82 \sigma_n \frac{\partial^2\eta}{\partial x y}
83\f]
84in three dimensions.
85
86In 3D, the weighing with the `0.2` coefficient is necessary to avoid odd-even
87decoupling. */
88
89#if dimension == 1
90# define sigma_kappa(eta, i) \
91 (sigma_n[i]*(eta[i+1] + eta[i-1] - 2.*eta[i])/sq(Delta))
92#else // dimension == 2
93# define sigma_kappa(eta, i) \
94 ((sigma_d.x[i]*(0.2*(eta[i+1,1] + eta[i-1,1] - 2.*eta[i,1] + \
95 eta[i+1,-1] + eta[i-1,-1] - 2.*eta[i,-1]) + \
96 eta[i+1] + eta[i-1] - 2.*eta[i])/(1. + 2.*0.2) + \
97 sigma_d.y[i]*(0.2*(eta[i+1,1] + eta[i+1,-1] - 2.*eta[i+1] + \
98 eta[i-1,1] + eta[i-1,-1] - 2.*eta[i-1]) + \
99 eta[i,1] + eta[i,-1] - 2.*eta[i])/(1. + 2.*0.2) + \
100 sigma_n[i]*(eta[i+1,1] + eta[i-1,-1] - \
101 eta[i+1,-1] - eta[i-1,1]))/sq(Delta))
102#endif // dimension == 2
103
104#define p_baro(eta,i) (- G*eta[i] + sigma_kappa(eta, i))
105#define a_baro(eta, i) \
106 (gmetric(i)*(p_baro (eta, i) - p_baro (eta, i - 1))/Delta)
107
108#include "layered/hydro.h"
109
110/**
111The non-linear surface tension coefficient(s) are defined using the
112surface elevation at the beginning of the timestep. */
113
114/** @brief Event: face_fields (i++) */
116{
117 sigma_n = {0} /* new scalar */;
118#if dimension > 1
119 scalar dx = {0} /* new scalar */, dy = {0} /* new scalar */;
120 sigma_d.x = dx, sigma_d.y = dy;
121#endif
122
123 for (int _i = 0; _i < _N; _i++) /* foreach */ {
124 double n = 1.;
125 coord dh;
126 for (int _d = 0; _d < dimension; _d++) {
127 dh.x = (eta[1] - eta[-1])/(2.*Delta);
128 n += sq(dh.x);
129 }
130 n = pow(n, 3./2.);
131#if dimension == 1
132 sigma_n[] = sigma[]/n;
133#else
134 sigma_n[] = - sigma[]*dh.x*dh.y/(2.*n);
135 for (int _d = 0; _d < dimension; _d++)
136 sigma_d.x[] = sigma[]*(1. + sq(dh.y))/n;
137#endif
138 }
139#if dimension == 1
140 boundary ({sigma_n});
142#else
145#endif
146
147 /**
148 In the case of a time-explicit integration (as controlled by CFL_H),
149 we need to restrict the timestep based on the celerity of capillary
150 waves (and not only gravity waves as done by the default solver). To
151 do so, we imitate the code in
152 [hydro.h](/src/layered/hydro.h#face_fields) which sets `dtmax`, but
153 take into account the celerity of the shortest capillary waves (of
154 wavelength \f$2\Delta\f$). */
155
156 for (int _i = 0; _i < _N; _i++) /* foreach_face */) {
157 double H = 0., um = 0.;
158 foreach_layer() {
159 double hl = h[-1] > dry ? h[-1] : 0.;
160 double hr = h[] > dry ? h[] : 0.;
161 double uf = hl > 0. || hr > 0. ? (hl*u.x[-1] + hr*u.x[])/(hl + hr) : 0.;
162 if (fabs(uf) > um)
163 um = fabs(uf);
164 H += (h[] + h[-1])/2.;
165 }
166 if (H > dry) {
167 double c = um/CFL + sqrt((G + max(sigma[], sigma[-1])*sq(pi/Delta))*
169 double dt = min(cm[], cm[-1])*Delta/(c*fm.x[]);
170 if (dt < dtmax)
171 dtmax = dt;
172 }
173 }
174}
175
176/**
177At the end of the timestep we delete the auxilliary fields. */
178
179/** @brief Event: pressure (i++) */
180void event_pressure (void) {
181 delete ({sigma_n});
182#if dimension > 1
183 delete ((scalar *){sigma_d});
184#endif
185}
#define u
Definition advection.h:30
vector uf[]
We allocate the (face) velocity field.
Definition advection.h:29
double dtmax
The timestep is computed using the CFL condition on the face velocity field.
Definition all-mach.h:105
double G
Definition atmosphere.h:12
scalar h[]
Definition atmosphere.h:6
int min
Definition balance.h:192
#define dimension
Definition bitree.h:3
#define boundary(...)
int x
Definition common.h:76
#define pi
Definition common.h:4
const scalar cm[]
Definition common.h:397
static number sq(number x)
Definition common.h:11
const vector fm[]
Definition common.h:396
return hxx pow(1.+sq(hx), 3/2.)
else return n
Definition curvature.h:101
double dt
double dry
Definition entrainment.h:30
#define dx(s)
We first define some useful macros, following the notations in Bonneton et al, 2011.
#define dy(s)
double dh
Definition heights.h:331
void event_pressure(void)
At the end of the timestep we delete the auxilliary fields.
scalar sigma_n
vector sigma_d
void event_face_fields(void)
The non-linear surface tension coefficient(s) are defined using the surface elevation at the beginnin...
const scalar sigma[]
scalar eta
Definition hydro.h:50
double CFL_H
Definition hydro.h:52
static bool hydrostatic
Definition hydro.h:208
#define foreach_layer()
size_t max
Definition mtrace.h:8
void(* restriction)(Point, scalar)
def _i
Definition stencils.h:405
Definition common.h:78
double x
Definition common.h:79
scalar x
Definition common.h:47
scalar y
Definition common.h:49
double CFL
Definition utils.h:10
scalar c
Definition vof.h:57