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
|