SpECTRE  v2021.12.06
elliptic::BoundaryConditions::BoundaryCondition< Dim, Registrars > Class Template Reference

Base class for boundary conditions for elliptic systems. More...

#include <BoundaryCondition.hpp>

Public Types

using registrars = Registrars
 
using creatable_classes = Registration::registrants< registrars >
 

Public Member Functions

 BoundaryCondition (const BoundaryCondition &)=default
 
 BoundaryCondition (BoundaryCondition &&)=default
 
BoundaryConditionoperator= (const BoundaryCondition &)=default
 
BoundaryConditionoperator= (BoundaryCondition &&)=default
 
- Public Member Functions inherited from domain::BoundaryConditions::BoundaryCondition
 BoundaryCondition (BoundaryCondition &&)=default
 
BoundaryConditionoperator= (BoundaryCondition &&)=default
 
 BoundaryCondition (const BoundaryCondition &)=default
 
BoundaryConditionoperator= (const BoundaryCondition &)=default
 
 BoundaryCondition (CkMigrateMessage *const msg)
 
 WRAPPED_PUPable_abstract (BoundaryCondition)
 
virtual auto get_clone () const -> std::unique_ptr< BoundaryCondition >=0
 

Static Public Attributes

static constexpr size_t volume_dim = Dim
 

Detailed Description

template<size_t Dim, typename Registrars>
class elliptic::BoundaryConditions::BoundaryCondition< Dim, Registrars >

Base class for boundary conditions for elliptic systems.

Boundary conditions for elliptic systems derive from this abstract base class. This allows boundary conditions to be factory-created from input-file options. Specific systems may implement further abstract base classes that derive from this class and add additional requirements.

Each derived class represents one kind of boundary conditions. For example, one derived class might implement homogeneous (zero) Dirichlet or Neumann boundary conditions, another might implement Dirichlet fields procured from an analytic solution, and yet another might set the boundary fields as a function of the dynamic variables on the domain boundary (e.g. Robin-type boundary conditions).

Note that almost all boundary conditions are actually nonlinear because even those that depend only linearly on the dynamic fields typically contribute non-zero field values. For example, a standard Dirichlet boundary condition \(u(x=0)=u_0\) is nonlinear for any \(u_0\neq 0\). Boundary conditions for linear systems may have exactly this nonlinearity (a constant non-zero contribution) but must depend at most linearly on the dynamic fields. Boundary conditions for nonlinear systems may have any nonlinearity. Either must implement their linearization as a separate function (see below). For linear systems the nonlinear (constant) contribution is typically added to the fixed-source part of the discretized equations and the linearized boundary conditions are being employed throughout the solve so the discretized operator remains linear. For nonlinear systems we typically solve the linearized equations repeatedly for a correction quantity, so we apply the linearized boundary conditions when solving for the correction quantity and apply the nonlinear boundary conditions when dealing with the nonlinear fields that are being corrected (see e.g. NonlinearSolver::newton_raphson::NewtonRaphson).

Derived classes are expected to implement the following compile-time interface:

  • They are option-creatable.
  • They have type aliases argument_tags, volume_tags, argument_tags_linearized and volume_tags_linearized. Those aliases list the tags required for computing nonlinear and linearized boundary conditions, respectively. The tags are always taken to represent quantities on the interior side of the domain boundary, i.e. whenever normal vectors are involved they point out of the computational domain. The volume_tags list the subset of the argument_tags that are not evaluated on the boundary but taken from the element directly.
  • They have apply and apply_linearized member functions that take these arguments (in this order):

    1. The dynamic fields as not-null pointers.
    2. The normal-dot-fluxes corresponding to the dynamic fields as not-null pointers. These have the same types as the dynamic fields.
    3. The types held by the argument tags.

    For first-order systems that involve auxiliary variables, only the non-auxiliary ("primal") variables are included in the lists above. For example, boundary conditions for a first-order Poisson system might have an apply function signature that looks like this:

    static void apply(const gsl::not_null<Scalar<DataVector>*> field,
    const gsl::not_null<Scalar<DataVector>*> n_dot_flux,
    const int arg_on_face, const bool arg_from_volume,
    const int arg_nonlinear) {
    Require a pointer to not be a nullptr
    Definition: Gsl.hpp:183
    auto apply(F &&f, const ObservationBox< ComputeTagsList, DataBoxType > &observation_box, Args &&... args)
    Apply the function object f using its nested argument_tags list of tags.
    Definition: ObservationBox.hpp:171
    Tensor< T, Symmetry<>, index_list<> > Scalar
    Scalar type.
    Definition: TypeAliases.hpp:21

The fields and normal-dot-fluxes passed to the apply and apply_linearized functions hold data which the implementations of the functions can use, and also serve as return variables. Modifying the fields means applying Dirichlet-type boundary conditions and modifying the normal-dot-fluxes means applying Neumann-type boundary conditions. Just like the arguments evaluated on the boundary, the normal-dot-fluxes involve normal vectors that point out of the computation domain. Note that linearized boundary conditions, as well as nonlinear boundary conditions for linear systems, may only depend linearly on the field data, since these are the fields the linearization is performed for.


The documentation for this class was generated from the following file: