Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cstddef> 7 : #include <pup.h> 8 : #include <vector> 9 : 10 : #include "DataStructures/DataBox/DataBox.hpp" 11 : #include "Domain/BoundaryConditions/BoundaryCondition.hpp" 12 : #include "Elliptic/BoundaryConditions/BoundaryConditionType.hpp" 13 : #include "Utilities/Serialization/CharmPupable.hpp" 14 : #include "Utilities/TMPL.hpp" 15 : 16 : namespace elliptic { 17 : /// Boundary conditions for elliptic systems 18 : namespace BoundaryConditions { 19 : 20 : /*! 21 : * \brief Base class for boundary conditions for elliptic systems 22 : * 23 : * Boundary conditions for elliptic systems derive from this abstract base 24 : * class. This allows boundary conditions to be factory-created from input-file 25 : * options. Specific systems may implement further abstract base classes that 26 : * derive from this class and add additional requirements. 27 : * 28 : * Each derived class represents one kind of boundary conditions. For example, 29 : * one derived class might implement homogeneous (zero) Dirichlet or Neumann 30 : * boundary conditions, another might implement Dirichlet fields procured from 31 : * an analytic solution, and yet another might set the boundary fields as a 32 : * function of the dynamic variables on the domain boundary (e.g. Robin-type 33 : * boundary conditions). 34 : * 35 : * Note that almost all boundary conditions are actually nonlinear because even 36 : * those that depend only linearly on the dynamic fields typically contribute 37 : * non-zero field values. For example, a standard Dirichlet boundary condition 38 : * \f$u(x=0)=u_0\f$ is nonlinear for any \f$u_0\neq 0\f$. Boundary conditions 39 : * for linear systems may have exactly this nonlinearity (a constant non-zero 40 : * contribution) but must depend at most linearly on the dynamic fields. 41 : * Boundary conditions for nonlinear systems may have any nonlinearity. Either 42 : * must implement their linearization as a separate function (see below). For 43 : * linear systems the nonlinear (constant) contribution is typically added to 44 : * the fixed-source part of the discretized equations and the linearized 45 : * boundary conditions are being employed throughout the solve so the 46 : * discretized operator remains linear. For nonlinear systems we typically solve 47 : * the linearized equations repeatedly for a correction quantity, so we apply 48 : * the linearized boundary conditions when solving for the correction quantity 49 : * and apply the nonlinear boundary conditions when dealing with the nonlinear 50 : * fields that are being corrected (see e.g. 51 : * `NonlinearSolver::newton_raphson::NewtonRaphson`). 52 : * 53 : * Derived classes are expected to implement the following compile-time 54 : * interface: 55 : * 56 : * - They are option-creatable. 57 : * - They have type aliases `argument_tags`, `volume_tags`, 58 : * `argument_tags_linearized` and `volume_tags_linearized`. Those aliases list 59 : * the tags required for computing nonlinear and linearized boundary 60 : * conditions, respectively. The tags are always taken to represent quantities 61 : * on the _interior_ side of the domain boundary, i.e. whenever normal vectors 62 : * are involved they point _out_ of the computational domain. The 63 : * `volume_tags` list the subset of the `argument_tags` that are _not_ 64 : * evaluated on the boundary but taken from the element directly. 65 : * - They have `apply` and `apply_linearized` member functions that take these 66 : * arguments (in this order): 67 : * 68 : * 1. The dynamic fields as not-null pointers. 69 : * 2. The normal-dot-fluxes corresponding to the dynamic fields as not-null 70 : * pointers. These have the same types as the dynamic fields. 71 : * 3. The field derivatives as const-refs. 72 : * 4. The types held by the argument tags. 73 : * 74 : * For example, boundary conditions for a first-order Poisson system might 75 : * have an `apply` function signature that looks like this: 76 : * 77 : * \snippet Elliptic/BoundaryConditions/Test_BoundaryCondition.cpp example_poisson_fields 78 : * 79 : * The fields and normal-dot-fluxes passed to the `apply` and `apply_linearized` 80 : * functions hold data which the implementations of the functions can use, and 81 : * also serve as return variables. Modifying the fields means applying 82 : * Dirichlet-type boundary conditions and modifying the normal-dot-fluxes means 83 : * applying Neumann-type boundary conditions. Just like the arguments evaluated 84 : * on the boundary, the normal-dot-fluxes involve normal vectors that point 85 : * _out_ of the computation domain. Note that linearized boundary conditions, as 86 : * well as nonlinear boundary conditions for linear systems, may only depend 87 : * linearly on the field data, since these are the fields the linearization is 88 : * performed for. 89 : */ 90 : template <size_t Dim> 91 1 : class BoundaryCondition : public domain::BoundaryConditions::BoundaryCondition { 92 : private: 93 0 : using Base = domain::BoundaryConditions::BoundaryCondition; 94 : 95 : public: 96 0 : static constexpr size_t volume_dim = Dim; 97 : 98 0 : BoundaryCondition() = default; 99 0 : BoundaryCondition(const BoundaryCondition&) = default; 100 0 : BoundaryCondition(BoundaryCondition&&) = default; 101 0 : BoundaryCondition& operator=(const BoundaryCondition&) = default; 102 0 : BoundaryCondition& operator=(BoundaryCondition&&) = default; 103 0 : ~BoundaryCondition() override = default; 104 : 105 : /// \cond 106 : explicit BoundaryCondition(CkMigrateMessage* m) : Base(m) {} 107 : WRAPPED_PUPable_abstract(BoundaryCondition); // NOLINT 108 : /// \endcond 109 : 110 : // The type of boundary condition (Dirichlet or Neumann) for every tensor 111 : // component. For example, if the derived class imposes Neumann-type 112 : // conditions on a Scalar and Dirichlet-type conditions on a 2D vector, then 113 : // it should return `{Dirichlet, Neumann, Neumann}`. 114 : virtual std::vector<elliptic::BoundaryConditionType> 115 0 : boundary_condition_types() const = 0; 116 : }; 117 : 118 : } // namespace BoundaryConditions 119 : } // namespace elliptic