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 <utility> 8 : 9 : #include "DataStructures/DataBox/DataBox.hpp" 10 : #include "DataStructures/Variables.hpp" 11 : #include "Domain/BoundaryVariables.hpp" 12 : #include "Domain/BoundaryVariablesTag.hpp" 13 : #include "Domain/Creators/Tags/ExternalBoundaryConditions.hpp" 14 : #include "Domain/Structure/Direction.hpp" 15 : #include "Domain/Structure/DirectionMap.hpp" 16 : #include "Domain/Structure/Element.hpp" 17 : #include "Domain/Tags.hpp" 18 : #include "Evolution/DiscontinuousGalerkin/BoundaryEvolvedVariables.hpp" 19 : #include "NumericalAlgorithms/DiscontinuousGalerkin/ProjectToBoundary.hpp" 20 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 21 : #include "Parallel/AlgorithmExecution.hpp" 22 : #include "Time/LtsMode.hpp" 23 : #include "Time/Tags/LtsMode.hpp" 24 : #include "Utilities/CallWithDynamicType.hpp" 25 : #include "Utilities/ErrorHandling/Error.hpp" 26 : #include "Utilities/Gsl.hpp" 27 : #include "Utilities/TMPL.hpp" 28 : 29 : /// \cond 30 : namespace Parallel { 31 : template <typename Metavariables> 32 : class GlobalCache; 33 : } // namespace Parallel 34 : namespace tuples { 35 : template <class... Tags> 36 : class TaggedTuple; 37 : } // namespace tuples 38 : /// \endcond 39 : 40 1 : namespace evolution::dg::Initialization { 41 : /// \ingroup ActionsGroup 42 : /// \ingroup DiscontinuousGalerkinGroup 43 : /// \brief Allocates and initializes the system's boundary-evolved variables 44 : /// (the `::Tags::BoundaryVariables` entry of the list-valued 45 : /// `System::variables_tag`) on each opting external face. 46 : /// 47 : /// Iterates the element's external boundaries and gives each face whose 48 : /// boundary condition opts in (declares the `evolves_boundary_variables` 49 : /// marker) a face-sized entry in the `BoundaryVariables` storage. Each 50 : /// `Tags::BoundaryValue<Source>` is initialized by projecting its interior 51 : /// `Source` from the volume variables to the face. Interior and non-opting 52 : /// faces get no entry. 53 : /// 54 : /// Runs after the domain and the initial data are set, and before 55 : /// `Initialization::TimeStepperHistory`, which sizes the `::Tags::dt` twin of 56 : /// the storage from the per-face storage initialized here. 57 : /// 58 : /// \tparam Dim the spatial dimension 59 : /// \tparam System the evolution system (supplies `variables_tag`) 60 : /// \tparam DerivedBoundaryConditionsList the concrete boundary condition 61 : /// types; it must contain every type that can appear on an external boundary 62 : template <size_t Dim, typename System, typename DerivedBoundaryConditionsList> 63 1 : struct BoundaryEvolvedVariables { 64 : private: 65 : static_assert( 66 : evolution::dg::system_has_boundary_variables_v<System>, 67 : "Boundary-evolved variables can only be initialized for a system whose " 68 : "variables_tag is a tmpl::list with a ::Tags::BoundaryVariables entry " 69 : "holding the boundary-evolved variables."); 70 0 : using boundary_variables_tag = evolution::dg::boundary_variables_tag<System>; 71 0 : using boundary_field_tags_list = typename boundary_variables_tag::tags_list; 72 0 : using volume_variables_tag = tmpl::front<typename System::variables_tag>; 73 : 74 : public: 75 0 : using const_global_cache_tags = 76 : tmpl::list<domain::Tags::ExternalBoundaryConditions<Dim>>; 77 0 : using simple_tags_from_options = tmpl::list<>; 78 0 : using simple_tags = tmpl::list<boundary_variables_tag>; 79 0 : using compute_tags = tmpl::list<>; 80 : 81 : template <typename DbTagsList, typename... InboxTags, typename Metavariables, 82 : typename ArrayIndex, typename ActionList, 83 : typename ParallelComponent> 84 0 : static Parallel::iterable_action_return_t apply( 85 : db::DataBox<DbTagsList>& box, 86 : const tuples::TaggedTuple<InboxTags...>& /*inboxes*/, 87 : const Parallel::GlobalCache<Metavariables>& /*cache*/, 88 : const ArrayIndex& /*array_index*/, ActionList /*meta*/, 89 : const ParallelComponent* const /*meta*/) { 90 : if (db::get<::Tags::LtsMode>(box) != LtsMode::Off) { 91 : ERROR( 92 : "Boundary-evolved variables are unverified with local time " 93 : "stepping."); 94 : } 95 : const auto& element = db::get<::domain::Tags::Element<Dim>>(box); 96 : const auto& mesh = db::get<::domain::Tags::Mesh<Dim>>(box); 97 : if (db::get<volume_variables_tag>(box).number_of_grid_points() != 98 : mesh.number_of_grid_points()) { 99 : ERROR("The volume variables are not allocated to the mesh size (" 100 : << db::get<volume_variables_tag>(box).number_of_grid_points() 101 : << " variables grid points vs " << mesh.number_of_grid_points() 102 : << " mesh grid points). This action projects the volume " 103 : "variables onto the opting external faces, so it must run " 104 : "after the volume variables are allocated and set from the " 105 : "initial data."); 106 : } 107 : const auto& external_boundary_conditions = 108 : db::get<domain::Tags::ExternalBoundaryConditions<Dim>>(box).at( 109 : element.id().block_id()); 110 : 111 : DirectionMap<Dim, size_t> points_per_direction{}; 112 : for (const Direction<Dim>& direction : element.external_boundaries()) { 113 : call_with_dynamic_type<void, DerivedBoundaryConditionsList>( 114 : &*external_boundary_conditions.at(direction), 115 : [&direction, &mesh, 116 : &points_per_direction]<typename DerivedBoundaryCondition>( 117 : const DerivedBoundaryCondition* const /*boundary_condition*/) { 118 : if constexpr (evolution::dg::evolves_boundary_variables_v< 119 : DerivedBoundaryCondition>) { 120 : points_per_direction.insert( 121 : {direction, mesh.slice_away(direction.dimension()) 122 : .number_of_grid_points()}); 123 : } 124 : }); 125 : } 126 : 127 : db::mutate<boundary_variables_tag>( 128 : [&mesh, &points_per_direction]( 129 : const gsl::not_null<typename boundary_variables_tag::type*> 130 : boundary_vars, 131 : const typename volume_variables_tag::type& volume_variables) { 132 : boundary_vars->initialize(std::move(points_per_direction)); 133 : for (auto& direction_and_face_values : boundary_vars->variables()) { 134 : const auto& direction = direction_and_face_values.first; 135 : auto& face_values = direction_and_face_values.second; 136 : tmpl::for_each<boundary_field_tags_list>( 137 : [&direction, &mesh, &volume_variables, 138 : &face_values]<typename BoundaryTag>( 139 : tmpl::type_<BoundaryTag> /*meta*/) { 140 : using source_tag = typename BoundaryTag::tag; 141 : auto& face_field = get<BoundaryTag>(face_values); 142 : ::dg::project_tensor_to_boundary( 143 : make_not_null(&face_field), 144 : get<source_tag>(volume_variables), mesh, direction); 145 : }); 146 : } 147 : }, 148 : make_not_null(&box), db::get<volume_variables_tag>(box)); 149 : return {Parallel::AlgorithmExecution::Continue, std::nullopt}; 150 : } 151 : }; 152 : } // namespace evolution::dg::Initialization