Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
embed.h File Reference
#include "fractions.h"
#include "embed-tree.h"
Include dependency graph for embed.h:

Go to the source code of this file.

Data Structures

struct  Cleanup
 This function "removes" (by setting their volume fraction to zero) cells which have inconsistent volume/surface fractions. More...
 

Macros

#define BGHOSTS   2
 
#define EMBED   1
 
#define SEPS   1e-30
 Embedded boundary operators specific to trees are defined in this file.
 
#define cs_avg(a, i, j, k)
 When combining third-order Dirichlet conditions and approximate projections, instabilities may occur due to feedback between the pressure mode and the velocity, amplified by the third-order derivative.
 
#define face_condition(fs, cs)
 Face gradients and face values, computed from cell-centered values must be tuned to take into account the area fractions of the embedded boundary.
 
#define face_gradient_x(a, i)
 
#define face_gradient_y(a, i)
 
#define face_gradient_z(a, i)
 
#define face_value(a, i)
 
#define center_gradient(a)
 The centered gradient must not use values of fields entirely contained within the embedded boundary (for which cs is zero).
 
#define embed_pos()   embed_area_center (point, &x, &y, &z)
 
#define quadratic(x, a1, a2, a3)    (((a1)*((x) - 1.) + (a3)*((x) + 1.))*(x)/2. - (a2)*((x) - 1.)*((x) + 1.))
 

Functions

 for (int _d=0;_d< 2;_d++) static inline double embed_face_gradient_x(Point point
 
 assert (cs[i] &&cs[i-1])
 
 if ((fs .x[i, j] > 0.5 &&fs .y[i, j+(j< 0)] &&fs .y[i-1, j+(j< 0)] &&cs[i, j] &&cs[i-1, j])) return((1.+fs.x[i]) *(a[i] - a[i-1])+(1. - fs.x[i]) *(a[i
 
j a (2.*Delta)
 
 return (a[i] - a[i-1])/Delta
 
 return (fs .x[i, j] > 0.5 &&fs .y[i, j+(j< 0)] &&fs .y[i-1, j+(j< 0)] &&cs[i, j] &&cs[i-1, j]) ?((1.+fs.x[i]) *((a[i
 
*cs[i, 0, 0] a *[i -1, 0, 0] cs (cs[i, 0, 0]+cs[i -1, 0, 0]+3.))+(1. - fs.x[i]) *((a[i
 
static double embed_geometry (Point point, coord *p, coord *n)
 
static double embed_area_center (Point point, double *x1, double *y1, double *z1)
 This function and the macro below shift the position $(x1,y1,z1)$ to the position of the barycenter of the embedded fragment.
 
double embed_interpolate (Point point, scalar s, coord p)
 This function returns the value of field s interpolated linearly at the barycenter p of the fragment of embedded boundary contained within the cell.
 
trace int fractions_cleanup (scalar c, vector s, double smin=0., bool opposite=false)
 
 for (int _d=0;_d< 2;_d++) if(defined &&!fs.x[(n.x > 0.)]) defined
 
 if (defined) for(int l=0
 
 if (fs.x[i+(i< 0), j] &&fs.y[i, j] &&fs.y[i, j+1] &&cs[i, j-1] &&cs[i, j] &&cs[i, j+1]) v[l]
 
 if (v[0]==nodata)
 
 if (v[1] !=nodata) return(d[1] *(bc - v[0])/d[0] - d[0] *(bc - v[1])/d[1])/((d[1] - d[0]) *Delta)
 
 return (bc - v[0])/(d[0] *Delta)
 
double dirichlet_gradient (Point point, scalar s, scalar cs, coord n, coord p, double bc, double *coef)
 
static coord embed_gradient (Point point, vector u, coord p, coord n)
 
trace void embed_force (scalar p, vector u, vector mu, coord *Fp, coord *Fmu)
 The force exerted by the fluid on the solid can be written.
 
double embed_vorticity (Point point, vector u, coord p, coord n)
 In two dimensions, embed_vorticity() returns the vorticity of velocity field u, on the surface of the embedded boundary contained in the cell.
 
double embed_flux (Point point, scalar s, vector mu, double *val)
 
macro2 double dirichlet (double expr, Point point=point, scalar s=_s, bool *data=data)
 For ease of use, we replace the Neumann and Dirichlet functions with macros so that they can be used either for standard domain boundaries or for embedded boundaries.
 
macro2 double dirichlet_homogeneous (double expr, Point point=point, scalar s=_s, bool *data=data)
 
macro2 double neumann (double expr, Point point=point, scalar s=_s, bool *data=data)
 
macro2 double neumann_homogeneous (double expr, Point point=point, scalar s=_s, bool *data=data)
 
trace void update_tracer (scalar f, vector uf, vector flux, double dt)
 
void event_metric (void)
 Event: metric (i = 0)
 
void event_defaults (void)
 We add the embedded boundary to the default display.
 

Variables

scalar cs []
 The volume and area fractions are stored in these fields.
 
vector fs []
 
double(* metric_embed_factor )(Point, coord) = NULL
 
scalar a
 
scalar int i
 
*cs[i, 0, 0] a *[i -1, 0, 0] j
 
*cs[i, 0, 0] a *[i -1, 0, 0] *cs[i, j, 0] a *[i -1, j, 0] cs(cs[i, j, 0]+cs[i -1, j, 0]+3.)))/2. attribute
 The generalisation to 3D is a bit more complicated.
 
scalar s
 
scalar scalar coord n
 
scalar scalar coord coord p
 
scalar scalar coord coord double bc
 
scalar scalar coord coord double doublecoef
 For non-degenerate cases, the gradient is obtained using either second- or third-order estimates.
 
double d [2]
 
double v [2] = {nodata,nodata}
 
bool defined = true
 
l<=1;l++) { int i=(l+1) *sign(n.x);d[l]=(i - p.x)/n.x;double y1=p.y+d[l] *n.y;int j=y1__pad0__
 
 y1 = j
 
else break
 
bid embed
 

Macro Definition Documentation

◆ BGHOSTS

#define BGHOSTS   2

Embedded boundaries

Boundaries of general shape can be described using an integral (i.e. finite volume) formulation which takes into account the volume and area fractions of intersection of the embedded boundary with the Cartesian mesh.

We will need to deal with volume fractions. Interpolations (for Dirichlet boundary conditions) assume a 5x5 stencil.

Definition at line 15 of file embed.h.

◆ center_gradient

#define center_gradient (   a)
Value:
(fs.x[] && fs.x[1] ? (a[1] - a[-1])/(2.*Delta) : \
fs.x[1] ? (a[1] - a[])/Delta : \
fs.x[] ? (a[] - a[-1])/Delta : 0.)
int x
Definition common.h:76
scalar a
Definition embed.h:73
vector fs[]
Definition embed.h:22
scalar x
Definition common.h:47

The centered gradient must not use values of fields entirely contained within the embedded boundary (for which cs is zero).

Definition at line 212 of file embed.h.

◆ cs_avg

#define cs_avg (   a,
  i,
  j,
  k 
)
Value:
((a[i,j,k]*(1.5 + cs[i,j,k]) + a[i-1,j,k]*(1.5 + cs[i-1,j,k]))/ \
(cs[i,j,k] + cs[i-1,j,k] + 3.))
define k
scalar cs[]
The volume and area fractions are stored in these fields.
Definition embed.h:21
*cs[i, 0, 0] a *[i -1, 0, 0] j
Definition embed.h:88
scalar int i
Definition embed.h:74

When combining third-order Dirichlet conditions and approximate projections, instabilities may occur due to feedback between the pressure mode and the velocity, amplified by the third-order derivative.

This can be stabilised using the weighted average below when computing face velocities. The corresponding test case is [test/uf.c](). Note that if only second-order Dirichlet fluxes are used, simple averaging is stable.

Definition at line 55 of file embed.h.

◆ EMBED

#define EMBED   1

Definition at line 16 of file embed.h.

◆ embed_pos

#define embed_pos ( )    embed_area_center (point, &x, &y, &z)

Definition at line 250 of file embed.h.

◆ face_condition

#define face_condition (   fs,
  cs 
)
Value:
(fs.x[i,j] > 0.5 && fs.y[i,j + (j < 0)] && fs.y[i-1,j + (j < 0)] && \
cs[i,j] && cs[i-1,j])
scalar y
Definition common.h:49

Face gradients and face values, computed from cell-centered values must be tuned to take into account the area fractions of the embedded boundary.

This follows the procedure described in Johansen and Colella, 1998, figure 3 and equation (16) in particular. Note that this is only used when using second-order fluxes.

Definition at line 68 of file embed.h.

◆ face_gradient_x

#define face_gradient_x (   a,
  i 
)
Value:
(a.third && fs.x[i] < 1. && fs.x[i] > 0. ? \
(a[i] - a[i-1])/Delta)
Point point
Definition conserving.h:86

Definition at line 184 of file embed.h.

◆ face_gradient_y

#define face_gradient_y (   a,
  i 
)
Value:
(a.third && fs.y[0,i] < 1. && fs.y[0,i] > 0. ? \
(a[0,i] - a[0,i-1])/Delta)

Definition at line 190 of file embed.h.

◆ face_gradient_z

#define face_gradient_z (   a,
  i 
)
Value:
(a.third && fs.z[0,0,i] < 1. && fs.z[0,0,i] > 0. ? \
(a[0,0,i] - a[0,0,i-1])/Delta)

Definition at line 196 of file embed.h.

◆ face_value

#define face_value (   a,
  i 
)
Value:
(a.third && fs.x[i] < 1. && fs.x[i] > 0. ? \
cs_avg(a,i,0,0))
#define cs_avg(a, i, j, k)
When combining third-order Dirichlet conditions and approximate projections, instabilities may occur ...
Definition embed.h:55

Definition at line 202 of file embed.h.

◆ quadratic

#define quadratic (   x,
  a1,
  a2,
  a3 
)     (((a1)*((x) - 1.) + (a3)*((x) + 1.))*(x)/2. - (a2)*((x) - 1.)*((x) + 1.))

Dirichlet boundary condition

This function returns the gradient of scalar s, normal to the embedded boundary defined by cs, of unit normal vector n (normalised using the Euclidean norm, not the box norm) and of centroid p. The Dirichlet boundary condition bc is imposed on the embedded boundary.

The calculation follows Johansen and Colella, 1998 and is summarised in the figure below (see also Figure 4 of Johansen and Colella and Figure 2 of Schwartz et al, 2006 for the 3D implementation).

Third-order normal gradient scheme

For degenerate cases, a non-zero value of coef is returned and coef*s[] must be added to the value returned to obtain the gradient.

Definition at line 373 of file embed.h.

◆ SEPS

#define SEPS   1e-30

Embedded boundary operators specific to trees are defined in this file.

Operator overloading

Several standard operators, defined in [common.h]() need to be tuned to take into account the embedded fractions.

The SEPS constant is used to avoid division by zero.

Definition at line 43 of file embed.h.

Function Documentation

◆ a()

j a ( 2.*  Delta)

◆ assert()

assert ( cs &&  cs[i][i-1])

◆ cs()

*cs[i, 0, 0] a *[i -1, 0, 0] cs ( cs+cs+  3.[i, 0, 0][i -1, 0, 0])

◆ dirichlet()

macro2 double dirichlet ( double  expr,
Point  point = point,
scalar  s = _s,
bool data = data 
)

For ease of use, we replace the Neumann and Dirichlet functions with macros so that they can be used either for standard domain boundaries or for embedded boundaries.

The distinction between the two cases is based on whether the dirichlet parameter is passed to the boundary function (using the data parameter).

Definition at line 717 of file embed.h.

References data, embed_area_center(), point, s, x, y, and z.

Referenced by embed_flux(), embed_gradient(), and event_metric().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dirichlet_gradient()

double dirichlet_gradient ( Point  point,
scalar  s,
scalar  cs,
coord  n,
coord  p,
double  bc,
double coef 
)

Definition at line 444 of file embed.h.

References bc, coef, cs, dimension, n, nodata, p, point, s, and x.

Referenced by embed_flux(), and embed_gradient().

Here is the caller graph for this function:

◆ dirichlet_homogeneous()

macro2 double dirichlet_homogeneous ( double  expr,
Point  point = point,
scalar  s = _s,
bool data = data 
)

Definition at line 725 of file embed.h.

References data, and s.

◆ embed_area_center()

static double embed_area_center ( Point  point,
double x1,
double y1,
double z1 
)
inlinestatic

This function and the macro below shift the position $(x1,y1,z1)$ to the position of the barycenter of the embedded fragment.


Definition at line 239 of file embed.h.

References area(), cs, embed_geometry(), n, p, point, x, and y1.

Referenced by dirichlet(), and neumann().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ embed_flux()

double embed_flux ( Point  point,
scalar  s,
vector  mu,
double val 
)

Flux through the embedded boundary

This function computes the flux through the embedded boundary contained within a cell

\[ \int_b \mu \nabla s\cdot\mathbf{n} db \]

with \(db\) the elementary boundary surface and \(\mathbf{n}\) the embedded boundary (outward-pointing) normal.

Boundary conditions for s are taken into account.

The result is returned in val.

For degenerate cases, the value returned by the function must be multiplied by s[] and added to val.

If the cell does not contain a fragment of embedded boundary, the flux is zero.

If the boundary condition is homogeneous Neumann, the flux is zero.

We compute the normal, area and barycenter of the fragment of embedded boundary contained within the cell.

If the boundary condition is Dirichlet, we need to compute the normal gradient.

We retrieve the (average) value of \(\mu\) without the metric.

Definition at line 657 of file embed.h.

References alpha, area(), coef, cs, dimension, dirichlet(), dirichlet_gradient(), embed, facet_normal(), fm, fs, metric_embed_factor, mu, n, normalize(), p, plane_alpha, plane_area_center, point, s, SEPS, val(), vector::x, and x.

Referenced by relax_diffusion(), residual_diffusion(), and viscosity().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ embed_force()

trace void embed_force ( scalar  p,
vector  u,
vector  mu,
coord Fp,
coord Fmu 
)

The force exerted by the fluid on the solid can be written.

\[ \mathbf{F}_{\Gamma} = - \int_{\partial \Gamma} ( - p\mathbf{I} + 2 \mu \mathbf{D}) \cdot \mathbf{n}d \partial \Gamma \]

with \(\Gamma\) the solid boundary. It can be further decomposed into a pressure (i.e. "form") drag

\[ \mathbf{F}_p = \int_{\partial \Gamma} p \mathbf{n}d \partial \Gamma \]

and a viscous drag

\[ \mathbf{F}_{\mu} = - \int_{\partial \Gamma} 2 \mu \mathbf{D} \cdot \mathbf{n}d \partial \Gamma \]

These two vectors are computed by the embed_force() function.

To compute the pressure force, we first get the coordinates of the barycentre of the embedded fragment, its area and normal, and then interpolate the pressure field on the surface.

To compute the viscous force, we first need to retrieve the local value of the viscosity (ideally at the barycentre of the embedded fragment). This is not completely trivial since it is defined on the faces of the cell. We use a surface-fraction-weighted average value.

To compute the viscous force, we need to take into account the (Dirichlet) boundary conditions for the velocity on the surface. We only know how to do this when computing the normal gradient \(\mathbf{\nabla}\mathbf{u}\cdot\mathbf{n}\) using the embed_gradient() function. We thus need to re-express the viscous force using only normal derivatives of the velocity field.

If we assume that \(\mathbf{u}\) is constant on the boundary, then

\[ \mathbf{{\nabla}} \mathbf{u} \cdot \mathbf{t}= \mathbf{0} \]

with \(\mathbf{t}\) the unit tangent vector to the boundary. We thus have the relations

\[ \mathbf{{\nabla}} \mathbf{u} = \left( \mathbf{{\nabla}} \mathbf{u} \cdot \mathbf{n} \right) \mathbf{n} + \left( \mathbf{{\nabla}} \mathbf{u} \cdot \mathbf{t} \right) \mathbf{t} = \left( \mathbf{{\nabla}} \mathbf{u} \cdot \mathbf{n} \right) \mathbf{n} \]

\[ \mathbf{D}= \frac{1}{2} \left( \mathbf{{\nabla}} \mathbf{u} + \mathbf{{\nabla}}^T \mathbf{u} \right) = \frac{1}{2} \left(\begin{array}{cc} 2 \left( \mathbf{{\nabla}} u \cdot \mathbf{n} \right) n_x & \left( \mathbf{{\nabla}} u \cdot \mathbf{n} \right) n_y + \left( \mathbf{{\nabla}} v \cdot \mathbf{n} \right) n_x\\ \left( \mathbf{{\nabla}} u \cdot \mathbf{n} \right) n_y + \left( \mathbf{{\nabla}} v \cdot \mathbf{n} \right) n_x & 2 \left( \mathbf{{\nabla}} v \cdot \mathbf{n} \right) n_y \end{array}\right) \]

\[ \mathbf{F}_{\mu} = - \int_{\Gamma} \left(\begin{array}{c} \left[2 \mu \left( \mathbf{{\nabla}} u \cdot \mathbf{n} \right) n_x \right] n_x + \mu \left[ \left( \mathbf{{\nabla}} u \cdot \mathbf{n} \right) n_y + \left( \mathbf{{\nabla}} v \cdot \mathbf{n} \right) n_x \right] n_y\\ \left[2 \mu \left( \mathbf{{\nabla}} v \cdot \mathbf{n} \right) n_y \right] n_y + \mu \left[ \left( \mathbf{{\nabla}} u \cdot \mathbf{n} \right) n_y + \left( \mathbf{{\nabla}} v \cdot \mathbf{n} \right) n_x \right] n_x \end{array}\right) \]

\[ \mathbf{F}_{\mu} = - \int_{\Gamma} \left(\begin{array}{c} \mu \left[ \left( \mathbf{{\nabla}} u \cdot \mathbf{n} \right) (n^2_x + 1) + \left( \mathbf{{\nabla}} v \cdot \mathbf{n} \right) n_x n_y \right]\\ \mu \left[ \left( \mathbf{{\nabla}} v \cdot \mathbf{n} \right) (n^2_y + 1) + \left( \mathbf{{\nabla}} u \cdot \mathbf{n} \right) n_x n_y \right] \end{array}\right) \]

Definition at line 511 of file embed.h.

References area(), assert, b, cs, dimension, embed_geometry(), embed_gradient(), embed_interpolate(), fm, mu, n, p, point, pow(), sq(), u, vector::x, and x.

Here is the call graph for this function:

◆ embed_geometry()

static double embed_geometry ( Point  point,
coord p,
coord n 
)
inlinestatic

Utility functions for the geometry of embedded boundaries

For a cell containing a fragment of embedded boundary (i.e. for which \(0 < cs < 1\)), embed_geometry() returns the area of the fragment, the relative position p of the barycenter of the fragment and the boundary normal n.

Definition at line 225 of file embed.h.

References alpha, area(), cs, facet_normal(), fs, n, normalize(), p, plane_alpha, plane_area_center, and point.

Referenced by embed_area_center(), and embed_force().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ embed_gradient()

static coord embed_gradient ( Point  point,
vector  u,
coord  p,
coord  n 
)
inlinestatic

Surface force and vorticity

We first define a function which computes \(\mathbf{\nabla}\mathbf{u}\cdot\mathbf{n}\) while taking the boundary conditions on the embedded surface into account.

Definition at line 473 of file embed.h.

References cs, dimension, dirichlet(), dirichlet_gradient(), embed, n, nodata, p, point, u, val(), x, and coord::x.

Referenced by embed_force(), and embed_vorticity().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ embed_interpolate()

double embed_interpolate ( Point  point,
scalar  s,
coord  p 
)

This function returns the value of field s interpolated linearly at the barycenter p of the fragment of embedded boundary contained within the cell.

Definition at line 257 of file embed.h.

References assert, cs, dimension, i, j, p, s, sign(), val(), and x.

Referenced by embed_force().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ embed_vorticity()

double embed_vorticity ( Point  point,
vector  u,
coord  p,
coord  n 
)

In two dimensions, embed_vorticity() returns the vorticity of velocity field u, on the surface of the embedded boundary contained in the cell.

p is the relative position of the barycentre of the embedded fragment and n its normal.

We compute \(\mathbf{{\nabla}}\mathbf{u}\cdot\mathbf{n}\), taking the boundary conditions into account.

The vorticity is then obtained using the relations

\[ \omega = \partial_x v - \partial_y u = \left( \mathbf{{\nabla}} v \cdot \mathbf{n} \right) n_x - \left( \mathbf{{\nabla}} u \cdot \mathbf{n} \right) n_y \]

Definition at line 618 of file embed.h.

References embed_gradient(), n, p, point, u, and x.

Here is the call graph for this function:

◆ event_defaults()

void event_defaults ( void  )

We add the embedded boundary to the default display.

Event: defaults (i = 0)

Event: defaults (i = 0 )

The default density field is set to unity (times the metric).

We reset the multigrid parameters to their default values.

If the viscosity is non-zero, we need to allocate the face-centered viscosity field.

We also initialize the list of tracers to be advected with the VOF function \(f\) (or its complementary function).

We set limiting.

On trees, we ensure that limiting is also applied to prolongation and refinement.

We add the interface and the density to the default display.

We switch to a pure minmod limiter by default for increased robustness.

With the MUSCL scheme we use the CFL depends on the dimension of the problem.

On trees we need to replace the default bilinear refinement/prolongation with linear so that reconstructed values also use slope limiting.

The restriction/refine attributes of the charge density are those of a tracer otherwise the conservation is not guaranteed.

By default the permittivity is unity and other quantities are zero.

Definition at line 953 of file embed.h.

References display().

Here is the call graph for this function:

◆ event_metric()

void event_metric ( void  )

Event: metric (i = 0)

Default settings

To apply the volume/area fraction-weighting to the solvers, we define the embedded solid using the embedded fractions. The fields are no longer constant and must be allocated.

The cm and fm fields contain the product of the metric and solid factors. For a Cartesian coordinate system cm and fm are thus identical to the solid factor fields cs and fs.

For prolongation we cannot use the same function since the surface fraction field fs is not necessarily defined for prolongation cells. So we switch back to the default fraction refinement (which is less accurate but only relies on cs).

Note that we do not need to change the refine method since the default refine method calls the prolongation method for each component.

Definition at line 909 of file embed.h.

References _i, assert, cm, cs, dimension, embed_fraction_refine(), fm, fraction_refine(), fs, restriction, vector::x, and x.

Here is the call graph for this function:

◆ for() [1/2]

for ( )

Definition at line 279 of file cartesian.h.

References list_add(), periodic_bc(), right, s, and x.

Here is the call graph for this function:

◆ for() [2/2]

for ( )

◆ fractions_cleanup()

trace int fractions_cleanup ( scalar  c,
vector  s,
double  smin = 0.,
bool  opposite = false 
)

Since both surface and volume fractions are altered, iterations are needed. This reflects the fact that changes are coupled spatially through the topology of the domain: for examples, long, unresolved "filaments" may need many iterations to be fully removed.

Face fractions of empty cells must be zero.

If opposite surface fractions are zero (and volume fraction is non-zero), then we are dealing with a thin "tube", which we just remove because it can sometimes lead to non-convergence when projecting the velocity field.

The number of "non-empty" faces (i.e. faces which have a surface fraction larger than epsilon) cannot be smaller than the dimension (the limiting cases correspond to a triangle in 2D and a tetrahedron in 3D).

Definition at line 295 of file embed.h.

References _i, c, dimension, i, LINENO, n, s, and x.

Referenced by event_adapt().

Here is the caller graph for this function:

◆ if() [1/5]

if ( (fs .x[i, j] > 0.5 && fs .y[i, j+(j< 0)] && fs .y[i-1, j+(j< 0)] && cs[i, j] && cs[i-1, j])  )

◆ if() [2/5]

if ( defined  )
pure virtual

◆ if() [3/5]

if ( fs.x &&fs.y &&fs.y &&cs &&cs &&  cs[i+(i< 0), j][i, j][i, j+1][i, j-1][i, j][i, j+1])

◆ if() [4/5]

if ( v  [0] = nodata)

This is a degenerate case, we use the boundary value and the cell-center value to define the gradient.

Definition at line 423 of file embed.h.

References bc, coef, d, max, n, p, and x.

◆ if() [5/5]

if ( v [1] = nodata)

◆ neumann()

macro2 double neumann ( double  expr,
Point  point = point,
scalar  s = _s,
bool data = data 
)

Definition at line 732 of file embed.h.

References data, embed_area_center(), point, s, x, y, and z.

Here is the call graph for this function:

◆ neumann_homogeneous()

macro2 double neumann_homogeneous ( double  expr,
Point  point = point,
scalar  s = _s,
bool data = data 
)

Definition at line 740 of file embed.h.

References data, and s.

◆ return() [1/3]

return ( a a[i][i-1])

◆ return() [2/3]

return ( bc v[0])

◆ return() [3/3]

return ( fs x[i, j],
0.5 &&fs .y &&fs .y &&cs &&  cs[i, j+(j< 0)][i-1, j+(j< 0)][i, j][i-1, j] 
)

◆ update_tracer()

trace void update_tracer ( scalar  f,
vector  uf,
vector  flux,
double  dt 
)

Prolongation for the multigrid solver

We use a simplified prolongation operator for the multigrid solver i.e. simple injection if bilinear interpolation would use values which are fully contained within the embedded boundary.

Lifting the "small cell" CFL restriction

For explicit advection schemes, the timestep is limited by the CFL conditions

\[ \Delta t < \frac{c_s\Delta}{f_i|u_i|} \]

where \(i\) is the index of each face, and \(c_s\) and \(f_i\) are the embedded volume and face fractions respectively. It is clear that the timestep may need to be arbitrarily small if \(c_s/f_s\) tends toward zero. This is the "small cell" restriction of cut-cell finite-volume techniques.

A classical technique to avoid this limitation is to use a "cell merging" procedure, where the fluxes from cells which would "overflow" are redistributed to neighboring cells.

The function below uses this approach to update a field f, advected by the face velocity field uf, with corresponding advection fluxes flux*, during timestep dt which only verifies the standard CFL condition

\[ \Delta t < \frac{\Delta}{|u_i|} \]

Note that the distinction should be made between \(c_m\), the cell fraction metric, and \(c_s\), the embedded fraction. This is not done now so that embedded boundaries cannot be combined with a metric yet.

The field e will store the "overflowing" sum of fluxes for each cell.

If the cell is empty, it cannot overflow.

If the cell does not contain an embedded boundary, it cannot overflow either and the sum of the fluxes can be added to advance f* in time.

If the cell contains the embedded boundary, we compute the maximum timestep verifying the restrictive CFL condition

\[ \Delta t_{max} = \frac{c_s\Delta}{max(f_i|u_i|)} \]

Note that fs does not appear in the code below because uf already stores the product \(u_f \, f_m\).

We compute the sum of the fluxes.

If the timestep is smaller than \(\Delta t_{max}\), the cell cannot overflow and f is advanced in time using the entire flux.

Otherwise, the cell is filled "to the brim" by advancing f using the maximum allowable timestep. The field e is used to store the excess flux, weighted by the sum of the neighboring embedded fractions.

In a second phase, the excesses in each cell are added to the neighboring cells in proportion of their embedded fractions.

Definition at line 803 of file embed.h.

References _i, cm, cs, dimension, dt, dtmax, f, flux, i, SEPS, sq(), uf, vector::x, and x.

Referenced by advection().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ __pad0__

l<= 1; l++) { int i = (l + 1)*sign(n.x); d[l] = (i - p.x)/n.x; double y1 = p.y + d[l]*n.y; int j = y1 > __pad0__

Definition at line 388 of file embed.h.

◆ a

scalar a

Definition at line 73 of file embed.h.

◆ attribute

*cs[i, 0, 0] a *[i -1, 0, 0] * cs [ i , j , 0 ] a* [ i -1, j , 0 ] cs (cs[ i , j , 0 ] + cs[ i -1, j , 0 ] + 3.)))/2. attribute
Initial value:
{
bool third

The generalisation to 3D is a bit more complicated.

See Fig. 1 of Schwartz et al, 2006. We use the functions above to redefine the face gradient macros. Note that the second-order face gradients and averaging are used only if the corresponding scalar attribute below (third because of third-order accuracy when using Dirichlet conditions, see [test/neumann.c]) is set to true. The default is false.

Definition at line 179 of file embed.h.

◆ bc

◆ break

else break

Definition at line 421 of file embed.h.

◆ coef

* coef
Initial value:
{
for (int _d = 0; _d < 2; _d++)
n.x = - n.x
scalar scalar coord n
Definition embed.h:378

For non-degenerate cases, the gradient is obtained using either second- or third-order estimates.

Definition at line 379 of file embed.h.

Referenced by colormap_color(), dirichlet_gradient(), embed_flux(), and if().

◆ cs

◆ d

◆ defined

bool defined = true

Definition at line 384 of file embed.h.

◆ embed

bid embed

Definition at line 463 of file embed.h.

Referenced by embed_flux(), embed_gradient(), and viscosity().

◆ fs

◆ i

Initial value:
{
int j = sign(fs.x[i,1] - fs.x[i,-1])
static int sign(number x)
Definition common.h:13

Definition at line 73 of file embed.h.

Referenced by _box_json(), _cells_json(), _draw_string_json(), _draw_vof_json(), _isoline_json(), _isosurface_json(), _labels_json(), _lines_json(), _squares_json(), _travelling_json(), _vectors_json(), _view_json(), adapt_wavelet(), add_boundary(), advance_generic(), advect(), alloc_children(), append_pid(), apply_bc(), area_integral(), args(), array_remove(), assemble_node(), barycenter(), bc_grd(), blue_white_red(), boundary_internal(), boundary_stencil(), bubbles_are_close(), bview_interface_json(), cartesian_scalar_clone(), cell(), check_depth(), check_flags(), check_snd_rcv_matrix(), check_stencil(), check_two_one(), colorized(), colormap_color(), cool_warm(), cpu_reduction(), curvature_prolongation(), de(), debug_mpi(), delete(), delete_terrain(), diagonalization_2D(), display_control_json(), display_control_lookup(), display_destroy(), display_send(), display_update(), dphidt(), eigenvalues(), eigsrt(), embed_interpolate(), evaluate_expression(), event__progress(), event_acceleration(), event_cleanup(), event_cond(), event_defaults(), event_face_fields(), event_perfs(), event_refresh_display(), event_viscous_term(), event_vof(), facets(), fclone(), find_coreGL(), flux(), for(), foreach_cell_post_root(), foreach_stencil(), foreach_stencil_generic(), fractions_cleanup(), free_boundaries(), free_solver(), GetRoot(), getvalue(), gpu_errors_scan_bytes(), gpu_reduction(), gray(), height_curvature_fit(), if(), if(), inc_scan_bytes(), includes(), independents(), init_const_scalar(), init_event(), init_grid(), init_solver(), input_pgm(), input_stl(), interfacial(), interpolate_array(), interpolate_linear(), jet(), kdt_heap_split(), kdt_write(), lambda2(), list_clone(), list_prepend(), list_print(), load(), lookup_tag(), main(), mapped_position(), matrix_new(), maxruntime(), mem_allocated(), mem_allocated(), mem_assign(), mem_assign(), mem_destroy(), mem_free(), mem_free1d(), mempool_alloc(), mempool_free(), memrange_alloc(), memrange_free(), mg_cycle(), mpi_boundary_refine(), mpi_boundary_update_buffers(), mpi_partitioning(), msolve(), new_const_scalar(), new_const_vector(), next_string(), no_coalescence(), normal_neighbor(), ohmic_flux(), OMP_PARALLEL(), open_image_cleanup(), open_image_lookup(), openpath(), output_fluxes(), output_vtk(), parabola_fit_add(), parabola_fit_init(), parabola_fit_solve(), parse_params(), periodic_boundary_level_x(), periodic_function(), pmfunc_index(), pmfuncs_free(), pmuntrace(), post_scan_bytes(), prediction(), prolongation_vertex(), psort(), push_once(), py_action(), py_inc(), py_start(), qpclose(), qpclose_all(), qpopen(), quad_neighbor(), quad_neighbor_finest(), quad_x(), quad_y(), query(), query_sum(), randomap(), rcv_destroy(), rcv_pid_append_pids(), rcv_pid_destroy(), rcv_pid_pointer(), rcv_pid_print(), rcv_pid_receive(), rcv_pid_row(), rcv_pid_send(), rcv_pid_wait(), rcv_pid_write(), realloc_scalar(), refine_embed_linear(), refine_face_solenoidal(), remap_c(), remap_robin(), remove_droplets(), repeat(), reset(), restriction_embed_linear(), restriction_vertex(), riemann(), right_value(), RPE(), segment_flux(), smatrix_inverse(), solve(), solve_hessenberg(), stencil_val(), stencil_val_a(), tag(), terrain(), timer_print(), timer_timing(), tracer_fluxes(), tracer_is_close(), tree_boundary_level(), treex(), update_cache_f(), update_conservation(), update_distance(), update_sum(), update_tracer(), vertex_buffer_glBegin(), vertex_buffer_glEnd(), vertex_buffer_push_index(), vertical_remapping(), volumez(), ws_send_array(), yy_get_next_buffer(), yy_get_next_buffer(), yy_get_next_buffer(), z_indexing(), zarea(), and zvolume().

◆ j

◆ metric_embed_factor

double(* metric_embed_factor) (Point, coord) ( Point  ,
coord   
) = NULL

Definition at line 24 of file embed.h.

Referenced by embed_flux(), and event_metric().

◆ n

◆ p

◆ s

◆ v

◆ y1

y1 = j

Definition at line 394 of file embed.h.

Referenced by DistancePointEllipse(), embed_area_center(), okada(), and parabola_fit_add().