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