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 "NumericalAlgorithms/Spectral/SegmentSize.hpp" 19 : #include "ParallelAlgorithms/Amr/Protocols/Projector.hpp" 20 : #include "Utilities/Gsl.hpp" 21 : #include "Utilities/TMPL.hpp" 22 : #include "Utilities/TaggedTuple.hpp" 23 : 24 : namespace amr::projectors { 25 : 26 : /// \brief Update the Variables corresponding to VariablesTags after an AMR 27 : /// change 28 : /// 29 : /// There is a specialization for 30 : /// `ProjectVariables<tmpl::list<VariablesTags...>>` that can be used if a 31 : /// `tmpl::list` is available. 32 : /// 33 : /// \details For each item corresponding to each tag in VariablesTags, project 34 : /// the data for each variable from the old mesh to the new mesh 35 : /// 36 : /// \see ProjectTensors 37 : template <size_t Dim, typename... VariablesTags> 38 1 : struct ProjectVariables : tt::ConformsTo<amr::protocols::Projector> { 39 0 : using return_tags = tmpl::list<VariablesTags...>; 40 0 : using argument_tags = 41 : tmpl::list<domain::Tags::Element<Dim>, domain::Tags::Mesh<Dim>>; 42 : 43 : // p-refinement 44 0 : static void apply( 45 : const gsl::not_null<typename VariablesTags::type*>... vars, 46 : const Element<Dim>& /*element*/, const Mesh<Dim>& new_mesh, 47 : const std::pair<Mesh<Dim>, Element<Dim>>& old_mesh_and_element) { 48 : const auto& old_mesh = old_mesh_and_element.first; 49 : if (old_mesh == new_mesh) { 50 : return; // mesh was not refined, so no projection needed 51 : } 52 : const auto projection_matrices = 53 : Spectral::p_projection_matrices(old_mesh, new_mesh); 54 : const auto& old_extents = old_mesh.extents(); 55 : expand_pack( 56 : (*vars = apply_matrices(projection_matrices, *vars, old_extents))...); 57 : } 58 : 59 : // h-refinement 60 : template <typename... Tags> 61 0 : static void apply(const gsl::not_null<typename VariablesTags::type*>... vars, 62 : const Element<Dim>& element, const Mesh<Dim>& new_mesh, 63 : const tuples::TaggedTuple<Tags...>& parent_items) { 64 : const auto& element_id = element.id(); 65 : const auto& parent_id = get<domain::Tags::Element<Dim>>(parent_items).id(); 66 : const auto& parent_mesh = get<domain::Tags::Mesh<Dim>>(parent_items); 67 : const auto child_sizes = 68 : domain::child_size(element_id.segment_ids(), parent_id.segment_ids()); 69 : const auto projection_matrices = 70 : Spectral::projection_matrix_parent_to_child(parent_mesh, new_mesh, 71 : child_sizes); 72 : expand_pack((*vars = apply_matrices(projection_matrices, 73 : get<VariablesTags>(parent_items), 74 : parent_mesh.extents()))...); 75 : } 76 : 77 : // h-coarsening 78 : template <typename... Tags> 79 0 : static void apply( 80 : const gsl::not_null<typename VariablesTags::type*>... vars, 81 : const Element<Dim>& element, const Mesh<Dim>& new_mesh, 82 : const std::unordered_map<ElementId<Dim>, tuples::TaggedTuple<Tags...>>& 83 : children_items) { 84 : const auto& element_id = element.id(); 85 : bool first_child = true; 86 : for (const auto& [child_id, child_items] : children_items) { 87 : const auto& child_mesh = get<domain::Tags::Mesh<Dim>>(child_items); 88 : const auto child_sizes = 89 : domain::child_size(child_id.segment_ids(), element_id.segment_ids()); 90 : const auto projection_matrices = 91 : Spectral::projection_matrix_child_to_parent(child_mesh, new_mesh, 92 : child_sizes); 93 : if (first_child) { 94 : expand_pack((*vars = apply_matrices(projection_matrices, 95 : get<VariablesTags>(child_items), 96 : child_mesh.extents()))...); 97 : first_child = false; 98 : } else { 99 : expand_pack((*vars += apply_matrices(projection_matrices, 100 : get<VariablesTags>(child_items), 101 : child_mesh.extents()))...); 102 : } 103 : } 104 : } 105 : }; 106 : 107 : /// \cond 108 : template <size_t Dim, typename... VariableTags> 109 : struct ProjectVariables<Dim, tmpl::list<VariableTags...>> 110 : : public ProjectVariables<Dim, VariableTags...> {}; 111 : /// \endcond 112 : } // namespace amr::projectors