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