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 <type_traits> 8 : 9 : #include "DataStructures/DataBox/DataBox.hpp" 10 : #include "Domain/Structure/Direction.hpp" 11 : #include "Domain/Tags.hpp" 12 : #include "Domain/Tags/Faces.hpp" 13 : #include "Elliptic/BoundaryConditions/BoundaryCondition.hpp" 14 : #include "Elliptic/Utilities/ApplyAt.hpp" 15 : #include "Parallel/Tags/Metavariables.hpp" 16 : #include "Utilities/CallWithDynamicType.hpp" 17 : #include "Utilities/Gsl.hpp" 18 : #include "Utilities/TMPL.hpp" 19 : 20 : namespace elliptic { 21 : 22 : namespace detail { 23 : // Return the `BoundaryConditionClasses`, or get the list of derived classes 24 : // from `Metavariables::factory_creation` if `BoundaryConditionClasses` is 25 : // empty. 26 : template <typename Base, typename BoundaryConditionClasses, typename DbTagsList> 27 : struct GetBoundaryConditionClasses { 28 : using type = BoundaryConditionClasses; 29 : }; 30 : template <typename Base, typename DbTagsList> 31 : struct GetBoundaryConditionClasses<Base, tmpl::list<>, DbTagsList> { 32 : using type = tmpl::at< 33 : typename std::decay_t<decltype(db::get<Parallel::Tags::Metavariables>( 34 : std::declval<db::DataBox<DbTagsList>>()))>::factory_creation:: 35 : factory_classes, 36 : Base>; 37 : }; 38 : } // namespace detail 39 : 40 : /*! 41 : * \brief Apply the `boundary_condition` to the `fields_and_fluxes` with 42 : * arguments from interface tags in the DataBox. 43 : * 44 : * This functions assumes the arguments for the `boundary_condition` are stored 45 : * in the DataBox in tags `domain::Tags::Faces<Dim, Tag>`. 46 : * This may turn out not to be the most efficient setup, so code that 47 : * uses the boundary conditions doesn't have to use this function but can 48 : * procure the arguments differently. For example, future optimizations may 49 : * involve storing a subset of arguments that don't change during an elliptic 50 : * solve in direction-maps in the DataBox, and slicing other arguments to the 51 : * interface every time the boundary conditions are applied. 52 : * 53 : * The `ArgsTransform` template parameter can be used to transform the set of 54 : * argument tags for the boundary conditions further. It must be compatible with 55 : * `tmpl::transform`. For example, it may wrap the tags in another prefix. Set 56 : * it to `void` (default) to apply no transformation. 57 : * 58 : * The `BoundaryConditionClasses` can be used to list a set of classes derived 59 : * from `elliptic::BoundaryConditions::BoundaryCondition` that are iterated to 60 : * determine the concrete type of `boundary_condition`. It can be `tmpl::list<>` 61 : * (default) to use the classes listed in `Metavariables::factory_creation` 62 : * instead. 63 : */ 64 : template <bool Linearized, typename ArgsTransform = void, 65 : typename BoundaryConditionClasses = tmpl::list<>, size_t Dim, 66 : typename DbTagsList, typename MapKeys, typename... FieldsAndFluxes> 67 1 : void apply_boundary_condition( 68 : const elliptic::BoundaryConditions::BoundaryCondition<Dim>& 69 : boundary_condition, 70 : const db::DataBox<DbTagsList>& box, const MapKeys& map_keys_to_direction, 71 : FieldsAndFluxes&&... fields_and_fluxes) { 72 : using boundary_condition_classes = 73 : typename detail::GetBoundaryConditionClasses< 74 : elliptic::BoundaryConditions::BoundaryCondition<Dim>, 75 : BoundaryConditionClasses, DbTagsList>::type; 76 : call_with_dynamic_type<void, boundary_condition_classes>( 77 : &boundary_condition, 78 : []<typename... LocalFieldsAndFluxes>( 79 : const auto* const derived, const MapKeys& local_map_keys_to_direction, 80 : const db::DataBox<DbTagsList>& local_box, 81 : const LocalFieldsAndFluxes&... local_fields_and_fluxes) { 82 : using Derived = std::decay_t<std::remove_pointer_t<decltype(derived)>>; 83 : using volume_tags = 84 : tmpl::conditional_t<Linearized, 85 : typename Derived::volume_tags_linearized, 86 : typename Derived::volume_tags>; 87 : using argument_tags = domain::make_faces_tags< 88 : Dim, 89 : tmpl::conditional_t<Linearized, 90 : typename Derived::argument_tags_linearized, 91 : typename Derived::argument_tags>, 92 : volume_tags>; 93 : using argument_tags_transformed = 94 : tmpl::conditional_t<std::is_same_v<ArgsTransform, void>, 95 : argument_tags, 96 : tmpl::transform<argument_tags, ArgsTransform>>; 97 : using volume_tags_transformed = 98 : tmpl::conditional_t<std::is_same_v<ArgsTransform, void>, 99 : volume_tags, 100 : tmpl::transform<volume_tags, ArgsTransform>>; 101 : elliptic::util::apply_at<argument_tags_transformed, 102 : volume_tags_transformed>( 103 : [&](const auto&... args) { 104 : if constexpr (Linearized) { 105 : derived->apply_linearized( 106 : local_fields_and_fluxes..., 107 : args...); 108 : } else { 109 : derived->apply(local_fields_and_fluxes..., args...); 110 : } 111 : }, 112 : local_box, local_map_keys_to_direction); 113 : }, 114 : map_keys_to_direction, box, 115 : std::forward<FieldsAndFluxes>(fields_and_fluxes)...); 116 : } 117 : } // namespace elliptic