Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
redistance.h
Go to the documentation of this file.
1/** @file redistance.h
2 */
3/**
4# Redistancing of a distance field
5
6The original implementation was by [Alexandre
7Limare](/sandbox/alimare/README) used in particular in [Limare et al.,
82022](#limare2022).
9
10This file implements redistancing of a distance field with subcell
11correction, see the work of [Russo & Smereka, 2000](#russo2000) with
12corrections by [Min & Gibou, 2007](#min2007) and by [Min,
132010](#min2010).
14
15Let \f$\phi\f$ be a function close to a signed function that has been
16perturbed by numerical diffusion (more precisely, a non-zero
17tangential velocity). By iterating on the eikonal equation
18\f[
19\left\{\begin{array}{ll}
20\phi_t + \text{sign}(\phi^{0}) \left(\left| \nabla \phi\right| - 1 \right) = 0\\
21\phi(x,0) = \phi^0(x)
22\end{array}
23\right.
24\f]
25we can correct or redistance \f$\phi\f$ to make it a signed function.
26
27We use a Godunov Hamiltonian approximation for
28\f$\left| \nabla \phi\right|\f$
29\f[
30\left| \nabla \phi \right|_{ij} = H_G(D_x^+\phi_{ij}, D_x^-\phi_{ij},
31 D_y^+\phi_{ij}, D_y^-\phi_{ij})
32\f]
33where \f$D^\pm\phi_{ij}\f$ denotes the one-sided ENO difference finite
34difference in the x- direction
35\f[
36D_x^+ = \dfrac{\phi_{i+1,j}-\phi_{i,j}}{\Delta} -
37 \dfrac{\Delta}{2}\text{minmod}(D_{xx}\phi_{ij}, D_{xx}\phi_{i+1,j})
38\f]
39\f[
40D_x^- = \dfrac{\phi_{i,j}-\phi_{i-1,j}}{\Delta} +
41 \dfrac{\Delta}{2}\text{minmod}(D_{xx}\phi_{ij}, D_{xx}\phi_{i+1,j})
42\f]
43here \f$D_{xx}\phi_{ij} = (\phi_{i-1,j} - 2\phi{ij} + \phi_{i+1,j})/\Delta^2\f$.
44
45The minmod function is zero when the two arguments have different
46signs, and takes the argument with smaller absolute value when the two
47have the same sign.
48
49The Godunov Hamiltonian \f$H_G\f$ is given as
50\f[
51H_G(a,b,c,d) = \left\{ \begin{array}{ll}
52\sqrt{\text{max}((a^-)^2,(b^+)^2 + (c^-)^2,(d^+)^2)} \text { when } \text{sign}(\phi^0_{ij})
53\geq 0\\
54\sqrt{\text{max}((a^+)^2,(b^-)^2 + (c^+)^2,(d^-)^2)} \text { when } \text{sign}(\phi^0_{ij}) < 0
55\end{array}
56\right.
57\f]
58with
59\f[
60x^+ = \text{max}(0, x)\\
61x^- = \text{min}(0, x)\\
62\f]
63
64We use a minmod limiter. */
65
66static inline double minmod3 (double a, double b)
67{
68 if (a == b || a*b <= 0.)
69 return 0.;
70 return fabs(a) < fabs(b) ? a : b;
71}
72
73#define BGHOSTS 2
74
75/**
76## Time derivative
77
78This function fills *dphi* with \f$\partial_t\phi\f$ .*/
79
80static
81void dphidt (scalar phi, scalar dphi, scalar phi0, const double cfl, const double phixxmin)
82{
83 for (int _i = 0; _i < _N; _i++) /* foreach */ {
84 double dt = cfl*Delta;
85
86 /**
87 We first calculate the inputs of the Hamiltonian
88 \f[
89 D^+\phi_{ij} = \dfrac{\phi_{i+1,j} - \phi_{ij}}{\Delta x} - \dfrac{\Delta}
90 {2}\text{minmod}(D_{xx}\phi_{ij},D_{xx}\phi_{i+1,j})
91 \f]
92 \f[
93 D^-\phi_{ij} = \dfrac{\phi_{i,j} - \phi_{i-1,j}}{\Delta x} - \dfrac{\Delta}
94 {2}\text{minmod}(D_{xx}\phi_{ij},D_{xx}\phi{i-1,j})
95 \f]
96 where
97 \f[
98 D_{xx}\phi_{ij} = \dfrac{\phi_{i-1,j} - 2\phi_{ij} + \phi_{i+1,j}}{\Delta x^2}
99 \f]
100 */
101
102 coord gra[2];
103 for (int i = 0, j = 1; i < 2; j = 1 - 2*++i)
104 for (int _d = 0; _d < dimension; _d++) {
105 double s1 = (phi[2*j] + phi[] - 2.*phi[j])/Delta;
106 double s2 = (phi[1] + phi[-1] - 2.*phi[])/Delta;
107 gra[i].x = j*((phi[j] - phi[])/Delta - minmod3(s1, s2)/2.);
108 }
109
110 /**
111 We check for interfacial cells. */
112
113 bool interfacial = false;
114 for (int _d = 0; _d < dimension; _d++)
115 if (phi0[-1]*phi0[] < 0 || phi0[1]*phi0[] < 0)
116 interfacial = true;
117
118 dphi[] = - sign2(phi0[]);
119
120 if (interfacial) {
121
122 /**
123 Near the interface, *i.e.* for cells where
124 \f[
125 \phi^0_i\phi^0_{i+1} \leq 0 \text{ or } \phi^0_i\phi^0_{i-1} \leq 0
126 \f]
127
128 The scheme must stay truly upwind, meaning that the movement of the 0
129 level-set of the function must be as small as possible. Therefore the upwind
130 numerical scheme is modified to
131 \f[
132 D_x^+ = \dfrac{0-\phi_{ij}}{\Delta x^+} - \dfrac{\Delta x^+}{2} \text{minmod}(D_
133 {xx}\phi_{ij},D_{xx}\phi_{i+1,j}) \text{ if } \phi_{ij}\phi_{i+1,j} < 0
134 \f]
135 \f[
136 D_x^- = \dfrac{\phi_{ij}-0}{\Delta x^-} + \dfrac{\Delta x^-}{2} \text{minmod}(D_
137 {xx}\phi_{ij},D_{xx}\phi_{i-1,j}) \text{ if } \phi_{ij}\phi_{i+1,j} < 0
138 \f]
139 which is the correction by [Min & Gibou 2007](#min2007). */
140
141 double size = HUGE;
142 for (int _d = 0; _d < dimension; _d++)
143 for (int i = 0, j = 1; i < 2; j = 1 - 2*++i)
144 if (phi0[]*phi0[j] < 0.) {
145
146 /**
147 We compute the subcell fix near the interface (see section 2.2 in [Min, 2010](#min2010)).
148
149 \f[
150 \Delta x^+ = \left\{ \begin{array}{ll}
151 \Delta x \cdot \left( \frac{1}{2} + \dfrac{\phi^0_{i,j}-\phi^0_{i+1,j} -
152 \text{sgn}(\phi^0_{i,j}-\phi^0_{i+1,j})\sqrt{D}}{}\right)
153 \text{ if } \left| \phi^0_{xx}\right| >\epsilon \\
154 \Delta x \cdot \dfrac{\phi^0_{ij}}{\phi^0_{i,j}-\phi^0_{i+1,j}} \text{ else.} \\
155 \end{array}
156 \right.
157 \f]
158 with
159 \f[
160 \phi_{xx}^0 = \text{minmod}(\phi^0_{i-1,j}-2\phi^0_{ij}+\phi^0_{i+1,j},
161 \phi^0_{i,j}-2\phi^0_{i+1j}+\phi^0_{i+2,j}) \\
162 D = \left( \phi^0_{xx}/2 - \phi_{ij}^0 - \phi_{i+1,j} \right)^2
163 - 4\phi_{ij}^0\phi_{i+1,j}^0
164 \f]
165 For the \f$\Delta x^-\f$ calculation, replace all the \f$+\f$ subscript by \f$-\f$, this
166 is dealt with properly with the `j` parameter below. */
167
168 double dx = Delta;
169 double phixx = minmod3 (phi0[2*j] + phi0[] - 2.*phi0[j],
170 phi0[1] + phi0[-1] - 2.*phi0[]);
171 if (fabs(phixx) > phixxmin) {
172 double D = sq(phixx/2. - phi0[] - phi0[j]) - 4.*phi0[]*phi0[j];
173 dx *= 1/2. + (phi0[] - phi0[j] - sign2(phi0[] - phi0[j])*sqrt(D))/phixx;
174 }
175 else
176 dx *= phi0[]/(phi0[] - phi0[j]);
177
178 if (dx != 0.) {
179 double sxx1 = phi[2 - 4*i] + phi[] - 2.*phi[1 - 2*i];
180 double sxx2 = phi[1] + phi[-1] - 2.*phi[];
181 gra[i].x = (2*i - 1)*(phi[]/dx + dx*minmod3(sxx1, sxx2)/(2.*sq(Delta)));
182 }
183 else
184 gra[i].x = 0.;
185 size = min(size, dx);
186 }
187 dphi[] *= min(dt, fabs(size)/2.)/dt;
188 }
189
190 /**
191 The Godunov Hamiltonian is
192 \f[
193 H_G(a,b,c,d) = \left\{ \begin{array}{ll}
194 \sqrt{\text{max}((a^-)^2,(b^+)^2 + (c^-)^2,(d^+)^2)} \text { when } \text{sign}(\phi^0_{ij})
195 \geq 0\\
196 \sqrt{\text{max}((a^+)^2,(b^-)^2 + (c^+)^2,(d^-)^2)} \text { when } \text{sign}(\phi^0_{ij}) < 0
197 \end{array}
198 \right.
199 \f]
200 */
201
202 double H_G = 0;
203 if (phi0[] > 0)
204 for (int _d = 0; _d < dimension; _d++) {
205 double a = min(0., gra[0].x);
206 double b = max(0., gra[1].x);
207 H_G += max(sq(a), sq(b));
208 }
209 else
210 for (int _d = 0; _d < dimension; _d++) {
211 double a = max(0., gra[0].x);
212 double b = min(0., gra[1].x);
213 H_G += max(sq(a), sq(b));
214 }
215
216 dphi[] *= sqrt(H_G) - 1.;
217 }
218}
219
220/**
221## The redistance() function */
222
223trace
225 int imax = 1, // The maximum number of iterations
226 double cfl = 0.5, // The CFL number
227 int order = 3, // The order of time integration
228 double eps = 1e-6, // The maximum error on \f$|\nabla\phi| - 1\f$
229 double band = HUGE, // The width of the band in which to compute the error
230 scalar resf = {-1}, // The residual \f$|\nabla\phi| - 1\f$
231 const double phixxmin = 1./HUGE) // The threshold for second-order subcell correction
232{
233
234 /**
235 We create `phi0[]`, a copy of the initial level-set function before
236 the iterations. */
237
238 scalar phi0[];
239 for (int _i = 0; _i < _N; _i++) /* foreach */
240 phi0[] = phi[] ;
241
242 /**
243 Time integration iteration loop. */
244
245 for (int i = 1; i <= imax; i++) {
246 double maxres = 0.;
247
248 /**
249 We use either a RK2 scheme... */
250
251 if (order == 2) {
252 scalar tmp1[];
253 dphidt (phi, tmp1, phi0, cfl/2., phixxmin);
254 for (int _i = 0; _i < _N; _i++) /* foreach */
255 tmp1[] = phi[] + Delta*cfl/2.*tmp1[];
256 scalar tmp2[];
258 foreach (reduction(max:maxres)) {
259 double res = tmp2[];
260 if (resf.i >= 0) resf[] = res;
261 if (fabs (res) > maxres && fabs(phi0[]) < band*Delta) maxres = fabs (res);
262 phi[] += Delta*cfl*tmp2[];
263 }
264 }
265
266 /**
267 ... or a RK3 compact scheme from [Shu and Osher,
268 1988](#shu1988). */
269
270 else {
271 scalar tmp1[];
273 for (int _i = 0; _i < _N; _i++) /* foreach */
274 tmp1[] = phi[] + Delta*cfl*tmp1[];
275 scalar tmp2[];
277 for (int _i = 0; _i < _N; _i++) /* foreach */
278 tmp1[] = (3.*phi[] + tmp1[] + Delta*cfl*tmp2[])/4.;
280 foreach (reduction(max:maxres)) {
281 double res = 2./3.*((phi[] - tmp1[])/(Delta*cfl) - tmp2[]);
282 if (resf.i >= 0) resf[] = res;
283 if (fabs (res) > maxres && fabs(phi0[]) < band*Delta) maxres = fabs (res);
284 phi[] = (phi[] + 2.*(tmp1[] + Delta*cfl*tmp2[]))/3.;
285 }
286 }
287
288 if (maxres < eps)
289 return i;
290 }
291 return imax;
292}
293
294/**
295## References
296
297~~~bib
298@Article{shu1988,
299 author = {Chi-Wang Shu and Stanley Osher},
300 title = {Efficient implementation of essentially non-oscillatory shock-capturing schemes},
301 journal = {Journal of Computational Physics},
302 year = {1988},
303 volume = {77},
304 pages = {439-471},
305 issn = {0021-9991},
306 doi = {10.1016/0021-9991(88)90177-5},
307}
308
309@article{russo2000,
310 title = {A remark on computing distance functions},
311 volume = {163},
312 number = {1},
313 journal = {Journal of Computational Physics},
314 author = {Russo, Giovanni and Smereka, Peter},
315 year = {2000},
316 pages = {51--67}
317}
318
319@article{min2007,
320 author = {Chohong Min and Frédéric Gibou},
321 title = {A second order accurate level set method on non-graded adaptive cartesian grids},
322 journal = {Journal of Computational Physics},
323 year = {2007},
324 volume = {225},
325 pages = {300-321},
326 issn = {0021-9991},
327 doi = {10.1016/j.jcp.2006.11.034},
328}
329
330@article{min2010,
331 author = {Chohong Min},
332 title = {On reinitializing level set functions},
333 journal = {Journal of Computational Physics},
334 year = {2010},
335 volume = {229},
336 pages = {2764-2772},
337 issn = {0021-9991},
338 doi = {10.1016/j.jcp.2009.12.032},
339}
340
341@hal{limare2022, hal-03889680}
342~~~
343*/
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
static int sign2(number x)
Definition common.h:14
#define HUGE
Definition common.h:6
static number sq(number x)
Definition common.h:11
static bool interfacial(Point point, scalar c)
Definition curvature.h:506
double dt
scalar phi[]
The electric potential and the volume charge density are scalars while the permittivity and conductiv...
Definition implicit.h:34
*cs[i, 0, 0] a *[i -1, 0, 0] j
Definition embed.h:88
scalar int i
Definition embed.h:74
#define dx(s)
We first define some useful macros, following the notations in Bonneton et al, 2011.
vector D[]
The linear system can be inverted with the multigrid Poisson solver.
size_t max
Definition mtrace.h:8
size_t size
size *double * b
trace int redistance(scalar phi, int imax=1, double cfl=0.5, int order=3, double eps=1e-6, double band=HUGE, scalar resf={-1}, const double phixxmin=1./HUGE)
Definition redistance.h:224
static void dphidt(scalar phi, scalar dphi, scalar phi0, const double cfl, const double phixxmin)
Definition redistance.h:81
static double minmod3(double a, double b)
Definition redistance.h:66
def _i
Definition stencils.h:405
Definition common.h:78
double x
Definition common.h:79
double cfl
Definition vof.h:167