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 <unordered_map>
9 : #include <utility>
10 :
11 : #include "DataStructures/DataVector.hpp"
12 : #include "DataStructures/TaggedTuple.hpp"
13 : #include "DataStructures/Variables.hpp"
14 : #include "Domain/Structure/ChildSize.hpp"
15 : #include "Domain/Structure/Element.hpp"
16 : #include "Domain/Structure/ElementId.hpp"
17 : #include "Domain/Tags.hpp"
18 : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
19 : #include "NumericalAlgorithms/Spectral/Projection.hpp"
20 : #include "NumericalAlgorithms/Spectral/SegmentSize.hpp"
21 : #include "ParallelAlgorithms/Amr/Protocols/Projector.hpp"
22 : #include "Utilities/Gsl.hpp"
23 : #include "Utilities/MakeArray.hpp"
24 : #include "Utilities/TMPL.hpp"
25 :
26 : namespace amr::projectors {
27 :
28 : /// \brief Update the Tensors corresponding to TensorTags after an AMR
29 : /// change
30 : ///
31 : /// There is a specialization for
32 : /// `ProjectTensors<tmpl::list<TensorTags...>>` that can be used if a
33 : /// `tmpl::list` is available.
34 : ///
35 : /// \details For each item corresponding to each tag in TensorTags, project
36 : /// the data for each tensor from the old mesh to the new mesh
37 : ///
38 : /// \see ProjectVariables
39 : template <size_t Dim, typename... TensorTags>
40 1 : struct ProjectTensors : tt::ConformsTo<amr::protocols::Projector> {
41 0 : using return_tags = tmpl::list<TensorTags...>;
42 0 : using argument_tags =
43 : tmpl::list<domain::Tags::Element<Dim>, domain::Tags::Mesh<Dim>>;
44 :
45 0 : static void apply(
46 : const gsl::not_null<typename TensorTags::type*>... tensors,
47 : const Element<Dim>& /*element*/, const Mesh<Dim>& new_mesh,
48 : const std::pair<Mesh<Dim>, Element<Dim>>& old_mesh_and_element) {
49 : const auto& old_mesh = old_mesh_and_element.first;
50 : if (old_mesh == new_mesh) {
51 : return; // mesh was not refined, so no projection needed
52 : }
53 : const auto project_tensor = [&old_mesh, &new_mesh](auto& tensor) {
54 : for (size_t i = 0; i < tensor.size(); ++i) {
55 : tensor[i] =
56 : Spectral::project(tensor[i], old_mesh, new_mesh,
57 : make_array<Dim>(Spectral::SegmentSize::Full),
58 : make_array<Dim>(Spectral::SegmentSize::Full));
59 : }
60 : };
61 : EXPAND_PACK_LEFT_TO_RIGHT(project_tensor(*tensors));
62 : }
63 :
64 : template <typename... Tags>
65 0 : static void apply(const gsl::not_null<typename TensorTags::type*>... tensors,
66 : const Element<Dim>& element, const Mesh<Dim>& new_mesh,
67 : const tuples::TaggedTuple<Tags...>& parent_items) {
68 : const auto& element_id = element.id();
69 : const auto& parent_id = get<domain::Tags::Element<Dim>>(parent_items).id();
70 : const auto& parent_mesh = get<domain::Tags::Mesh<Dim>>(parent_items);
71 : const auto child_sizes =
72 : domain::child_size(element_id.segment_ids(), parent_id.segment_ids());
73 : const auto project_tensor = [&](auto& new_tensor, const auto& old_tensor) {
74 : for (size_t i = 0; i < new_tensor.size(); ++i) {
75 : Spectral::project(
76 : make_not_null(&new_tensor[i]), old_tensor[i], parent_mesh, new_mesh,
77 : make_array<Dim>(Spectral::SegmentSize::Full), child_sizes);
78 : }
79 : return 0;
80 : };
81 : expand_pack(project_tensor(*tensors, get<TensorTags>(parent_items))...);
82 : }
83 :
84 : template <typename... Tags>
85 0 : static void apply(
86 : const gsl::not_null<typename TensorTags::type*>... tensors,
87 : const Element<Dim>& element, const Mesh<Dim>& new_mesh,
88 : const std::unordered_map<ElementId<Dim>, tuples::TaggedTuple<Tags...>>&
89 : children_items) {
90 : const auto& element_id = element.id();
91 : bool first_child = true;
92 : for (const auto& [child_id, child_items] : children_items) {
93 : const auto& child_mesh = get<domain::Tags::Mesh<Dim>>(child_items);
94 : const auto child_sizes =
95 : domain::child_size(child_id.segment_ids(), element_id.segment_ids());
96 : if (first_child) {
97 : const auto project_tensor = [&](auto& new_tensor,
98 : const auto& old_tensor) {
99 : for (size_t i = 0; i < new_tensor.size(); ++i) {
100 : Spectral::project(make_not_null(&new_tensor[i]), old_tensor[i],
101 : child_mesh, new_mesh, child_sizes,
102 : make_array<Dim>(Spectral::SegmentSize::Full));
103 : }
104 : return 0;
105 : };
106 : expand_pack(project_tensor(*tensors, get<TensorTags>(child_items))...);
107 : first_child = false;
108 : } else {
109 : const auto project_tensor = [&](auto& new_tensor,
110 : const auto& old_tensor) {
111 : for (size_t i = 0; i < new_tensor.size(); ++i) {
112 : new_tensor[i] += Spectral::project(
113 : old_tensor[i], child_mesh, new_mesh, child_sizes,
114 : make_array<Dim>(Spectral::SegmentSize::Full));
115 : }
116 : return 0;
117 : };
118 : expand_pack(project_tensor(*tensors, get<TensorTags>(child_items))...);
119 : }
120 : }
121 : }
122 : };
123 :
124 : /// \cond
125 : template <size_t Dim, typename... TensorTags>
126 : struct ProjectTensors<Dim, tmpl::list<TensorTags...>>
127 : : public ProjectTensors<Dim, TensorTags...> {};
128 : /// \endcond
129 : } // namespace amr::projectors
|