11 #include "DataStructures/Tensor/EagerMath/Magnitude.hpp"
12 #include "DataStructures/Tensor/Slice.hpp"
15 #include "Domain/Structure/IndexToSliceAt.hpp"
17 #include "Elliptic/BoundaryConditions/BoundaryCondition.hpp"
18 #include "Elliptic/BoundaryConditions/BoundaryConditionType.hpp"
19 #include "Elliptic/BoundaryConditions/Tags.hpp"
20 #include "NumericalAlgorithms/DiscontinuousGalerkin/NormalDotFlux.hpp"
23 #include "PointwiseFunctions/AnalyticSolutions/Tags.hpp"
27 #include "Utilities/TaggedTuple.hpp"
28 #include "Utilities/TypeTraits/IsA.hpp"
33 template <
typename System,
size_t Dim,
typename FieldTags,
typename FluxTags,
35 struct AnalyticSolution;
37 namespace Registrars {
38 template <
typename System,
size_t Dim = System::volume_dim,
39 typename FieldTags =
typename System::primal_fields,
40 typename FluxTags =
typename System::primal_fluxes>
41 struct AnalyticSolution {
42 template <
typename Registrars>
43 using f = BoundaryConditions::AnalyticSolution<System, Dim, FieldTags,
44 FluxTags, Registrars>;
48 template <
typename System,
size_t Dim = System::volume_dim,
49 typename FieldTags =
typename System::primal_fields,
50 typename FluxTags =
typename System::primal_fluxes,
52 tmpl::list<BoundaryConditions::Registrars::AnalyticSolution<
53 System, Dim, FieldTags, FluxTags>>>
54 struct AnalyticSolution;
71 template <
typename System,
size_t Dim,
typename... FieldTags,
72 typename... FluxTags,
typename Registrars>
73 class AnalyticSolution<System, Dim, tmpl::list<FieldTags...>,
74 tmpl::list<FluxTags...>, Registrars>
81 tmpl::list<elliptic::OptionTags::BoundaryConditionType<FieldTags>...>;
83 "Boundary conditions from the analytic solution";
85 AnalyticSolution() =
default;
86 AnalyticSolution(
const AnalyticSolution&) noexcept =
default;
87 AnalyticSolution& operator=(
const AnalyticSolution&) noexcept =
default;
88 AnalyticSolution(AnalyticSolution&&) noexcept =
default;
89 AnalyticSolution& operator=(AnalyticSolution&&) noexcept =
default;
90 ~AnalyticSolution() noexcept =
default;
93 explicit AnalyticSolution(CkMigrateMessage* m) noexcept :
Base(m) {}
94 using PUP::able::register_constructor;
103 FieldTags>::type... boundary_condition_types) noexcept
104 : boundary_condition_types_{boundary_condition_types...} {}
107 const noexcept
override {
108 return std::make_unique<AnalyticSolution>(*
this);
111 const auto& boundary_condition_types() const noexcept {
112 return boundary_condition_types_;
115 using argument_tags =
116 tmpl::list<::Tags::AnalyticSolutionsBase, domain::Tags::Mesh<Dim>,
121 tmpl::list<::Tags::AnalyticSolutionsBase, domain::Tags::Mesh<Dim>>;
123 template <
typename OptionalAnalyticSolutions>
126 const OptionalAnalyticSolutions& optional_analytic_solutions,
128 const tnsr::i<DataVector, Dim>& face_normal)
const noexcept {
129 const auto& analytic_solutions = [&optional_analytic_solutions]() noexcept
131 if constexpr (tt::is_a_v<std::optional, OptionalAnalyticSolutions>) {
132 if (not optional_analytic_solutions.has_value()) {
134 "Trying to impose boundary conditions from an analytic solution, "
135 "but no analytic solution is available. You probably selected "
136 "the 'AnalyticSolution' boundary condition but chose to solve a "
137 "problem that has no analytic solution. If this is the case, you "
138 "should probably select a different boundary condition.");
140 return *optional_analytic_solutions;
142 return optional_analytic_solutions;
146 const size_t slice_index =
148 const auto impose_boundary_condition = [
this, &analytic_solutions,
149 &volume_mesh, &direction,
150 &slice_index, &face_normal](
154 const auto n_dot_flux) noexcept {
155 using field_tag = decltype(field_tag_v);
156 using flux_tag = decltype(flux_tag_v);
158 boundary_condition_types())) {
162 volume_mesh.extents(), direction.dimension(), slice_index);
166 n_dot_flux, face_normal,
168 volume_mesh.extents(), direction.dimension(),
172 ERROR(
"Unsupported boundary condition type: "
174 boundary_condition_types()));
178 fields, n_dot_fluxes));
181 using argument_tags_linearized = tmpl::list<>;
182 using volume_tags_linearized = tmpl::list<>;
184 void apply_linearized(
188 const auto impose_boundary_condition = [
this](
191 const auto n_dot_flux) noexcept {
192 using field_tag = decltype(field_tag_v);
194 boundary_condition_types())) {
196 for (
auto& field_component : *field) {
197 field_component = 0.;
201 for (
auto& n_dot_flux_component : *n_dot_flux) {
202 n_dot_flux_component = 0.;
206 ERROR(
"Unsupported boundary condition type: "
208 boundary_condition_types()));
212 impose_boundary_condition(FieldTags{}, fields, n_dot_fluxes));
216 void pup(PUP::er& p) noexcept
override;
219 friend bool operator==(
const AnalyticSolution& lhs,
220 const AnalyticSolution& rhs) noexcept {
221 return lhs.boundary_condition_types_ == rhs.boundary_condition_types_;
224 friend bool operator!=(
const AnalyticSolution& lhs,
225 const AnalyticSolution& rhs) noexcept {
226 return not(lhs == rhs);
230 boundary_condition_types_{};
233 template <
typename System,
size_t Dim,
typename... FieldTags,
234 typename... FluxTags,
typename Registrars>
235 void AnalyticSolution<System, Dim, tmpl::list<FieldTags...>,
236 tmpl::list<FluxTags...>,
237 Registrars>::pup(PUP::er& p) noexcept {
239 p | boundary_condition_types_;
243 template <
typename System,
size_t Dim,
typename... FieldTags,
244 typename... FluxTags,
typename Registrars>
245 PUP::able::PUP_ID AnalyticSolution<System, Dim, tmpl::list<FieldTags...>,
246 tmpl::list<FluxTags...>,
247 Registrars>::my_PUP_ID = 0;