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 : using options = tmpl::list<>; 58 0 : static constexpr Options::String help{ 59 : "Cartoon boundary condition, to be used in systems that do not implement " 60 : "Subcell.\n\nNote: This should never be used as an external boundary, it " 61 : "is only used on specific cartoon-system boundaries that are " 62 : "automatically handled in the domain creators."}; 63 0 : static std::string name() { return "Cartoon"; } 64 : 65 0 : Cartoon() = default; 66 0 : Cartoon(Cartoon&&) = default; 67 0 : Cartoon& operator=(Cartoon&&) = default; 68 0 : Cartoon(const Cartoon&) = default; 69 0 : Cartoon& operator=(const Cartoon&) = default; 70 0 : ~Cartoon() override = default; 71 : 72 0 : explicit Cartoon(CkMigrateMessage* msg); 73 : 74 0 : WRAPPED_PUPable_decl_base_template( 75 : domain::BoundaryConditions::BoundaryCondition, Cartoon); 76 : 77 0 : auto get_clone() const -> std::unique_ptr< 78 : domain::BoundaryConditions::BoundaryCondition> override; 79 : 80 0 : void pup(PUP::er& p) override; 81 : }; 82 : 83 : template <typename SystemBoundaryConditionBaseClass> 84 : Cartoon<SystemBoundaryConditionBaseClass>::Cartoon(CkMigrateMessage* const msg) 85 : : SystemBoundaryConditionBaseClass(msg) {} 86 : 87 : template <typename SystemBoundaryConditionBaseClass> 88 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition> 89 : Cartoon<SystemBoundaryConditionBaseClass>::get_clone() const { 90 : return std::make_unique<Cartoon>(*this); 91 : } 92 : 93 : template <typename SystemBoundaryConditionBaseClass> 94 : void Cartoon<SystemBoundaryConditionBaseClass>::pup(PUP::er& p) { 95 : BoundaryCondition::pup(p); 96 : } 97 : 98 : /// \cond 99 : template <typename SystemBoundaryConditionBaseClass> 100 : // NOLINTNEXTLINE 101 : PUP::able::PUP_ID Cartoon<SystemBoundaryConditionBaseClass>::my_PUP_ID = 0; 102 : /// \endcond 103 : 104 : /// Check if a boundary condition inherits from `MarkAsCartoon`, which 105 : /// constitutes as it being marked as an internal Cartoon boundary condition. 106 1 : bool is_cartoon(const std::unique_ptr<BoundaryCondition>& boundary_condition); 107 : 108 : /// Check if a mesh is compatible with a Cartoon boundary condition, i.e. it is 109 : /// using cartoon bases in a proper way. 110 : template <size_t Dim> 111 1 : bool dg_mesh_is_cartoon_compatible(const Mesh<Dim>& dg_mesh); 112 : 113 : namespace detail { 114 : template <typename T> 115 : struct inherits_from_mark_as_cartoon : std::is_base_of<MarkAsCartoon, T> {}; 116 : 117 : template <typename List> 118 : struct find_cartoon_bc_impl { 119 : using filtered_list = 120 : tmpl::filter<List, inherits_from_mark_as_cartoon<tmpl::_1>>; 121 : 122 : // Ensure there's exactly one cartoon BC, not zero or multiple 123 : static_assert(tmpl::size<filtered_list>::value <= 1, 124 : "Multiple cartoon boundary conditions found in factory list. " 125 : "Only one cartoon boundary condition is allowed per system."); 126 : 127 : // Need lazy evaluation in case list is empty 128 : template <typename L> 129 : using get_maybe_first = tmpl::apply<tmpl::apply< 130 : tmpl::if_<std::bool_constant<(tmpl::size<L>::value != 0)>, 131 : tmpl::defer<tmpl::bind<tmpl::front, tmpl::pin<L>>>, void>>>; 132 : 133 : using type = get_maybe_first<filtered_list>; 134 : }; 135 : 136 : /// Find the unique type in a tmpl::list that inherits from MarkAsCartoon 137 : template <typename List> 138 : using find_cartoon_bc = typename find_cartoon_bc_impl<List>::type; 139 : 140 : /// Check if a tmpl::list contains any types that inherit from MarkAsCartoon 141 : template <typename List> 142 : constexpr bool has_cartoon_bc_v = not std::is_void_v<find_cartoon_bc<List>>; 143 : 144 : /// Filter out cartoon boundary conditions from a list, leaving only external 145 : /// BCs 146 : template <typename List> 147 : using filter_out_cartoon_bcs = 148 : tmpl::remove_if<List, inherits_from_mark_as_cartoon<tmpl::_1>>; 149 : } // namespace detail 150 : 151 : /// Extract the cartoon boundary condition type from a system's boundary 152 : /// condition list. Returns void if no cartoon boundary condition is found. 153 : template <typename Metavariables> 154 1 : using get_cartoon_boundary_condition_from_system = detail::find_cartoon_bc< 155 : tmpl::at<typename Metavariables::factory_creation::factory_classes, 156 : typename Metavariables::system::boundary_conditions_base>>; 157 : 158 : /// Extract only the external (non-cartoon) boundary conditions from a system's 159 : /// boundary condition list. This should be used for user-selectable boundary 160 : /// condition options to prevent cartoon BCs from being specified as external 161 : /// BCs. 162 : template <typename Metavariables> 163 1 : using get_external_boundary_conditions_from_system = 164 : detail::filter_out_cartoon_bcs< 165 : tmpl::at<typename Metavariables::factory_creation::factory_classes, 166 : typename Metavariables::system::boundary_conditions_base>>; 167 : 168 : /// Check if a system has a cartoon boundary condition available 169 : template <typename Metavariables> 170 1 : constexpr bool system_has_cartoon_bc_v = not std::is_void_v< 171 : get_cartoon_boundary_condition_from_system<Metavariables>>; 172 : 173 : /// Create a cartoon boundary condition for systems that support it. 174 : /// Returns nullptr if the system doesn't have a cartoon boundary condition. 175 : template <typename Metavariables> 176 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition> 177 1 : make_cartoon_boundary_condition() { 178 : if constexpr (system_has_cartoon_bc_v<Metavariables>) { 179 : using cartoon_bc_type = 180 : get_cartoon_boundary_condition_from_system<Metavariables>; 181 : return std::make_unique<cartoon_bc_type>(); 182 : } else { 183 : return nullptr; 184 : } 185 : } 186 : } // namespace domain::BoundaryConditions