Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <boost/functional/hash.hpp>
8 : #include <cstddef>
9 : #include <optional>
10 : #include <tuple>
11 : #include <unordered_map>
12 : #include <utility>
13 : #include <vector>
14 :
15 : #include "DataStructures/DataBox/DataBox.hpp"
16 : #include "DataStructures/DataBox/DataBoxTag.hpp"
17 : #include "DataStructures/DataBox/Prefixes.hpp"
18 : #include "DataStructures/Variables.hpp"
19 : #include "Domain/Amr/Info.hpp"
20 : #include "Domain/Amr/Tags/NeighborFlags.hpp"
21 : #include "Domain/Creators/Tags/InitialExtents.hpp"
22 : #include "Domain/Structure/Direction.hpp"
23 : #include "Domain/Structure/Element.hpp"
24 : #include "Domain/Structure/Neighbors.hpp"
25 : #include "Domain/Structure/OrientationMap.hpp"
26 : #include "Domain/Tags.hpp"
27 : #include "Evolution/DiscontinuousGalerkin/Initialization/QuadratureTag.hpp"
28 : #include "Evolution/DiscontinuousGalerkin/MortarData.hpp"
29 : #include "Evolution/DiscontinuousGalerkin/MortarTags.hpp"
30 : #include "Evolution/DiscontinuousGalerkin/NormalVectorTags.hpp"
31 : #include "NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp"
32 : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
33 : #include "Parallel/AlgorithmExecution.hpp"
34 : #include "ParallelAlgorithms/Amr/Protocols/Projector.hpp"
35 : #include "ParallelAlgorithms/Initialization/MutateAssign.hpp"
36 : #include "Time/TimeStepId.hpp"
37 : #include "Utilities/Gsl.hpp"
38 : #include "Utilities/TMPL.hpp"
39 :
40 : /// \cond
41 : namespace Parallel {
42 : template <typename Metavariables>
43 : class GlobalCache;
44 : } // namespace Parallel
45 : namespace Spectral {
46 : enum class ChildSize;
47 : using MortarSize = ChildSize;
48 : enum class Quadrature;
49 : } // namespace Spectral
50 : namespace Tags {
51 : struct TimeStepId;
52 : } // namespace Tags
53 : namespace tuples {
54 : template <class... Tags>
55 : class TaggedTuple;
56 : } // namespace tuples
57 : /// \endcond
58 :
59 1 : namespace evolution::dg::Initialization {
60 : namespace detail {
61 : template <size_t Dim>
62 : std::tuple<
63 : std::unordered_map<DirectionalId<Dim>, evolution::dg::MortarData<Dim>,
64 : boost::hash<DirectionalId<Dim>>>,
65 : std::unordered_map<DirectionalId<Dim>, Mesh<Dim - 1>,
66 : boost::hash<DirectionalId<Dim>>>,
67 : std::unordered_map<DirectionalId<Dim>,
68 : std::array<Spectral::MortarSize, Dim - 1>,
69 : boost::hash<DirectionalId<Dim>>>,
70 : std::unordered_map<DirectionalId<Dim>, TimeStepId,
71 : boost::hash<DirectionalId<Dim>>>,
72 : DirectionMap<Dim, std::optional<Variables<tmpl::list<
73 : evolution::dg::Tags::MagnitudeOfNormal,
74 : evolution::dg::Tags::NormalCovector<Dim>>>>>>
75 : mortars_apply_impl(const std::vector<std::array<size_t, Dim>>& initial_extents,
76 : Spectral::Quadrature quadrature, const Element<Dim>& element,
77 : const TimeStepId& next_temporal_id,
78 : const Mesh<Dim>& volume_mesh);
79 : } // namespace detail
80 :
81 : /*!
82 : * \brief Initialize mortars between elements for exchanging boundary correction
83 : * terms.
84 : *
85 : * Uses:
86 : * - DataBox:
87 : * - `Tags::Element<Dim>`
88 : * - `Tags::Mesh<Dim>`
89 : * - `BoundaryScheme::receive_temporal_id`
90 : *
91 : * DataBox changes:
92 : * - Adds:
93 : * - `Tags::MortarData<Dim>`
94 : * - `Tags::MortarMesh<Dim>`
95 : * - `Tags::MortarSize<Dim>`
96 : * - `Tags::MortarNextTemporalId<Dim>`
97 : * - `evolution::dg::Tags::NormalCovectorAndMagnitude<Dim>`
98 : * - Removes: nothing
99 : * - Modifies: nothing
100 : */
101 : template <size_t Dim, typename System>
102 1 : struct Mortars {
103 0 : using Key = DirectionalId<Dim>;
104 :
105 : template <typename MappedType>
106 0 : using MortarMap = std::unordered_map<Key, MappedType, boost::hash<Key>>;
107 :
108 : public:
109 0 : using simple_tags_from_options =
110 : tmpl::list<::domain::Tags::InitialExtents<Dim>,
111 : evolution::dg::Tags::Quadrature>;
112 :
113 0 : using simple_tags = tmpl::list<
114 : Tags::MortarData<Dim>, Tags::MortarMesh<Dim>, Tags::MortarSize<Dim>,
115 : Tags::MortarNextTemporalId<Dim>,
116 : evolution::dg::Tags::NormalCovectorAndMagnitude<Dim>,
117 : Tags::MortarDataHistory<
118 : Dim, typename db::add_tag_prefix<
119 : ::Tags::dt, typename System::variables_tag>::type>>;
120 0 : using compute_tags = tmpl::list<>;
121 :
122 : template <typename DbTagsList, typename... InboxTags, typename Metavariables,
123 : typename ArrayIndex, typename ActionList,
124 : typename ParallelComponent>
125 0 : static Parallel::iterable_action_return_t apply(
126 : db::DataBox<DbTagsList>& box,
127 : const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
128 : const Parallel::GlobalCache<Metavariables>& /*cache*/,
129 : const ArrayIndex& /*array_index*/, ActionList /*meta*/,
130 : const ParallelComponent* const /*meta*/) {
131 : auto [mortar_data, mortar_meshes, mortar_sizes, mortar_next_temporal_ids,
132 : normal_covector_quantities] =
133 : detail::mortars_apply_impl(
134 : db::get<::domain::Tags::InitialExtents<Dim>>(box),
135 : db::get<evolution::dg::Tags::Quadrature>(box),
136 : db::get<::domain::Tags::Element<Dim>>(box),
137 : db::get<::Tags::Next<::Tags::TimeStepId>>(box),
138 : db::get<::domain::Tags::Mesh<Dim>>(box));
139 : typename Tags::MortarDataHistory<
140 : Dim, typename db::add_tag_prefix<
141 : ::Tags::dt, typename System::variables_tag>::type>::type
142 : boundary_data_history{};
143 : if (Metavariables::local_time_stepping) {
144 : for (const auto& mortar_id_and_data : mortar_data) {
145 : // default initialize data
146 : boundary_data_history[mortar_id_and_data.first];
147 : }
148 : }
149 : ::Initialization::mutate_assign<simple_tags>(
150 : make_not_null(&box), std::move(mortar_data), std::move(mortar_meshes),
151 : std::move(mortar_sizes), std::move(mortar_next_temporal_ids),
152 : std::move(normal_covector_quantities),
153 : std::move(boundary_data_history));
154 : return {Parallel::AlgorithmExecution::Continue, std::nullopt};
155 : }
156 : };
157 :
158 : /// \brief Initialize/update items related to mortars after an AMR change
159 : ///
160 : /// Mutates:
161 : /// - Tags::MortarData<dim>
162 : /// - Tags::MortarMesh<dim>
163 : /// - Tags::MortarSize<dim>
164 : /// - Tags::MortarNextTemporalId<dim>
165 : /// - evolution::dg::Tags::NormalCovectorAndMagnitude<dim>
166 : /// - Tags::MortarDataHistory<dim, typename dt_variables_tag::type>>
167 : ///
168 : /// For p-refinement:
169 : /// - Does nothing to MortarDataHistory (only valid for global time-stepping)
170 : /// or MortarNextTemporalId (only valid for no h-refinement)
171 : /// - Sets the other Mortar tags to be default initialized for each neighbor
172 : /// - Sets the NormalCovectorAndMagnitude to std::nullopt
173 : template <typename Metavariables>
174 1 : struct ProjectMortars : tt::ConformsTo<amr::protocols::Projector> {
175 0 : static constexpr size_t dim = Metavariables::volume_dim;
176 0 : using dt_variables_tag = typename db::add_tag_prefix<
177 : ::Tags::dt, typename Metavariables::system::variables_tag>;
178 0 : using mortar_data_history_type =
179 : typename Tags::MortarDataHistory<dim,
180 : typename dt_variables_tag::type>::type;
181 :
182 0 : using return_tags =
183 : tmpl::list<Tags::MortarData<dim>, Tags::MortarMesh<dim>,
184 : Tags::MortarSize<dim>, Tags::MortarNextTemporalId<dim>,
185 : evolution::dg::Tags::NormalCovectorAndMagnitude<dim>,
186 : Tags::MortarDataHistory<dim, typename dt_variables_tag::type>>;
187 0 : using argument_tags =
188 : tmpl::list<domain::Tags::Mesh<dim>, domain::Tags::Element<dim>,
189 : amr::Tags::NeighborInfo<dim>>;
190 :
191 0 : static void apply(
192 : const gsl::not_null<::dg::MortarMap<dim, evolution::dg::MortarData<dim>>*>
193 : mortar_data,
194 : const gsl::not_null<::dg::MortarMap<dim, Mesh<dim - 1>>*> mortar_mesh,
195 : const gsl::not_null<
196 : ::dg::MortarMap<dim, std::array<Spectral::MortarSize, dim - 1>>*>
197 : mortar_size,
198 : const gsl::not_null<
199 : ::dg::MortarMap<dim, TimeStepId>*> /*mortar_next_temporal_id*/,
200 : const gsl::not_null<
201 : DirectionMap<dim, std::optional<Variables<tmpl::list<
202 : evolution::dg::Tags::MagnitudeOfNormal,
203 : evolution::dg::Tags::NormalCovector<dim>>>>>*>
204 : normal_covector_and_magnitude,
205 : const gsl::not_null<mortar_data_history_type*>
206 : /*mortar_data_history*/,
207 : const Mesh<dim>& new_mesh, const Element<dim>& new_element,
208 : const std::unordered_map<ElementId<dim>, amr::Info<dim>>& neighbor_info,
209 : const std::pair<Mesh<dim>, Element<dim>>& /*old_mesh_and_element*/) {
210 : if (Metavariables::local_time_stepping) {
211 : ERROR("AMR with local time-stepping is not yet supported");
212 : }
213 :
214 : mortar_data->clear();
215 : mortar_mesh->clear();
216 : mortar_size->clear();
217 : // mortar_next_temporal_id is not changed, but this will break when
218 : // h-refinement is enabled and the neighbors are no longer the same
219 : for (const auto& [direction, neighbors] : new_element.neighbors()) {
220 : (*normal_covector_and_magnitude)[direction] = std::nullopt;
221 : for (const auto& neighbor : neighbors) {
222 : const DirectionalId<dim> mortar_id{direction, neighbor};
223 : mortar_data->emplace(mortar_id, MortarData<dim>{1});
224 : const auto new_neighbor_mesh = neighbors.orientation().inverse_map()(
225 : neighbor_info.at(neighbor).new_mesh);
226 : mortar_mesh->emplace(
227 : mortar_id,
228 : ::dg::mortar_mesh(
229 : new_mesh.slice_away(direction.dimension()),
230 : new_neighbor_mesh.slice_away(direction.dimension())));
231 : mortar_size->emplace(
232 : mortar_id,
233 : ::dg::mortar_size(new_element.id(), neighbor, direction.dimension(),
234 : neighbors.orientation()));
235 : }
236 : }
237 : for (const auto& direction : new_element.external_boundaries()) {
238 : (*normal_covector_and_magnitude)[direction] = std::nullopt;
239 : }
240 : }
241 :
242 : template <typename... Tags>
243 0 : static void apply(
244 : const gsl::not_null<::dg::MortarMap<dim, evolution::dg::MortarData<dim>>*>
245 : /*mortar_data*/,
246 : const gsl::not_null<::dg::MortarMap<dim, Mesh<dim - 1>>*> /*mortar_mesh*/,
247 : const gsl::not_null<
248 : ::dg::MortarMap<dim, std::array<Spectral::MortarSize, dim - 1>>*>
249 : /*mortar_size*/,
250 : const gsl::not_null<
251 : ::dg::MortarMap<dim, TimeStepId>*> /*mortar_next_temporal_id*/,
252 : const gsl::not_null<
253 : DirectionMap<dim, std::optional<Variables<tmpl::list<
254 : evolution::dg::Tags::MagnitudeOfNormal,
255 : evolution::dg::Tags::NormalCovector<dim>>>>>*>
256 : /*normal_covector_and_magnitude*/,
257 : const gsl::not_null<mortar_data_history_type*>
258 : /*mortar_data_history*/,
259 : const Mesh<dim>& /*new_mesh*/, const Element<dim>& /*new_element*/,
260 : const std::unordered_map<ElementId<dim>,
261 : amr::Info<dim>>& /*neighbor_info*/,
262 : const tuples::TaggedTuple<Tags...>& /*parent_items*/) {
263 : ERROR("h-refinement not implemented yet");
264 : }
265 :
266 : template <typename... Tags>
267 0 : static void apply(
268 : const gsl::not_null<::dg::MortarMap<dim, evolution::dg::MortarData<dim>>*>
269 : /*mortar_data*/,
270 : const gsl::not_null<::dg::MortarMap<dim, Mesh<dim - 1>>*> /*mortar_mesh*/,
271 : const gsl::not_null<
272 : ::dg::MortarMap<dim, std::array<Spectral::MortarSize, dim - 1>>*>
273 : /*mortar_size*/,
274 : const gsl::not_null<
275 : ::dg::MortarMap<dim, TimeStepId>*> /*mortar_next_temporal_id*/,
276 : const gsl::not_null<
277 : DirectionMap<dim, std::optional<Variables<tmpl::list<
278 : evolution::dg::Tags::MagnitudeOfNormal,
279 : evolution::dg::Tags::NormalCovector<dim>>>>>*>
280 : /*normal_covector_and_magnitude*/,
281 : const gsl::not_null<mortar_data_history_type*>
282 : /*mortar_data_history*/,
283 : const Mesh<dim>& /*new_mesh*/, const Element<dim>& /*new_element*/,
284 : const std::unordered_map<ElementId<dim>,
285 : amr::Info<dim>>& /*neighbor_info*/,
286 : const std::unordered_map<ElementId<dim>, tuples::TaggedTuple<Tags...>>&
287 : /*children_items*/) {
288 : ERROR("h-refinement not implemented yet");
289 : }
290 : };
291 : } // namespace evolution::dg::Initialization
|