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 <tuple>
9 : #include <unordered_map>
10 : #include <unordered_set>
11 : #include <vector>
12 :
13 : #include "DataStructures/DataBox/DataBox.hpp"
14 : #include "DataStructures/TaggedTuple.hpp"
15 : #include "Domain/Amr/NeighborsOfParent.hpp"
16 : #include "Domain/Amr/Tags/Flags.hpp"
17 : #include "Domain/Amr/Tags/NeighborFlags.hpp"
18 : #include "Domain/Structure/Direction.hpp"
19 : #include "Domain/Structure/DirectionMap.hpp"
20 : #include "Domain/Structure/DirectionalIdMap.hpp"
21 : #include "Domain/Structure/Element.hpp"
22 : #include "Domain/Structure/ElementId.hpp"
23 : #include "Domain/Structure/IsValidDgMesh.hpp"
24 : #include "Domain/Structure/Neighbors.hpp"
25 : #include "Domain/Structure/Topology.hpp"
26 : #include "Domain/Tags.hpp"
27 : #include "Domain/Tags/NeighborMesh.hpp"
28 : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
29 : #include "Parallel/ElementRegistration.hpp"
30 : #include "ParallelAlgorithms/Amr/Projectors/Mesh.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 parent element from the data
45 : /// of its children elements
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::CollectDataFromChildren
55 1 : struct InitializeParent {
56 : template <typename ParallelComponent, typename DbTagList,
57 : typename Metavariables>
58 0 : static void apply(
59 : db::DataBox<DbTagList>& box, Parallel::GlobalCache<Metavariables>& cache,
60 : const ElementId<Metavariables::volume_dim>& parent_id,
61 : std::unordered_map<
62 : ElementId<Metavariables::volume_dim>,
63 : tuples::tagged_tuple_from_typelist<
64 : typename db::DataBox<DbTagList>::mutable_item_creation_tags>>
65 : children_items) {
66 : constexpr size_t volume_dim = Metavariables::volume_dim;
67 : std::vector<std::tuple<
68 : const Element<volume_dim>&,
69 : const std::unordered_map<ElementId<volume_dim>, Info<volume_dim>>&>>
70 : children_elements_and_neighbor_info;
71 : for (const auto& [_, child_items] : children_items) {
72 : children_elements_and_neighbor_info.emplace_back(std::forward_as_tuple(
73 : tuples::get<::domain::Tags::Element<volume_dim>>(child_items),
74 : tuples::get<amr::Tags::NeighborInfo<volume_dim>>(child_items)));
75 : }
76 : auto parent_neighbors = amr::neighbors_of_parent(
77 : parent_id, children_elements_and_neighbor_info);
78 :
79 : std::vector<Mesh<volume_dim>> projected_children_meshes{};
80 : projected_children_meshes.reserve(children_items.size());
81 : auto parent_topologies =
82 : make_array<volume_dim>(domain::Topology::Uninitialized);
83 : bool parent_has_bn_topology = false;
84 : for (const auto& [child_id, child_items] : children_items) {
85 : const auto& child =
86 : tuples::get<::domain::Tags::Element<volume_dim>>(child_items);
87 : const auto& child_mesh =
88 : tuples::get<::domain::Tags::Mesh<volume_dim>>(child_items);
89 : const auto& child_flags =
90 : tuples::get<amr::Tags::Info<volume_dim>>(child_items).flags;
91 : const auto& child_topologies = child.topologies();
92 : projected_children_meshes.emplace_back(amr::projectors::p_refined_mesh(
93 : child_mesh, child_flags, child_topologies));
94 : if (not parent_has_bn_topology and
95 : child_topologies != parent_topologies) {
96 : const domain::Topology first_topology = child_topologies[0];
97 : const bool child_has_bn_topology =
98 : first_topology == domain::Topology::B1Radial or
99 : first_topology == domain::Topology::B2Radial or
100 : first_topology == domain::Topology::B3Radial;
101 : if (child_has_bn_topology or
102 : parent_topologies ==
103 : make_array<volume_dim>(domain::Topology::Uninitialized)) {
104 : parent_topologies = child_topologies;
105 : parent_has_bn_topology = child_has_bn_topology;
106 : } else {
107 : ERROR("Expect all topologies to be the same, not "
108 : << parent_topologies << " and " << child_topologies);
109 : }
110 : }
111 : }
112 : Element<volume_dim> parent(parent_id, std::move(parent_neighbors.first),
113 : parent_topologies);
114 : Mesh<volume_dim> parent_mesh =
115 : amr::projectors::parent_mesh(projected_children_meshes);
116 : if (not domain::is_valid_dg_mesh(parent_mesh, parent)) {
117 : ERROR("Invalid mesh " << parent_mesh << " for Element " << parent);
118 : }
119 :
120 : // Default initialization of amr::Tags::Info and amr::Tags::NeighborInfo
121 : // is okay
122 : ::Initialization::mutate_assign<tmpl::list<
123 : ::domain::Tags::Element<volume_dim>, ::domain::Tags::Mesh<volume_dim>,
124 : ::domain::Tags::NeighborMesh<volume_dim>>>(
125 : make_not_null(&box), std::move(parent), std::move(parent_mesh),
126 : std::move(parent_neighbors.second));
127 :
128 : tmpl::for_each<typename Metavariables::amr::projectors>(
129 : [&box, &children_items](auto projector_v) {
130 : using projector = typename decltype(projector_v)::type;
131 : try {
132 : db::mutate_apply<projector>(make_not_null(&box), children_items);
133 : } catch (std::exception& e) {
134 : ERROR("Error in AMR projector '"
135 : << pretty_type::get_name<projector>() << "':\n"
136 : << e.what());
137 : }
138 : });
139 :
140 : Parallel::register_element<ParallelComponent>(box, cache, parent_id);
141 : }
142 : };
143 : } // namespace amr::Actions
|