Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <memory> 7 : #include <pup.h> 8 : 9 : #include "Domain/BoundaryConditions/BoundaryCondition.hpp" 10 : #include "Options/String.hpp" 11 : #include "Utilities/Serialization/CharmPupable.hpp" 12 : #include "Utilities/TMPL.hpp" 13 : 14 : /// \cond 15 : template <size_t Dim> 16 : class Mesh; 17 : /// \endcond 18 : 19 : namespace domain::BoundaryConditions { 20 : /// Mark a boundary condition as being used as an internal Cartoon boundary. 21 : /// 22 : /// The cartoon method requires a ZernikeB1 basis to be stable at small 23 : /// \f$x\f$, which should not have a boundary condition applied. However, FD 24 : /// does require ghost zones to be filled on this boundary, so `is_cartoon()` 25 : /// can be used to determine whether to treat this boundary condition as 26 : /// something to implement or skip. 27 1 : class MarkAsCartoon { 28 : public: 29 0 : MarkAsCartoon() = default; 30 0 : MarkAsCartoon(MarkAsCartoon&&) = default; 31 0 : MarkAsCartoon& operator=(MarkAsCartoon&&) = default; 32 0 : MarkAsCartoon(const MarkAsCartoon&) = default; 33 0 : MarkAsCartoon& operator=(const MarkAsCartoon&) = default; 34 0 : virtual ~MarkAsCartoon() = 0; 35 : }; 36 : 37 : /*! 38 : * \brief Cartoon boundary conditions, to be used as the default placeholder in 39 : * systems without Subcell. 40 : * 41 : * To use with a specific system, add: 42 : * 43 : * \code 44 : * domain::BoundaryConditions::Cartoon<your::system::BoundaryConditionBase> 45 : * \endcode 46 : * 47 : * to the list of creatable classes. 48 : * 49 : * Note: Cartoon boundary conditions should only be specified with systems 50 : * set-up to use the cartoon method. It should not be used as an external 51 : * boundary. 52 : */ 53 : template <typename SystemBoundaryConditionBaseClass> 54 1 : struct Cartoon final : public SystemBoundaryConditionBaseClass, 55 : public MarkAsCartoon { 56 : public: 57 0 : static constexpr bool factory_creatable = false; 58 0 : static std::string name() { return "Cartoon"; } 59 : 60 0 : Cartoon() = default; 61 0 : Cartoon(Cartoon&&) = default; 62 0 : Cartoon& operator=(Cartoon&&) = default; 63 0 : Cartoon(const Cartoon&) = default; 64 0 : Cartoon& operator=(const Cartoon&) = default; 65 0 : ~Cartoon() override = default; 66 : 67 0 : explicit Cartoon(CkMigrateMessage* msg); 68 : 69 0 : WRAPPED_PUPable_decl_base_template( 70 : domain::BoundaryConditions::BoundaryCondition, Cartoon); 71 : 72 0 : auto get_clone() const -> std::unique_ptr< 73 : domain::BoundaryConditions::BoundaryCondition> override; 74 : 75 0 : void pup(PUP::er& p) override; 76 : }; 77 : 78 : template <typename SystemBoundaryConditionBaseClass> 79 : Cartoon<SystemBoundaryConditionBaseClass>::Cartoon(CkMigrateMessage* const msg) 80 : : SystemBoundaryConditionBaseClass(msg) {} 81 : 82 : template <typename SystemBoundaryConditionBaseClass> 83 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition> 84 : Cartoon<SystemBoundaryConditionBaseClass>::get_clone() const { 85 : return std::make_unique<Cartoon>(*this); 86 : } 87 : 88 : template <typename SystemBoundaryConditionBaseClass> 89 : void Cartoon<SystemBoundaryConditionBaseClass>::pup(PUP::er& p) { 90 : BoundaryCondition::pup(p); 91 : } 92 : 93 : /// \cond 94 : template <typename SystemBoundaryConditionBaseClass> 95 : // NOLINTNEXTLINE 96 : PUP::able::PUP_ID Cartoon<SystemBoundaryConditionBaseClass>::my_PUP_ID = 0; 97 : /// \endcond 98 : 99 : /// Check if a boundary condition inherits from `MarkAsCartoon`, which 100 : /// constitutes as it being marked as an internal Cartoon boundary condition. 101 1 : bool is_cartoon(const std::unique_ptr<BoundaryCondition>& boundary_condition); 102 : 103 : /// Check if a mesh is compatible with a Cartoon boundary condition, i.e. it is 104 : /// using cartoon bases in a proper way. 105 : template <size_t Dim> 106 1 : bool dg_mesh_is_cartoon_compatible(const Mesh<Dim>& dg_mesh); 107 : 108 : namespace detail { 109 : template <typename T> 110 : struct inherits_from_mark_as_cartoon : std::is_base_of<MarkAsCartoon, T> {}; 111 : 112 : template <typename List> 113 : struct find_cartoon_bc_impl { 114 : using filtered_list = 115 : tmpl::filter<List, inherits_from_mark_as_cartoon<tmpl::_1>>; 116 : 117 : // Ensure there's exactly one cartoon BC, not zero or multiple 118 : static_assert(tmpl::size<filtered_list>::value <= 1, 119 : "Multiple cartoon boundary conditions found in factory list. " 120 : "Only one cartoon boundary condition is allowed per system."); 121 : 122 : // Need lazy evaluation in case list is empty 123 : template <typename L> 124 : using get_maybe_first = tmpl::apply<tmpl::apply< 125 : tmpl::if_<std::bool_constant<(tmpl::size<L>::value != 0)>, 126 : tmpl::defer<tmpl::bind<tmpl::front, tmpl::pin<L>>>, void>>>; 127 : 128 : using type = get_maybe_first<filtered_list>; 129 : }; 130 : 131 : /// Find the unique type in a tmpl::list that inherits from MarkAsCartoon 132 : template <typename List> 133 : using find_cartoon_bc = typename find_cartoon_bc_impl<List>::type; 134 : 135 : /// Check if a tmpl::list contains any types that inherit from MarkAsCartoon 136 : template <typename List> 137 : constexpr bool has_cartoon_bc_v = not std::is_void_v<find_cartoon_bc<List>>; 138 : 139 : /// Filter out cartoon boundary conditions from a list, leaving only external 140 : /// BCs 141 : template <typename List> 142 : using filter_out_cartoon_bcs = 143 : tmpl::remove_if<List, inherits_from_mark_as_cartoon<tmpl::_1>>; 144 : } // namespace detail 145 : 146 : /// Extract the cartoon boundary condition type from a system's boundary 147 : /// condition list. Returns void if no cartoon boundary condition is found. 148 : template <typename Metavariables> 149 1 : using get_cartoon_boundary_condition_from_system = detail::find_cartoon_bc< 150 : tmpl::at<typename Metavariables::factory_creation::factory_classes, 151 : typename Metavariables::system::boundary_conditions_base>>; 152 : 153 : /// Extract only the external (non-cartoon) boundary conditions from a system's 154 : /// boundary condition list. This should be used for user-selectable boundary 155 : /// condition options to prevent cartoon BCs from being specified as external 156 : /// BCs. 157 : template <typename Metavariables> 158 1 : using get_external_boundary_conditions_from_system = 159 : detail::filter_out_cartoon_bcs< 160 : tmpl::at<typename Metavariables::factory_creation::factory_classes, 161 : typename Metavariables::system::boundary_conditions_base>>; 162 : 163 : /// Check if a system has a cartoon boundary condition available 164 : template <typename Metavariables> 165 1 : constexpr bool system_has_cartoon_bc_v = not std::is_void_v< 166 : get_cartoon_boundary_condition_from_system<Metavariables>>; 167 : 168 : /// Create a cartoon boundary condition for systems that support it. 169 : /// Returns nullptr if the system doesn't have a cartoon boundary condition. 170 : template <typename Metavariables> 171 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition> 172 1 : make_cartoon_boundary_condition() { 173 : if constexpr (system_has_cartoon_bc_v<Metavariables>) { 174 : using cartoon_bc_type = 175 : get_cartoon_boundary_condition_from_system<Metavariables>; 176 : return std::make_unique<cartoon_bc_type>(); 177 : } else { 178 : return nullptr; 179 : } 180 : } 181 : } // namespace domain::BoundaryConditions