Skip to content

Boundary conditions ​

Each of the six faces of the domain takes a boundary condition from its section [bc_x_min], [bc_x_max], [bc_y_min], [bc_y_max], [bc_z_min], [bc_z_max]. The condition fills the ghost cells of the blocks that touch the face before every residual evaluation; interior block faces, inter-realm seams and AMR coarse–fine faces are filled by the exchange machinery instead (below).

Input ​

There are six sections, [bc_x_min], [bc_x_max], [bc_y_min], [bc_y_max], [bc_z_min] and [bc_z_max], which are faces 1–6. Each section requires type. The value goes through strip_control, so CRLF files are accepted. Seven values are accepted, and matching is case-sensitive:

typeidper-face keys
extrapolationBC_EXTRAPOLATION = 1none
inflowBC_INFLOW = 2r, u, v, w, p (+ bx, by, bz for MHD), all required
wall-inviscidBC_WALL_INVISCID = 3none
wall-noslipBC_WALL_NOSLIP = 4wall_u, wall_v, wall_w (optional, default 0; the normal one must be 0)
wall-isothermalBC_WALL_ISOTHERMAL = 5wall_temperature (required, >0), wall_u, wall_v, wall_w as above
periodiclibrary BC_PERIODIC = -1none
hydrostaticBC_HYDROSTATIC = 6none (reads [gravity]); refused with [eos] isothermal or barotropic
non-reflectingBC_NONREFLECTING = 8the target r, u, v, w, p (required), nr_length L (required, >0), nr_sigma σ (default 0.28); Euler only (#121 S2)
shock-generatorBC_SHOCK_GENERATOR = 9the upstream r, u, v, w, p, one of shock_deflection and shock_angle (degrees), shock_x, shock_x_end (optional); bc_y_min and bc_y_max only, Euler only (#121 S3)

Validation:

  • an unknown value stops the run and the message lists the accepted spellings;
  • a missing inflow key, or a missing or non-positive wall_temperature, is fatal;
  • a non-zero normal wall velocity is fatal (the wall does not move through the domain);
  • periodicity must be paired: [bc_x_min] and [bc_x_max] must both be periodic or neither, and the same for y and z;
  • a physical model other than Euler or MHD is fatal.

How the ghost cells are filled ​

update_ghost runs three steps in order:

  1. the intra-realm local copies;
  2. the MPI exchange;
  3. set_boundary_conditions.

Step 3 walks the boundary crown map maps%local_map_bc_crown crown by crown, c=1..ngc, from the innermost crown outwards. Each ghost cell (i,j,k) carries an "inward step" (δi,δj,δk), its BC type and its fec code (face 1–6, edge 7–18, corner 19–26). The CPU implementation is cpu/adam_flume_cpu_object.F90; the FNL twin is fnl/adam_flume_fnl_kernels.F90, called crown by crown from fnl/adam_flume_fnl_object.F90. Both apply the same rules.

The grid receives the six BC ids through grid%set_bc_type. That call turns on is_ijk_periodic for a periodic axis.

extrapolation: zeroth order (constant) ​

qghost(i,j,k)=q(i−δi,j−δj,k−δk)

Each ghost copies its inward neighbour. The crowns are filled innermost first, so every ghost column ends up equal to the first interior cell: q(1−g)=q(1) for g=1..ngc. This is order-0 extrapolation, a zero-gradient outflow, and matches the !< Zeroth-order extrapolation comment. All nv variables are copied, including ψ.

inflow: prescribed state (Dirichlet on the full conservative vector) ​

qghost=qinflow(f)on every crown

qinflow(f) is converted once from the primitive keys. For MHD with GLM this sets ψ=0 in the inflow ghosts.

wall-inviscid: slip wall by mirroring with a sign vector ​

qghost(i,j,k)=Sd⊙q(im,jm,km),d=⌈f/2⌉

The mirror index reflects the ghost across the face:

facemirror
xminim=1−i
xmaxim=2ni+1−i
yminjm=1−j
ymaxjm=2nj+1−j
zminkm=1−k
zmaxkm=2nk+1−k

So ghost 1−g mirrors interior cell g, for example q(0)←Sq(1) and q(−1)←Sq(2).

The sign vector Sd is built by adam_flume_bc_object.F90:

variableEulerMHD / MHD-GLM
ρ, E+1 (even)+1
ρun (the normal momentum of direction d)−1 (odd)−1
ρut (tangential momenta)+1+1
Bn (the normal field of direction d)—−1 (odd), a perfectly conducting reflecting wall (issue #41, D-12)
Bt—+1
ψ—+1 (even)

E is unchanged by the sign flips because it depends only on squares of the flipped components. The ghost state is therefore the exact mirror image. As a result, un=0 and Bn=0 at the wall face in the sense of the symmetric average, and ∂nψ=0 there.

wall-noslip and wall-isothermal: no-slip walls ​

The two no-slip walls (#65, D-M4-7) mirror the cell like wall-inviscid and reflect the whole velocity about the wall velocity uw (tangential, wall_u, wall_v, wall_w):

ug=2uw−um,pg=pm,

so the mean of the ghost and its mirror cell is the wall velocity (no slip, no penetration). The pressure is mirrored.

  • wall-noslip (adiabatic) mirrors the temperature, so ρg=ρm and ∂nT=0 at the wall in the sense of the symmetric difference.
  • wall-isothermal sets the ghost temperature to the geometric mirror, Tg=Tw2/Tm, so the geometric mean of the ghost and its mirror cell is the wall temperature, and the density from the mirrored pressure, ρg=pm/(RTg), with T=p/(ρR). The ghost is admissible for any admissible cell. Until #65 P2 the mirror was linear, Tg=2Tw−Tm, which is negative beside gas hotter than twice the wall: on Sod's right state (T=0.0027) against a wall at Tw=0.001 the ghosts reached ρ=−1.96, silently, with no non-finite value. For Tm=Tw+δ the two mirrors differ by δ2/Tw, so both are second-order at the wall.

The total energy is rebuilt from the ghost state, Eg=pg/(γ−1)+12ρg|ug|2+emag, where the magnetic energy emag (and ψ2/2 under EGLM) is unchanged by the mirror. The field follows the wall-inviscid rule (normal component odd, a perfectly conducting wall); ψ is even. On a resting adiabatic wall the rule reduces to a sign vector with every momentum component odd. Both walls are second-order accurate at the wall, by construction of the mirror.

The rule is the pure procedure wall_noslip_ghost in adam_flume_bc_object.F90, shared by both backends. It is model-agnostic: the field components are those present in the state vector (none for Euler), so no kernel branches on the model. The ghost probe GP checks it on every face and edge, moving and resting walls, Euler and MHD with EGLM (verification).

The walls are boundary conditions of the ideal solver too: they take effect on any run. Their physical test is the compressible Couette flow between an isothermal wall and a moving adiabatic one, against its exact profiles (VV-3): the moving-wall mirror is exact for its linear velocity and symmetric temperature, the isothermal mirror Tw2/T is second-order, so the run converges at order 2.

hydrostatic: an atmosphere under gravity (#73) ​

The ghost density and pressure continue the isothermal hydrostatic equilibrium of the first interior cell along the normal, ρg=ρ1exp⁡(gds/T1), pg=ρgT1, with T1=p1/ρ1 and s the signed distance from that cell to the ghost along the axis d: an isothermal atmosphere has exact ghosts. The velocity is mirrored as at wall-inviscid (no mass flux); the magnetic field and ψ are mirrored even. Without gravity along the normal it is a slip wall that copies the first interior cell's thermodynamic state (Zingale et al. 2002). Source: adam_flume_bc_object.F90 (hydrostatic_ghost).

non-reflecting: a characteristic outflow and far field (#121 S2) ​

The ghosts are the first interior cell plus the jumps of the characteristic variables, linearised about it (outward normal velocity un, sound speed c):

  • Outgoing waves (speed >0): no jump, extrapolated.
  • The incoming acoustic wave, w1=p−ρcun with speed un−c<0: its gradient along the normal is set by the relaxation of Rudy & Strikwerda (1980) and Poinsot & Lele (1992), ∂w1/∂n=K(p−pt)/(un−c), K=σ(1−M2)c/L. Ghost m lies m cells off the interior cell, and w5=p+ρcun is unchanged.
  • Flow into the domain (un<0): the entropy ρ−p/c2 and the tangential velocity of the target; un+c≤0 (supersonic inflow) the whole target.

A supersonic outflow, or σ=0 at an outflow, is extrapolation bit for bit. The edge and corner rows beyond the face are extrapolated.

When to use it. In this characteristic-upwind scheme extrapolation (outflow) and inflow (a prescribed state) already let linear waves out: they make the incoming characteristic jumps zero, or the free stream's. What they cannot do is hold a mean pressure at a subsonic outflow, and extrapolation keeps whatever pressure the box has. non-reflecting pulls it to pt on the time scale 1/K. The price is a reflection of order σc/(ωL) of a wave of frequency ω passing through. Measured in the verification:

non-reflectingthe alternative
a 2 % overpressure at Mach 0.5, left after t=20=10L/c0.099extrapolation: 1.000
a packet leaving at rest (λ=0.2, L=2), left behind2.9e-3 (σ=0.28), 7.6e-4 (σ=0.07)extrapolation: 1.2e-4
a packet leaving through a subsonic inflow face, left behind4.3e-3inflow: 1.4e-5

Source: adam_flume_bc_object.F90 (nonreflecting_ghost).

shock-generator: an oblique shock through a y face (#121 S3) ​

The face of a shock–boundary-layer interaction that brings the incident shock in (the top of the box). The ghosts with shock_x ≤x< shock_x_end take the state behind an oblique shock in the upstream state r, u, v, w, p; the others are extrapolated, as are the edge and corner rows beyond the face. The shock is given by its deflection θ (shock_deflection, the weak solution of the θ–β–M relation) or by its angle β from the upstream velocity (shock_angle), and turns the flow toward the opposite face. The post-shock state follows from the normal Mach number Msin⁡β, with M of the velocity in the x-y plane (Rankine–Hugoniot; Anderson, Modern Compressible Flow, ch. 4); w, tangent to the shock, is unchanged. The run prints the shock angle, the deflection and p2/p1.

  • Refused: a flow that is not supersonic in the x-y plane, an angle outside (μ,90∘], a deflection beyond detachment, a face other than y, a model other than Euler (no dual energy, no passive scalars).
  • The rest of the face is extrapolation: upstream of shock_x the free stream leaves or enters at its own state, as at an extrapolated top. A reflected shock that reaches the face beyond shock_x_end leaves through it.

Measured in the verification: at Mach 2 and 10∘ the shock angle within 0.01∘ of 39.314∘, the state behind it within 1.5⋅10−3 of Rankine–Hugoniot.

Source: adam_flume_bc_object.F90 (oblique_shock).

periodic ​

periodic gets no crown rows. The library tree builds true periodic neighbours, and update_ghost_local and update_ghost_mpi fill the ghosts across blocks and ranks. It is the library BC_PERIODIC (as PRISM's periodic since cd92194a), so it works with any number of blocks along the axis, one included: the tree and the maps are rebuilt once the BC types are known (#103; before, a grid not refined at init kept its boundary neighbours, which the CPU refused and the FNL silently left unfilled). The only constraint is the pairing rule in B.1.

Edges and corners (fec > 6) ​

An edge ghost lies outside its block along two axes, a corner ghost along three. The directional WENO stencils never read them, but a cross derivative does: the tangential derivatives of the viscous stress or of the current at a face (M4, #65) read the edge ghosts of the rows next to a block edge. They are filled so that the ghost layer continues the face ghosts, and the probe GP of the verification holds every face and edge ghost to a linear field on every path.

Each crown row carries the boundary its cell lies beyond (bc_fec, from the tree), which gives two cases:

  • Beyond one realm face (bc_fec a face). The cell's other directions lead into another block, whose ghosts the exchange has filled. The face's kind applies along its normal exactly as for a face ghost, so a wall edge mirrors the exchanged ghost and negates its normal momentum.
  • Beyond two or three realm faces (bc_fec an edge or a corner: an edge or a corner of the realm). The kind of one physical face among them applies, inflow first (an inflow ghost holds the inflow state whatever else it lies beyond), else the first non-seam face, realm_edge_face. It acts on the donor realm_edge_donor: the cell mirrored about that face (any wall kind) or the first interior cell along its normal (extrapolation), with the indexes along the other axes kept. The donor therefore lies beyond the other faces only. It is a face ghost (for an edge) or an edge ghost (for a corner), already filled by the seam, the exchange or its own face. Two walls compose to a double mirror with both normal momenta negated, and a wall beside a seam mirrors the seam ghost.

Beyond seams only, the cell lies outside every realm: the re-entrant corner of an L-shaped forest, inside the step of the Woodward–Colella tunnel. It keeps a copy of its inward diagonal, q(i−δi,j−δj,k−δk): finite, and read by no stencil of a fluid cell.

Both backends fill the crown in three passes, the rows beyond one face, then two, then three, each crown by crown, so that every donor is filled before it is read (set_boundary_conditions on the CPU, set_boundary_conditions_dev on FNL). Within the first pass no row reads another row of the pass: a wall row reads the mirrored interior cell, an extrapolation row the first interior cell along its normal (not the previous ghost of the chain, which gives the same value but is a row of the same launch: on FNL the chain raced, and a ghost beyond a block interface along another axis could read its donor before it was written; issue #65 P1). The kind of each realm face comes from [bc_*], overridden by maps%seam_face for the faces the forest glued. On FNL each launch visits the rows of its own pass only: the rows of every crown are grouped by pass on the host whenever the device map is copied (build_bc_pass_rows), and an empty pass is not launched (issue #90; before, each of the 3 × ngc launches scanned the whole crown map).

Before #65 P0 every row beyond two realm faces held its inward diagonal copy. On a linear field that is off by up to 0.78 of the field scale at a wall corner (wrong sign of the normal momentum, wrong position), measured by GP on the step forest.

Inter-realm seam ​

set_boundary_conditions leaves seam face rows untouched. The forest fills them through fill_seam_from_peer_forest, which is a plain injection copy of the peer's interior cell into this realm's ghost cell, following the seam ghost map rows. The buffers used are q when stage_active == 0, otherwise the active stage of rk%q_rk, on each side independently. update_ghost does not fill seam ghosts. Any diagnostic that reads them has to refill them explicitly; compute_divb_history does this. The field write does too: with sibling realms, save_simulation_data refills the seams and then calls update_ghost, the order of a Runge-Kutta stage, so the written ghosts (edges included) are those the stencils read. The step-0 file is the exception: it is written while each realm initialises, before the forest connects the realms, and its seam ghosts are unfilled.

2:1 AMR coarse-fine ghosts ​

These ghosts are library behaviour, not FLUME-specific. The regime is chosen by the optional key [amr] seam_ghost_fill = injection | restriction-compatible | tricubic. The default when the key is absent is tricubic, and an unknown value is fatal. The fill runs inside field%update_ghost_local.

Immersed solids ​

Immersed solids (for example regression/shock-cylinder-ib) are not a [bc_*] kind. They enter through the level-set phi and the cut spacing in compute_flux_difference, and are out of scope here.

Examples ​

Walls on x, extrapolation elsewhere, from src/tests/flume/verification/sod/sod-wall-x.ini:

ini
[bc_x_min]
type = wall-inviscid
[bc_x_max]
type = wall-inviscid
[bc_y_min]
type = extrapolation
[bc_y_max]
type = extrapolation
[bc_z_min]
type = extrapolation
[bc_z_max]
type = extrapolation

Euler inflow, from src/tests/flume/verification/shock-cylinder/shock-cylinder.ini:

ini
[bc_x_min]
type = inflow
r    = 3.7333333333333334
u    = 1.25
v    = 0.0
w    = 0.0
p    = 4.5
[bc_x_max]
type = extrapolation
[bc_y_min]
type = wall-inviscid
[bc_y_max]
type = wall-inviscid
[bc_z_min]
type = extrapolation
[bc_z_max]
type = extrapolation

MHD inflow, from src/tests/flume/verification/mhd/plumbing/mhd-uniform-glm.ini:

ini
[bc_z_min]
type = inflow
r    = 1.0
u    = 0.3
v    = -0.2
w    = 0.1
p    = 1.0
bx   = 0.8
by   = 0.5
bz   = -0.3

Periodic faces are written the same way, type = periodic, and must be set on both faces of an axis.