Boundary Conditions
Built-in boundary conditions
Natively, Parthenon supports three kinds of boundary conditions:
periodic
outflow
reflecting
which are all imposed on variables with the Metadata::FillGhost
metadata flag. To set the boundaries in each direction, set the
*x*_bc
variables under parthenon/mesh
in the input file. e.g.,
<parthenon/mesh>
ix1_bc = outflow
ox1_bc = outflow
ix2_bc = reflecting
ox2_bc = reflecting
ix3_bc = periodic
ox3_bc = periodic
sets outflow boundary conditions in the X1
direction, reflecting in
X2
, and periodic in X3
.
User-defined boundary conditions.
You can provide your own boundary conditions by setting the the
boundary_conditions
function pointers in the ApplicationInput
for your parthenon_manager
. e.g.,
pman.app_input->boundary_conditions[parthenon::BoundaryFace::inner_x1] = MyBoundaryInnerX1;
where BoundaryFace
is an enum defined in defs.hpp
as
// identifiers for all 6 faces of a MeshBlock
constexpr int BOUNDARY_NFACES = 6;
enum BoundaryFace {
undef = -1,
inner_x1 = 0,
outer_x1 = 1,
inner_x2 = 2,
outer_x2 = 3,
inner_x3 = 4,
outer_x3 = 5
};
You can then set this boundary condition via the user
flag in the
input file:
<parthenon/mesh>
ix1_bc = user
Boundary conditions so defined should look roughly like
// an implementation of outflow conditions
void MyBoundaryInnerX1(std::shared_ptr<MeshBlockData<Real>> &rc, bool coarse) {
std::shared_ptr<MeshBlock> pmb = rc->GetBlockPointer();
auto bounds = coarse ? pmb->c_cellbounds : pmb->cellbounds;
int ref = bounds.GetBoundsI(IndexDomain::interior).s;
auto q = rc->PackVariables(std::vector<MetadataFlag>{Metadata::FillGhost}, coarse);
auto nb = IndexRange{0, q.GetDim(4) - 1};
pmb->par_for_bndry(
"OutflowInnerX1", nb, IndexDomain::inner_x1, coarse,
KOKKOS_LAMBDA(const int &l, const int &k, const int &j, const int &i) {
q(l, k, j, i) = q(l, k, j, ref);
});
}
Important things to note:
The signature is a
std::shared_ptr<MeshBlockData<Real>>
and a boolean.The boolean determines whether the boundary condition is applied over ghost cells on a coarse buffer (for mesh refinement) or for a fine buffer.
You can use the
MeshBlock::par_for_bndry
abstraction to loop over the appropriate cells by specifying theIndexDomain
for the ghost region and whether or not the loop is coarse. For more information on theIndexDomain
object, see here.You can pack over all the coarse or fine buffers of a variable with the
PackVariables
optionalcoarse
boolean as seen here.
Other than these requirements, the Boundary
object can do whatever
you like. Reference implementations of the standard boundary conditions
are available here.