redistance.h
📄 View in API Reference (Doxygen) · View on basilisk.fr
Test cases (1): redistance-ellipse
Redistancing of a distance field
The original implementation was by Alexandre Limare used in particular in Limare et al., 2022.
This file implements redistancing of a distance field with subcell correction, see the work of Russo & Smereka, 2000 with corrections by Min & Gibou, 2007 and by Min, 2010.
Let $\phi$ be a function close to a signed function that has been perturbed by numerical diffusion (more precisely, a non-zero tangential velocity). By iterating on the eikonal equation
we can correct or redistance $\phi$ to make it a signed function.
We use a Godunov Hamiltonian approximation for $\left| \nabla \phi\right|$
where $D^\pm\phi_{ij}$ denotes the one-sided ENO difference finite difference in the x- direction
here $D_{xx}\phi_{ij} = (\phi_{i-1,j} - 2\phi{ij} + \phi_{i+1,j})/\Delta^2$.
The minmod function is zero when the two arguments have different signs, and takes the argument with smaller absolute value when the two have the same sign.
The Godunov Hamiltonian $H_G$ is given as
with
We use a minmod limiter.
static inline double minmod3 (double a, double b)
{
if (a == b || a*b <= 0.)
return 0.;
return fabs(a) < fabs(b) ? a : b;
}
#define BGHOSTS 2
Time derivative
This function fills *dphi* with $\partial_t\phi$ .
static
void dphidt (scalar phi, scalar dphi, scalar phi0, const double cfl, const double phixxmin)
{
foreach() {
double dt = cfl*Delta;
We first calculate the inputs of the Hamiltonian
where
coord gra[2];
for (int i = 0, j = 1; i < 2; j = 1 - 2*++i)
foreach_dimension() {
double s1 = (phi[2*j] + phi[] - 2.*phi[j])/Delta;
double s2 = (phi[1] + phi[-1] - 2.*phi[])/Delta;
gra[i].x = j*((phi[j] - phi[])/Delta - minmod3(s1, s2)/2.);
}
We check for interfacial cells.
bool interfacial = false;
foreach_dimension()
if (phi0[-1]*phi0[] < 0 || phi0[1]*phi0[] < 0)
interfacial = true;
dphi[] = - sign2(phi0[]);
if (interfacial) {
Near the interface, *i.e.* for cells where
The scheme must stay truly upwind, meaning that the movement of the 0 level-set of the function must be as small as possible. Therefore the upwind numerical scheme is modified to
which is the correction by Min & Gibou 2007.
double size = HUGE;
foreach_dimension()
for (int i = 0, j = 1; i < 2; j = 1 - 2*++i)
if (phi0[]*phi0[j] < 0.) {
We compute the subcell fix near the interface (see section 2.2 in Min, 2010).
with
For the $\Delta x^-$ calculation, replace all the $+$ subscript by $-$, this is dealt with properly with the j parameter below.
double dx = Delta;
double phixx = minmod3 (phi0[2*j] + phi0[] - 2.*phi0[j],
phi0[1] + phi0[-1] - 2.*phi0[]);
if (fabs(phixx) > phixxmin) {
double D = sq(phixx/2. - phi0[] - phi0[j]) - 4.*phi0[]*phi0[j];
dx *= 1/2. + (phi0[] - phi0[j] - sign2(phi0[] - phi0[j])*sqrt(D))/phixx;
}
else
dx *= phi0[]/(phi0[] - phi0[j]);
if (dx != 0.) {
double sxx1 = phi[2 - 4*i] + phi[] - 2.*phi[1 - 2*i];
double sxx2 = phi[1] + phi[-1] - 2.*phi[];
gra[i].x = (2*i - 1)*(phi[]/dx + dx*minmod3(sxx1, sxx2)/(2.*sq(Delta)));
}
else
gra[i].x = 0.;
size = min(size, dx);
}
dphi[] *= min(dt, fabs(size)/2.)/dt;
}
The Godunov Hamiltonian is
double H_G = 0;
if (phi0[] > 0)
foreach_dimension() {
double a = min(0., gra[0].x);
double b = max(0., gra[1].x);
H_G += max(sq(a), sq(b));
}
else
foreach_dimension() {
double a = max(0., gra[0].x);
double b = min(0., gra[1].x);
H_G += max(sq(a), sq(b));
}
dphi[] *= sqrt(H_G) - 1.;
}
}
The redistance() function
trace
int redistance (scalar phi,
int imax = 1, // The maximum number of iterations
double cfl = 0.5, // The CFL number
int order = 3, // The order of time integration
double eps = 1e-6, // The maximum error on $|\nabla\phi| - 1$
double band = HUGE, // The width of the band in which to compute the error
scalar resf = {-1}, // The residual $|\nabla\phi| - 1$
const double phixxmin = 1./HUGE) // The threshold for second-order subcell correction
{
We create phi0[], a copy of the initial level-set function before the iterations.
scalar phi0[];
foreach()
phi0[] = phi[] ;
Time integration iteration loop.
for (int i = 1; i <= imax; i++) {
double maxres = 0.;
We use either a RK2 scheme...
if (order == 2) {
scalar tmp1[];
dphidt (phi, tmp1, phi0, cfl/2., phixxmin);
foreach()
tmp1[] = phi[] + Delta*cfl/2.*tmp1[];
scalar tmp2[];
dphidt (tmp1, tmp2, phi0, cfl, phixxmin);
foreach (reduction(max:maxres)) {
double res = tmp2[];
if (resf.i >= 0) resf[] = res;
if (fabs (res) > maxres && fabs(phi0[]) < band*Delta) maxres = fabs (res);
phi[] += Delta*cfl*tmp2[];
}
}
... or a RK3 compact scheme from Shu and Osher, 1988.
else {
scalar tmp1[];
dphidt (phi, tmp1, phi0, cfl, phixxmin);
foreach()
tmp1[] = phi[] + Delta*cfl*tmp1[];
scalar tmp2[];
dphidt (tmp1, tmp2, phi0, cfl, phixxmin);
foreach()
tmp1[] = (3.*phi[] + tmp1[] + Delta*cfl*tmp2[])/4.;
dphidt (tmp1, tmp2, phi0, cfl, phixxmin);
foreach (reduction(max:maxres)) {
double res = 2./3.*((phi[] - tmp1[])/(Delta*cfl) - tmp2[]);
if (resf.i >= 0) resf[] = res;
if (fabs (res) > maxres && fabs(phi0[]) < band*Delta) maxres = fabs (res);
phi[] = (phi[] + 2.*(tmp1[] + Delta*cfl*tmp2[]))/3.;
}
}
if (maxres < eps)
return i;
}
return imax;
}
References
~~~bib @Article{shu1988, author = {Chi-Wang Shu and Stanley Osher}, title = {Efficient implementation of essentially non-oscillatory shock-capturing schemes}, journal = {Journal of Computational Physics}, year = {1988}, volume = {77}, pages = {439-471}, issn = {0021-9991}, doi = {10.1016/0021-9991(88)90177-5}, }
@article{russo2000, title = {A remark on computing distance functions}, volume = {163}, number = {1}, journal = {Journal of Computational Physics}, author = {Russo, Giovanni and Smereka, Peter}, year = {2000}, pages = {51--67} }
@article{min2007, author = {Chohong Min and Frédéric Gibou}, title = {A second order accurate level set method on non-graded adaptive cartesian grids}, journal = {Journal of Computational Physics}, year = {2007}, volume = {225}, pages = {300-321}, issn = {0021-9991}, doi = {10.1016/j.jcp.2006.11.034}, }
@article{min2010, author = {Chohong Min}, title = {On reinitializing level set functions}, journal = {Journal of Computational Physics}, year = {2010}, volume = {229}, pages = {2764-2772}, issn = {0021-9991}, doi = {10.1016/j.jcp.2009.12.032}, }
@hal{limare2022, hal-03889680} ~~~