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 <cstddef>
8 : #include <limits>
9 : #include <unordered_map>
10 : #include <utility>
11 :
12 : #include "DataStructures/DataBox/DataBox.hpp"
13 : #include "DataStructures/TaggedTuple.hpp"
14 : #include "Domain/Amr/Flag.hpp"
15 : #include "Domain/Amr/NeighborsOfChild.hpp"
16 : #include "Domain/Amr/Tags/Flags.hpp"
17 : #include "Domain/Amr/Tags/NeighborFlags.hpp"
18 : #include "Domain/Structure/DirectionMap.hpp"
19 : #include "Domain/Structure/DirectionalIdMap.hpp"
20 : #include "Domain/Structure/Element.hpp"
21 : #include "Domain/Structure/ElementId.hpp"
22 : #include "Domain/Structure/IsValidDgMesh.hpp"
23 : #include "Domain/Structure/Neighbors.hpp"
24 : #include "Domain/Structure/Topology.hpp"
25 : #include "Domain/Tags.hpp"
26 : #include "Domain/Tags/NeighborMesh.hpp"
27 : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
28 : #include "Parallel/ElementRegistration.hpp"
29 : #include "ParallelAlgorithms/Amr/Projectors/Mesh.hpp"
30 : #include "ParallelAlgorithms/Amr/Tags.hpp"
31 : #include "ParallelAlgorithms/Initialization/MutateAssign.hpp"
32 : #include "Utilities/ErrorHandling/Error.hpp"
33 : #include "Utilities/Gsl.hpp"
34 : #include "Utilities/TMPL.hpp"
35 :
36 : /// \cond
37 : namespace Parallel {
38 : template <typename Metavariables>
39 : class GlobalCache;
40 : } // namespace Parallel
41 : /// \endcond
42 :
43 : namespace amr::Actions {
44 : /// \brief Initializes the data of a newly created child element from the data
45 : /// of its parent element
46 : ///
47 : /// DataBox:
48 : /// - Modifies:
49 : /// * domain::Tags::Element<volume_dim>
50 : /// * domain::Tags::Mesh<volume_dim>
51 : /// * all return_tags of Metavariables::amr::projectors
52 : ///
53 : /// \details This action is meant to be invoked by
54 : /// amr::Actions::SendDataToChildren
55 1 : struct InitializeChild {
56 : template <typename ParallelComponent, typename DbTagList,
57 : typename Metavariables, typename... Tags>
58 0 : static void apply(db::DataBox<DbTagList>& box,
59 : Parallel::GlobalCache<Metavariables>& cache,
60 : const ElementId<Metavariables::volume_dim>& child_id,
61 : const tuples::TaggedTuple<Tags...>& parent_items) {
62 : constexpr size_t volume_dim = Metavariables::volume_dim;
63 : const auto& parent =
64 : tuples::get<::domain::Tags::Element<volume_dim>>(parent_items);
65 : const auto& parent_info =
66 : tuples::get<amr::Tags::Info<volume_dim>>(parent_items);
67 : const auto& parent_neighbor_info =
68 : tuples::get<amr::Tags::NeighborInfo<volume_dim>>(parent_items);
69 : const auto& parent_mesh =
70 : tuples::get<::domain::Tags::Mesh<volume_dim>>(parent_items);
71 : auto neighbors = amr::neighbors_of_child(parent, parent_info,
72 : parent_neighbor_info, child_id);
73 : auto child_topologies = parent.topologies();
74 : if constexpr (volume_dim == 2) {
75 : if (parent_mesh.basis(0) == Spectral::Basis::ZernikeB2 and
76 : child_id.segment_id(0).index() == 1) {
77 : child_topologies = domain::topologies::annulus;
78 : }
79 : } else if constexpr (volume_dim == 3) {
80 : if (child_id.segment_id(0).index() == 1) {
81 : if (parent_mesh.basis(0) == Spectral::Basis::ZernikeB1) {
82 : child_topologies[0] = domain::Topology::I1;
83 : } else if (parent_mesh.basis(0) == Spectral::Basis::ZernikeB2) {
84 : child_topologies = domain::topologies::cylindrical_shell;
85 : } else if (parent_mesh.basis(0) == Spectral::Basis::ZernikeB3) {
86 : child_topologies = domain::topologies::spherical_shell;
87 : }
88 : }
89 : }
90 : Element<volume_dim> child(child_id, std::move(neighbors.first),
91 : child_topologies);
92 : Mesh<volume_dim> child_mesh = amr::projectors::child_mesh(
93 : parent_mesh, child_id, parent_info.flags, parent.topologies());
94 : if (not domain::is_valid_dg_mesh(child_mesh, child)) {
95 : ERROR("Invalid mesh " << child_mesh << " for Element " << child);
96 : }
97 :
98 : // Default initialization of amr::Tags::Info and amr::Tags::NeighborInfo
99 : // is okay
100 : ::Initialization::mutate_assign<tmpl::list<
101 : ::domain::Tags::Element<volume_dim>, ::domain::Tags::Mesh<volume_dim>,
102 : ::domain::Tags::NeighborMesh<volume_dim>>>(
103 : make_not_null(&box), std::move(child), std::move(child_mesh),
104 : std::move(neighbors.second));
105 :
106 : if constexpr (Metavariables::amr::keep_coarse_grids) {
107 : if (db::get<amr::Tags::MaxCoarseLevels>(box).value_or(
108 : std::numeric_limits<size_t>::max()) > 0) {
109 : ::Initialization::mutate_assign<
110 : tmpl::list<amr::Tags::ParentId<volume_dim>,
111 : amr::Tags::ParentMesh<volume_dim>>>(
112 : make_not_null(&box), parent.id(), parent_mesh);
113 : }
114 : }
115 :
116 : tmpl::for_each<typename Metavariables::amr::projectors>(
117 : [&box, &parent_items](auto projector_v) {
118 : using projector = typename decltype(projector_v)::type;
119 : try {
120 : db::mutate_apply<projector>(make_not_null(&box), parent_items);
121 : } catch (std::exception& e) {
122 : ERROR("Error in AMR projector '"
123 : << pretty_type::get_name<projector>() << "':\n"
124 : << e.what());
125 : }
126 : });
127 :
128 : Parallel::register_element<ParallelComponent>(box, cache, child_id);
129 : }
130 : };
131 : } // namespace amr::Actions
|