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 <utility>
8 :
9 : #include "DataStructures/DataBox/DataBox.hpp"
10 : #include "DataStructures/Variables.hpp"
11 : #include "Domain/BoundaryVariables.hpp"
12 : #include "Domain/BoundaryVariablesTag.hpp"
13 : #include "Domain/Creators/Tags/ExternalBoundaryConditions.hpp"
14 : #include "Domain/Structure/Direction.hpp"
15 : #include "Domain/Structure/DirectionMap.hpp"
16 : #include "Domain/Structure/Element.hpp"
17 : #include "Domain/Tags.hpp"
18 : #include "Evolution/DiscontinuousGalerkin/BoundaryEvolvedVariables.hpp"
19 : #include "NumericalAlgorithms/DiscontinuousGalerkin/ProjectToBoundary.hpp"
20 : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
21 : #include "Parallel/AlgorithmExecution.hpp"
22 : #include "Time/LtsMode.hpp"
23 : #include "Time/Tags/LtsMode.hpp"
24 : #include "Utilities/CallWithDynamicType.hpp"
25 : #include "Utilities/ErrorHandling/Error.hpp"
26 : #include "Utilities/Gsl.hpp"
27 : #include "Utilities/TMPL.hpp"
28 :
29 : /// \cond
30 : namespace Parallel {
31 : template <typename Metavariables>
32 : class GlobalCache;
33 : } // namespace Parallel
34 : namespace tuples {
35 : template <class... Tags>
36 : class TaggedTuple;
37 : } // namespace tuples
38 : /// \endcond
39 :
40 1 : namespace evolution::dg::Initialization {
41 : /// \ingroup ActionsGroup
42 : /// \ingroup DiscontinuousGalerkinGroup
43 : /// \brief Allocates and initializes the system's boundary-evolved variables
44 : /// (the `::Tags::BoundaryVariables` entry of the list-valued
45 : /// `System::variables_tag`) on each opting external face.
46 : ///
47 : /// Iterates the element's external boundaries and gives each face whose
48 : /// boundary condition opts in (declares the `evolves_boundary_variables`
49 : /// marker) a face-sized entry in the `BoundaryVariables` storage. Each
50 : /// `Tags::BoundaryValue<Source>` is initialized by projecting its interior
51 : /// `Source` from the volume variables to the face. Interior and non-opting
52 : /// faces get no entry.
53 : ///
54 : /// Runs after the domain and the initial data are set, and before
55 : /// `Initialization::TimeStepperHistory`, which sizes the `::Tags::dt` twin of
56 : /// the storage from the per-face storage initialized here.
57 : ///
58 : /// \tparam Dim the spatial dimension
59 : /// \tparam System the evolution system (supplies `variables_tag`)
60 : /// \tparam DerivedBoundaryConditionsList the concrete boundary condition
61 : /// types; it must contain every type that can appear on an external boundary
62 : template <size_t Dim, typename System, typename DerivedBoundaryConditionsList>
63 1 : struct BoundaryEvolvedVariables {
64 : private:
65 : static_assert(
66 : evolution::dg::system_has_boundary_variables_v<System>,
67 : "Boundary-evolved variables can only be initialized for a system whose "
68 : "variables_tag is a tmpl::list with a ::Tags::BoundaryVariables entry "
69 : "holding the boundary-evolved variables.");
70 0 : using boundary_variables_tag = evolution::dg::boundary_variables_tag<System>;
71 0 : using boundary_field_tags_list = typename boundary_variables_tag::tags_list;
72 0 : using volume_variables_tag = tmpl::front<typename System::variables_tag>;
73 :
74 : public:
75 0 : using const_global_cache_tags =
76 : tmpl::list<domain::Tags::ExternalBoundaryConditions<Dim>>;
77 0 : using simple_tags_from_options = tmpl::list<>;
78 0 : using simple_tags = tmpl::list<boundary_variables_tag>;
79 0 : using compute_tags = tmpl::list<>;
80 :
81 : template <typename DbTagsList, typename... InboxTags, typename Metavariables,
82 : typename ArrayIndex, typename ActionList,
83 : typename ParallelComponent>
84 0 : static Parallel::iterable_action_return_t apply(
85 : db::DataBox<DbTagsList>& box,
86 : const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
87 : const Parallel::GlobalCache<Metavariables>& /*cache*/,
88 : const ArrayIndex& /*array_index*/, ActionList /*meta*/,
89 : const ParallelComponent* const /*meta*/) {
90 : if (db::get<::Tags::LtsMode>(box) != LtsMode::Off) {
91 : ERROR(
92 : "Boundary-evolved variables are unverified with local time "
93 : "stepping.");
94 : }
95 : const auto& element = db::get<::domain::Tags::Element<Dim>>(box);
96 : const auto& mesh = db::get<::domain::Tags::Mesh<Dim>>(box);
97 : if (db::get<volume_variables_tag>(box).number_of_grid_points() !=
98 : mesh.number_of_grid_points()) {
99 : ERROR("The volume variables are not allocated to the mesh size ("
100 : << db::get<volume_variables_tag>(box).number_of_grid_points()
101 : << " variables grid points vs " << mesh.number_of_grid_points()
102 : << " mesh grid points). This action projects the volume "
103 : "variables onto the opting external faces, so it must run "
104 : "after the volume variables are allocated and set from the "
105 : "initial data.");
106 : }
107 : const auto& external_boundary_conditions =
108 : db::get<domain::Tags::ExternalBoundaryConditions<Dim>>(box).at(
109 : element.id().block_id());
110 :
111 : DirectionMap<Dim, size_t> points_per_direction{};
112 : for (const Direction<Dim>& direction : element.external_boundaries()) {
113 : call_with_dynamic_type<void, DerivedBoundaryConditionsList>(
114 : &*external_boundary_conditions.at(direction),
115 : [&direction, &mesh,
116 : &points_per_direction]<typename DerivedBoundaryCondition>(
117 : const DerivedBoundaryCondition* const /*boundary_condition*/) {
118 : if constexpr (evolution::dg::evolves_boundary_variables_v<
119 : DerivedBoundaryCondition>) {
120 : points_per_direction.insert(
121 : {direction, mesh.slice_away(direction.dimension())
122 : .number_of_grid_points()});
123 : }
124 : });
125 : }
126 :
127 : db::mutate<boundary_variables_tag>(
128 : [&mesh, &points_per_direction](
129 : const gsl::not_null<typename boundary_variables_tag::type*>
130 : boundary_vars,
131 : const typename volume_variables_tag::type& volume_variables) {
132 : boundary_vars->initialize(std::move(points_per_direction));
133 : for (auto& direction_and_face_values : boundary_vars->variables()) {
134 : const auto& direction = direction_and_face_values.first;
135 : auto& face_values = direction_and_face_values.second;
136 : tmpl::for_each<boundary_field_tags_list>(
137 : [&direction, &mesh, &volume_variables,
138 : &face_values]<typename BoundaryTag>(
139 : tmpl::type_<BoundaryTag> /*meta*/) {
140 : using source_tag = typename BoundaryTag::tag;
141 : auto& face_field = get<BoundaryTag>(face_values);
142 : ::dg::project_tensor_to_boundary(
143 : make_not_null(&face_field),
144 : get<source_tag>(volume_variables), mesh, direction);
145 : });
146 : }
147 : },
148 : make_not_null(&box), db::get<volume_variables_tag>(box));
149 : return {Parallel::AlgorithmExecution::Continue, std::nullopt};
150 : }
151 : };
152 : } // namespace evolution::dg::Initialization
|