SpECTRE Documentation Coverage Report
Current view: top level - Domain/Creators - CartoonCylinder.hpp Hit Total Coverage
Commit: c3e43f8d41800b0ecefb9d1393f1de1d5a280c8f Lines: 7 73 9.6 %
Date: 2026-07-24 22:09:25
Legend: Lines: hit not hit

          Line data    Source code
       1           0 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : #pragma once
       5             : 
       6             : #include <array>
       7             : #include <cstddef>
       8             : #include <memory>
       9             : #include <string>
      10             : #include <unordered_map>
      11             : #include <vector>
      12             : 
      13             : #include "Domain/BoundaryConditions/BoundaryCondition.hpp"
      14             : #include "Domain/BoundaryConditions/Cartoon.hpp"
      15             : #include "Domain/BoundaryConditions/GetBoundaryConditionsBase.hpp"
      16             : #include "Domain/CoordinateMaps/Distribution.hpp"
      17             : #include "Domain/Creators/DomainCreator.hpp"
      18             : #include "Domain/Creators/TimeDependence/TimeDependence.hpp"
      19             : #include "Domain/Domain.hpp"
      20             : #include "Domain/Structure/DirectionMap.hpp"
      21             : #include "Options/Context.hpp"
      22             : #include "Options/String.hpp"
      23             : #include "Utilities/TMPL.hpp"
      24             : 
      25             : /// \cond
      26             : namespace domain {
      27             : namespace CoordinateMaps {
      28             : class Interval;
      29             : template <typename Map1, typename Map2, typename Map3>
      30             : class ProductOf3Maps;
      31             : }  // namespace CoordinateMaps
      32             : 
      33             : template <typename SourceFrame, typename TargetFrame, typename... Maps>
      34             : class CoordinateMap;
      35             : }  // namespace domain
      36             : /// \endcond
      37             : 
      38             : namespace domain::creators {
      39             : /// Create a 3D Domain with its computational domain being the\f$x-y\f$
      40             : /// plane. The third dimension uses a Cartoon basis with Killing vector along
      41             : /// the \f$\phi\f$ direction.
      42           1 : class CartoonCylinder : public DomainCreator<3> {
      43             :  public:
      44           0 :   using maps_list = tmpl::list<domain::CoordinateMap<
      45             :       Frame::BlockLogical, Frame::Inertial,
      46             :       CoordinateMaps::ProductOf3Maps<CoordinateMaps::Interval,
      47             :                                      CoordinateMaps::Interval,
      48             :                                      CoordinateMaps::Identity<1>>>>;
      49             : 
      50           0 :   static std::string name() { return "CartoonCylinder"; }
      51             : 
      52           0 :   struct LowerBounds {
      53           0 :     using type = std::array<double, 2>;
      54           0 :     static constexpr Options::String help = {
      55             :         "Lower bound in the [x,y] dimensions. The lower x must be greater than "
      56             :         "or equal to 0. If x=0 is included, the innermost elements use a 1D "
      57             :         "Zernike basis, otherwise the domain will be a cylindrical shell."};
      58             :   };
      59             : 
      60           0 :   struct UpperBounds {
      61           0 :     using type = std::array<double, 2>;
      62           0 :     static constexpr Options::String help = {
      63             :         "Upper bound in the [x,y] dimensions."};
      64             :   };
      65             : 
      66           0 :   struct InitialRefinement {
      67           0 :     using type = std::array<size_t, 2>;
      68           0 :     static constexpr Options::String help = {
      69             :         "Initial refinement level for the [x,y] dimensions."};
      70             :   };
      71             : 
      72           0 :   struct InitialGridPoints {
      73           0 :     using type = std::array<size_t, 2>;
      74           0 :     static constexpr Options::String help = {
      75             :         "Initial number of grid points in the [x,y] dimensions."};
      76             :   };
      77             : 
      78           0 :   struct Distributions {
      79           0 :     using type = std::array<CoordinateMaps::Distribution, 2>;
      80           0 :     static constexpr Options::String help = {
      81             :         "Distribution of grid points in the [x,y] dimensions."};
      82             :   };
      83             : 
      84             :   template <typename BoundaryConditionsBase>
      85           0 :   struct LowerUpperBoundaryCondition {
      86           0 :     static constexpr Options::String help =
      87             :         "Lower and upper Boundary Conditions";
      88           0 :     struct LowerBC {
      89           0 :       using type = std::unique_ptr<BoundaryConditionsBase>;
      90           0 :       static constexpr Options::String help = "Lower Boundary Condition";
      91           0 :       static std::string name() { return "Lower"; };
      92             :     };
      93           0 :     struct UpperBC {
      94           0 :       using type = std::unique_ptr<BoundaryConditionsBase>;
      95           0 :       static constexpr Options::String help = "Upper Boundary Condition";
      96           0 :       static std::string name() { return "Upper"; };
      97             :     };
      98           0 :     LowerUpperBoundaryCondition(typename LowerBC::type lower_bc,
      99             :                                 typename UpperBC::type upper_bc)
     100             :         : lower(std::move(lower_bc)), upper(std::move(upper_bc)){};
     101           0 :     LowerUpperBoundaryCondition() = default;
     102           0 :     std::unique_ptr<BoundaryConditionsBase> lower;
     103           0 :     std::unique_ptr<BoundaryConditionsBase> upper;
     104           0 :     using options = tmpl::list<LowerBC, UpperBC>;
     105             :   };
     106             : 
     107             :   template <typename BoundaryConditionsBase>
     108           0 :   struct BoundaryConditions {
     109           0 :     static constexpr Options::String help = {
     110             :         "The boundary conditions to be imposed in the x & y dimensions. "
     111             :         "Either specify one B.C. to be imposed for both "
     112             :         "lower and upper boundary or a pair 'Lower:' and 'Upper:'."};
     113           0 :     using type = std::array<
     114             :         std::variant<std::unique_ptr<BoundaryConditionsBase>,
     115             :                      LowerUpperBoundaryCondition<BoundaryConditionsBase>>,
     116             :         2>;
     117             :   };
     118             : 
     119           0 :   struct TimeDependence {
     120           0 :     using type =
     121             :         std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>;
     122           0 :     static constexpr Options::String help = {
     123             :         "The time dependence of the moving mesh domain. Specify `None` for no "
     124             :         "time dependant maps."};
     125             :   };
     126             : 
     127           0 :   using basic_options =
     128             :       tmpl::list<LowerBounds, UpperBounds, InitialRefinement, InitialGridPoints,
     129             :                  Distributions, TimeDependence>;
     130             : 
     131             :   template <typename Metavariables>
     132           0 :   using options = tmpl::conditional_t<
     133             :       domain::BoundaryConditions::has_boundary_conditions_base_v<
     134             :           typename Metavariables::system>,
     135             :       tmpl::push_back<
     136             :           basic_options,
     137             :           BoundaryConditions<
     138             :               domain::BoundaryConditions::get_boundary_conditions_base<
     139             :                   typename Metavariables::system>>>,
     140             :       basic_options>;
     141             : 
     142           0 :   static constexpr Options::String help{
     143             :       "A cylinder domain that requires/enforces axial symmetry. The "
     144             :       "computational domain is the x-y plane, with Cartoon partial derivatives "
     145             :       "being used for the z direction. Elements touching the x=0 axis use "
     146             :       "ZernikeB1 bases in the x direction and automatically apply a system's "
     147             :       "Cartoon-type boundary condition."};
     148             : 
     149           0 :   CartoonCylinder(
     150             :       std::array<double, 2> lower_bounds, std::array<double, 2> upper_bounds,
     151             :       std::array<size_t, 2> initial_refinement_levels,
     152             :       std::array<size_t, 2> initial_num_points,
     153             :       std::array<CoordinateMaps::Distribution, 2> distributions = {},
     154             :       std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
     155             :           time_dependence = nullptr,
     156             :       std::array<std::array<std::unique_ptr<
     157             :                                 domain::BoundaryConditions::BoundaryCondition>,
     158             :                             2>,
     159             :                  2>
     160             :           boundary_conditions = {},
     161             :       std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
     162             :           cartoon_boundary_condition = nullptr,
     163             :       const Options::Context& context = {});
     164             : 
     165           0 :   CartoonCylinder() = default;
     166           0 :   CartoonCylinder(const CartoonCylinder&) = delete;
     167           0 :   CartoonCylinder(CartoonCylinder&&) = default;
     168           0 :   CartoonCylinder& operator=(const CartoonCylinder&) = delete;
     169           0 :   CartoonCylinder& operator=(CartoonCylinder&&) = default;
     170           0 :   ~CartoonCylinder() override = default;
     171             : 
     172           0 :   Domain<3> create_domain() const override;
     173             : 
     174             :   std::vector<DirectionMap<
     175             :       3, std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>>>
     176           1 :   external_boundary_conditions() const override;
     177             : 
     178           1 :   std::vector<std::array<size_t, 3>> initial_extents() const override;
     179             : 
     180           1 :   std::vector<std::array<size_t, 3>> initial_refinement_levels() const override;
     181             : 
     182             :   /// The only block is Block0
     183           1 :   std::vector<std::string> block_names() const override;
     184             : 
     185             :   /// The only group is CartoonCylinder
     186             :   std::unordered_map<std::string, std::unordered_set<std::string>>
     187           1 :   block_groups() const override;
     188             : 
     189           1 :   auto functions_of_time(const std::unordered_map<std::string, double>&
     190             :                              initial_expiration_times = {}) const
     191             :       -> std::unordered_map<
     192             :           std::string,
     193             :           std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>> override;
     194             : 
     195             :   // Transforms from option-created boundary conditions to the type used in the
     196             :   // constructor
     197             :   template <typename BoundaryConditionsBase>
     198           0 :   static auto transform_boundary_conditions(
     199             :       std::array<
     200             :           std::variant<std::unique_ptr<BoundaryConditionsBase>,
     201             :                        LowerUpperBoundaryCondition<BoundaryConditionsBase>>,
     202             :           2>
     203             :           boundary_conditions)
     204             :       -> std::array<
     205             :           std::array<
     206             :               std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>,
     207             :               2>,
     208             :           2>;
     209             : 
     210             :  private:
     211           0 :   std::array<double, 2> lower_bounds_{};
     212           0 :   std::array<double, 2> upper_bounds_{};
     213           0 :   std::array<size_t, 2> initial_refinement_levels_{};
     214           0 :   std::array<size_t, 2> initial_num_points_{};
     215           0 :   bool is_periodic_in_y_{};
     216           0 :   std::array<CoordinateMaps::Distribution, 2> distributions_{};
     217           0 :   bool using_zernike_{};
     218             :   std::array<
     219             :       std::array<std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>,
     220             :                  2>,
     221             :       2>
     222           0 :       boundary_conditions_{};
     223             :   std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
     224           0 :       cartoon_boundary_condition_{};
     225             :   std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
     226           0 :       time_dependence_;
     227           0 :   size_t num_blocks_{};
     228           0 :   std::vector<std::string> block_names_{};
     229             :   std::unordered_map<std::string, std::unordered_set<std::string>>
     230           0 :       block_groups_{};
     231             : };
     232             : 
     233             : template <typename BoundaryConditionsBase>
     234             : auto CartoonCylinder::transform_boundary_conditions(
     235             :     std::array<
     236             :         std::variant<std::unique_ptr<BoundaryConditionsBase>,
     237             :                      LowerUpperBoundaryCondition<BoundaryConditionsBase>>,
     238             :         2>
     239             :         boundary_conditions)
     240             :     -> std::array<
     241             :         std::array<
     242             :             std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>, 2>,
     243             :         2> {
     244             :   std::array<
     245             :       std::array<std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>,
     246             :                  2>,
     247             :       2>
     248             :       result{};
     249             :   for (size_t d = 0; d < 2; ++d) {
     250             :     if (std::holds_alternative<std::unique_ptr<BoundaryConditionsBase>>(
     251             :             boundary_conditions[d])) {
     252             :       auto bc = std::move(std::get<std::unique_ptr<BoundaryConditionsBase>>(
     253             :           boundary_conditions[d]));
     254             :       gsl::at(gsl::at(result, d), 0) = bc->get_clone();
     255             :       gsl::at(gsl::at(result, d), 1) = std::move(bc);
     256             :     } else {
     257             :       auto& bc = std::get<LowerUpperBoundaryCondition<BoundaryConditionsBase>>(
     258             :           boundary_conditions[d]);
     259             :       gsl::at(gsl::at(result, d), 0) = std::move(bc.lower);
     260             :       gsl::at(gsl::at(result, d), 1) = std::move(bc.upper);
     261             :     }
     262             :   }
     263             :   return result;
     264             : }
     265             : 
     266             : }  // namespace domain::creators
     267             : 
     268             : namespace domain::creators::detail {
     269             : /// \brief Helper struct for CartoonCylinder options parsing so the internal
     270             : /// cartoon boundary condition at $x = 0$ is not a required argument.
     271             : ///
     272             : /// \details To get the cartoon-type boundary condition from a system we need
     273             : /// access to the system's metavariables, which is only present when parsing
     274             : /// options. The point of this design is so that the input file does not
     275             : /// require a dummy value for an InnerBoundaryCondition that is always the
     276             : /// same for a given system.
     277             : ///
     278             : /// This helper's constructor does not take an InnerBoundaryCondition, which
     279             : /// means if we parse a CartoonCylinder as a CartonSphere2DOptionsHelper
     280             : /// by having an options parsing specialization (so the input file values are
     281             : /// the helper's construtor, not CartoonCylinder's), we can detect the
     282             : /// cartoon-type boundary condition for the given system and only then call
     283             : /// the CartoonCylinder constructor with the extra information.
     284             : struct CartoonCylinderOptionsHelper {
     285             :   template <typename Metavariables>
     286             :   using options = typename domain::creators::CartoonCylinder::template options<
     287             :       Metavariables>;
     288             : 
     289             :   template <typename BoundaryConditionsBase>
     290             :   using LowerUpperBoundaryCondition =
     291             :       domain::creators::CartoonCylinder::LowerUpperBoundaryCondition<
     292             :           BoundaryConditionsBase>;
     293             : 
     294             :   static constexpr Options::String help = {"CartoonCylinderOptionsHelper"};
     295             : 
     296             :   // Default constructor required by Options system
     297             :   CartoonCylinderOptionsHelper() = default;
     298             : 
     299             :   // Does not take cartoon BC
     300             :   CartoonCylinderOptionsHelper(
     301             :       std::array<double, 2> lower_bounds, std::array<double, 2> upper_bounds,
     302             :       std::array<size_t, 2> initial_refinement_levels,
     303             :       std::array<size_t, 2> initial_num_points,
     304             :       std::array<CoordinateMaps::Distribution, 2> distributions,
     305             :       std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
     306             :           time_dependence = nullptr,
     307             :       std::array<std::array<std::unique_ptr<
     308             :                                 domain::BoundaryConditions::BoundaryCondition>,
     309             :                             2>,
     310             :                  2>
     311             :           boundary_conditions = {},
     312             :       Options::Context context = {});
     313             : 
     314             :   template <typename BoundaryConditionsBase>
     315             :   CartoonCylinderOptionsHelper(
     316             :       std::array<double, 2> lower_bounds, std::array<double, 2> upper_bounds,
     317             :       std::array<size_t, 2> initial_refinement_levels,
     318             :       std::array<size_t, 2> initial_num_points,
     319             :       std::array<CoordinateMaps::Distribution, 2> distributions,
     320             :       std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
     321             :           time_dependence = nullptr,
     322             :       std::array<
     323             :           std::variant<std::unique_ptr<BoundaryConditionsBase>,
     324             :                        LowerUpperBoundaryCondition<BoundaryConditionsBase>>,
     325             :           2>
     326             :           boundary_conditions = {},
     327             :       Options::Context context = {})
     328             :       : CartoonCylinderOptionsHelper(
     329             :             std::move(lower_bounds), std::move(upper_bounds),
     330             :             std::move(initial_refinement_levels), std::move(initial_num_points),
     331             :             std::move(distributions), std::move(time_dependence),
     332             :             domain::creators::CartoonCylinder::transform_boundary_conditions(
     333             :                 std::move(boundary_conditions)),
     334             :             std::move(context)) {}
     335             :   // Same members as in CartoonCylinder; public, to be extracted
     336             :   std::array<double, 2> lower_bounds_{};
     337             :   std::array<double, 2> upper_bounds_{};
     338             :   std::array<size_t, 2> initial_refinement_levels_{};
     339             :   std::array<size_t, 2> initial_num_points_{};
     340             :   std::array<CoordinateMaps::Distribution, 2> distributions_{};
     341             :   std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
     342             :       time_dependence_{nullptr};
     343             :   std::array<
     344             :       std::array<std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>,
     345             :                  2>,
     346             :       2>
     347             :       boundary_conditions_{};
     348             :   Options::Context context_{};
     349             : };
     350             : }  // namespace domain::creators::detail
     351             : 
     352             : // Options parsing specialization to automate CartoonCylinder's cartoon
     353             : // boundary condition
     354             : template <>
     355           0 : struct Options::create_from_yaml<domain::creators::CartoonCylinder> {
     356             :   template <typename Metavariables>
     357           0 :   static domain::creators::CartoonCylinder create(
     358             :       const Options::Option& options) {
     359             :     auto helper =
     360             :         options.parse_as<domain::creators::detail::CartoonCylinderOptionsHelper,
     361             :                          Metavariables>();
     362             : 
     363             :     // Create cartoon BC if system supports it, if not will throw parse error in
     364             :     // real constructor
     365             :     std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
     366             :         cartoon_boundary_condition = nullptr;
     367             :     if constexpr (domain::BoundaryConditions::has_boundary_conditions_base_v<
     368             :                       typename Metavariables::system>) {
     369             :       if constexpr (domain::BoundaryConditions::system_has_cartoon_bc_v<
     370             :                         Metavariables>) {
     371             :         cartoon_boundary_condition =
     372             :             domain::BoundaryConditions::make_cartoon_boundary_condition<
     373             :                 Metavariables>();
     374             :       }
     375             :     }
     376             : 
     377             :     // Construct CartoonCylinder using the helper's parsed data + cartoon BC
     378             :     return domain::creators::CartoonCylinder(
     379             :         helper.lower_bounds_, helper.upper_bounds_,
     380             :         helper.initial_refinement_levels_, helper.initial_num_points_,
     381             :         helper.distributions_, std::move(helper.time_dependence_),
     382             :         std::move(helper.boundary_conditions_),
     383             :         std::move(cartoon_boundary_condition), helper.context_);
     384             :   }
     385             : };

Generated by: LCOV version 1.14