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/Tag.hpp" 10 : #include "Utilities/NoSuchType.hpp" 11 : #include "Utilities/TMPL.hpp" 12 : #include "Utilities/TypeTraits/CreateGetStaticMemberVariableOrDefault.hpp" 13 : #include "Utilities/TypeTraits/CreateGetTypeAliasOrDefault.hpp" 14 : #include "Utilities/TypeTraits/IsA.hpp" 15 : 16 : /// \cond 17 : namespace Tags { 18 : template <size_t Dim, typename TagsList> 19 : struct BoundaryVariables; 20 : } // namespace Tags 21 : /// \endcond 22 : 23 : namespace evolution::dg { 24 1 : namespace Tags { 25 : /// \ingroup DiscontinuousGalerkinGroup 26 : /// \brief The boundary-evolved twin of an interior source field. 27 : /// 28 : /// A boundary-evolved field is stored and time-integrated only on external 29 : /// boundary faces (a pointwise per-face-node ODE); it has no volume extent. 30 : /// This is a prefix tag wrapping the interior source, so its type matches the 31 : /// source. 32 : /// 33 : /// \note Boundary evolved fields cannot currently be used with AMR or LTS. 34 : template <typename Source> 35 1 : struct BoundaryValue : db::PrefixTag, db::SimpleTag { 36 0 : using type = typename Source::type; 37 : /// The interior source field this boundary field is the twin of. 38 1 : using tag = Source; 39 : }; 40 : } // namespace Tags 41 : 42 : namespace detail { 43 : template <typename Tag> 44 : struct is_boundary_variables_tag : std::false_type {}; 45 : template <size_t Dim, typename TagsList> 46 : struct is_boundary_variables_tag<::Tags::BoundaryVariables<Dim, TagsList>> 47 : : std::true_type {}; 48 : 49 : template <typename VariablesTag> 50 : struct boundary_variables_tag_impl : std::false_type { 51 : using type = NoSuchType; 52 : }; 53 : template <typename VariablesTag> 54 : requires tt::is_a_v<tmpl::list, VariablesTag> 55 : struct boundary_variables_tag_impl<VariablesTag> { 56 : private: 57 : using back = tmpl::back<VariablesTag>; 58 : 59 : public: 60 : static constexpr bool value = is_boundary_variables_tag<back>::value; 61 : static_assert( 62 : tmpl::count_if<VariablesTag, 63 : tmpl::bind<is_boundary_variables_tag, tmpl::_1>>::value == 64 : (value ? 1 : 0), 65 : "A list-valued variables_tag must contain at most one " 66 : "::Tags::BoundaryVariables entry, and it must be the last entry."); 67 : using type = tmpl::conditional_t<value, back, NoSuchType>; 68 : }; 69 : } // namespace detail 70 : 71 : /// \ingroup DiscontinuousGalerkinGroup 72 : /// \brief Whether the system declares boundary-evolved variables, i.e. 73 : /// whether `System::variables_tag` is a `tmpl::list` whose last entry is a 74 : /// `::Tags::BoundaryVariables`. 75 : template <typename System> 76 1 : constexpr bool system_has_boundary_variables_v = 77 : detail::boundary_variables_tag_impl<typename System::variables_tag>::value; 78 : 79 : /// \ingroup DiscontinuousGalerkinGroup 80 : /// \brief The `::Tags::BoundaryVariables` entry of the system's list-valued 81 : /// `variables_tag`, or `NoSuchType` if the system does not declare 82 : /// boundary-evolved variables. 83 : template <typename System> 84 1 : using boundary_variables_tag = typename detail::boundary_variables_tag_impl< 85 : typename System::variables_tag>::type; 86 : 87 : /// @{ 88 : /// \ingroup DiscontinuousGalerkinGroup 89 : /// \brief The projected interior inputs to a boundary condition's 90 : /// `boundary_field_time_derivatives` method, in the order evolved, 91 : /// primitive, temporary. 92 : /// 93 : /// They are declared separately from the `dg_ghost` interior inputs 94 : /// (`dg_interior_evolved_variables_tags` etc.) so that a boundary condition 95 : /// can request a different projected interior state for its boundary-field 96 : /// time derivative. The boundary-condition pass projects the requested 97 : /// fields onto the face exactly as it does for the `dg_ghost` inputs. 98 1 : CREATE_GET_TYPE_ALIAS_OR_DEFAULT( 99 : boundary_field_time_derivatives_evolved_variables_tags) 100 : CREATE_GET_TYPE_ALIAS_OR_DEFAULT(boundary_field_time_derivatives_primitive_tags) 101 : CREATE_GET_TYPE_ALIAS_OR_DEFAULT(boundary_field_time_derivatives_temporary_tags) 102 : 103 : template <typename BoundaryCondition> 104 : using boundary_field_time_derivatives_interior_tags = tmpl::append< 105 : get_boundary_field_time_derivatives_evolved_variables_tags_or_default_t< 106 : BoundaryCondition, tmpl::list<>>, 107 : get_boundary_field_time_derivatives_primitive_tags_or_default_t< 108 : BoundaryCondition, tmpl::list<>>, 109 : get_boundary_field_time_derivatives_temporary_tags_or_default_t< 110 : BoundaryCondition, tmpl::list<>>>; 111 : /// @} 112 : 113 : namespace detail { 114 : CREATE_GET_STATIC_MEMBER_VARIABLE_OR_DEFAULT(evolves_boundary_variables) 115 : 116 : // Detect if the boundary condition declares a `boundary_field_time_derivatives` 117 : // method. 118 : template <typename BoundaryCondition> 119 : constexpr bool has_boundary_field_time_derivatives_v = requires { 120 : &BoundaryCondition::boundary_field_time_derivatives; 121 : }; 122 : } // namespace detail 123 : 124 : /// @{ 125 : /// \ingroup DiscontinuousGalerkinGroup 126 : /// \brief Whether a boundary condition evolves the system's boundary-evolved 127 : /// variables: the opt-in is the marker 128 : /// `static constexpr bool evolves_boundary_variables = true;` on the 129 : /// boundary condition. An opt-in boundary condition must declare 130 : /// the method `boundary_field_time_derivatives`. 131 : template <typename BoundaryCondition> 132 1 : constexpr bool evolves_boundary_variables_v = 133 : detail::get_evolves_boundary_variables_or_default_v<BoundaryCondition, 134 : false>; 135 : /// @} 136 : } // namespace evolution::dg