SpECTRE Documentation Coverage Report
Current view: top level - Domain/Creators - CartoonSphere2D.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 9.5 % 74 7
Test Date: 2026-10-22 17:29:42
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 <unordered_set>
      12              : #include <variant>
      13              : #include <vector>
      14              : 
      15              : #include "Domain/BoundaryConditions/BoundaryCondition.hpp"
      16              : #include "Domain/BoundaryConditions/Cartoon.hpp"
      17              : #include "Domain/BoundaryConditions/GetBoundaryConditionsBase.hpp"
      18              : #include "Domain/CoordinateMaps/Distribution.hpp"
      19              : #include "Domain/Creators/DomainCreator.hpp"
      20              : #include "Domain/Creators/Sphere.hpp"
      21              : #include "Domain/Creators/TimeDependence/TimeDependence.hpp"
      22              : #include "Domain/Domain.hpp"
      23              : #include "Domain/Structure/DirectionMap.hpp"
      24              : #include "Options/Context.hpp"
      25              : #include "Options/String.hpp"
      26              : #include "Utilities/TMPL.hpp"
      27              : 
      28              : /// \cond
      29              : namespace domain {
      30              : namespace CoordinateMaps {
      31              : class Affine;
      32              : class Equiangular;
      33              : template <size_t Dim>
      34              : class Identity;
      35              : template <typename Map1, typename Map2>
      36              : class ProductOf2Maps;
      37              : template <typename Map1, typename Map2, typename Map3>
      38              : class ProductOf3Maps;
      39              : template <size_t Dim>
      40              : class Wedge;
      41              : template <size_t Dim>
      42              : class DiscreteRotation;
      43              : }  // namespace CoordinateMaps
      44              : 
      45              : template <typename SourceFrame, typename TargetFrame, typename... Maps>
      46              : class CoordinateMap;
      47              : }  // namespace domain
      48              : /// \endcond
      49              : 
      50              : namespace domain::creators::detail {
      51              : /// Options for filling the interior of the disk with a square
      52              : struct InnerSquare {
      53              :   static constexpr Options::String help = {
      54              :       "Fill the interior of the 2D sphere with a half-square."};
      55              :   struct Sphericity {
      56              :     static std::string name() { return "FillWithSphericity"; }
      57              :     using type = double;
      58              :     static constexpr Options::String help = {
      59              :         "Sphericity of the inner half-square. Only a sphericity of "
      60              :         "0.0 is currently implemented."};
      61              :     static double lower_bound() { return 0.0; }
      62              :     static double upper_bound() { return 0.0; }
      63              :   };
      64              :   using options = tmpl::list<Sphericity>;
      65              :   InnerSquare() = default;
      66              :   explicit InnerSquare(double sphericity_in) : sphericity(sphericity_in) {}
      67              :   double sphericity = std::numeric_limits<double>::signaling_NaN();
      68              : };
      69              : }  // namespace domain::creators::detail
      70              : 
      71              : namespace domain::creators {
      72              : /// Create a 3D Domain with a half-disk computational domain employing axial
      73              : /// symmetry. The third dimension uses a Cartoon basis with Killing vector
      74              : /// along the $\phi$ direction.
      75            1 : class CartoonSphere2D : public DomainCreator<3> {
      76              :  public:
      77            0 :   using maps_list = tmpl::list<
      78              :       domain::CoordinateMap<
      79              :           Frame::BlockLogical, Frame::Inertial,
      80              :           CoordinateMaps::ProductOf2Maps<
      81              :               CoordinateMaps::ProductOf2Maps<CoordinateMaps::Affine,
      82              :                                              CoordinateMaps::Affine>,
      83              :               CoordinateMaps::Identity<1>>>,
      84              :       domain::CoordinateMap<
      85              :           Frame::BlockLogical, Frame::Inertial,
      86              :           CoordinateMaps::ProductOf2Maps<
      87              :               CoordinateMaps::ProductOf2Maps<CoordinateMaps::Equiangular,
      88              :                                              CoordinateMaps::Equiangular>,
      89              :               CoordinateMaps::Identity<1>>>,
      90              :       domain::CoordinateMap<
      91              :           Frame::BlockLogical, Frame::Inertial,
      92              :           CoordinateMaps::DiscreteRotation<3>,
      93              :           CoordinateMaps::ProductOf2Maps<CoordinateMaps::Wedge<2>,
      94              :                                          CoordinateMaps::Identity<1>>>>;
      95              : 
      96            0 :   struct InnerRadius {
      97            0 :     using type = double;
      98            0 :     static constexpr Options::String help = {
      99              :         "Radius of the circle circumscribing the inner half-square, or the "
     100              :         "radius of the inner boundary if ExciseCenter = true."};
     101              :   };
     102              : 
     103            0 :   struct OuterRadius {
     104            0 :     using type = double;
     105            0 :     static constexpr Options::String help = {"Outer radius of the half-disk."};
     106              :   };
     107              : 
     108            0 :   struct InitialAngularRefinement {
     109            0 :     using type = size_t;
     110            0 :     static constexpr Options::String help = {
     111              :         "Initial refinement level in theta. It will be applied to all "
     112              :         "blocks because h-refinement is not supported for the ZernikeB1 "
     113              :         "basis.\n"
     114              :         "Note: the half-wedges will have their theta values decremented by "
     115              :         "one.\n"
     116              :         "Note: the inner square, if included, will have refinement set to "
     117              :         "the theta value for the center half-circle for both dimensions "
     118              :         "(decremented by one in the halved dimension)."};
     119              :   };
     120              : 
     121            0 :   struct InitialRadialRefinement {
     122            0 :     using type = std::variant<size_t, std::vector<size_t>>;
     123            0 :     static constexpr Options::String help = {
     124              :         "Initial refinement level in r. If one value is given, it will be "
     125              :         "applied to all blocks, otherwise each shell can be specificed, "
     126              :         "from innermost to outermost.\n"};
     127              :   };
     128              : 
     129            0 :   struct InitialGridPoints {
     130            0 :     using type = std::array<size_t, 2>;
     131            0 :     static constexpr Options::String help = {
     132              :         "Initial number of grid points in [r,theta]. It will be applied to all "
     133              :         "blocks because p-refinement is not supported for the ZernikeB1 "
     134              :         "basis.\n"
     135              :         "Note: if included, the inner square will have both dimensions'"
     136              :         "number of grid points set to the theta value of the surrounding "
     137              :         "wedges."};
     138              :   };
     139              : 
     140            0 :   struct RadialPartitioning {
     141            0 :     using type = std::vector<double>;
     142            0 :     static constexpr Options::String help = {
     143              :         "Radial coordinates of the boundaries splitting the radial shells. "
     144              :         "Leave empty for only one layer."};
     145              :   };
     146              : 
     147            0 :   struct UseEquiangularMap {
     148            0 :     using type = bool;
     149            0 :     static constexpr Options::String help = {
     150              :         "Use equiangular instead of equidistant coordinates in wedges."};
     151              :   };
     152              : 
     153            0 :   using Excision = detail::Excision;
     154            0 :   using InnerSquare = detail::InnerSquare;
     155              : 
     156            0 :   struct Interior {
     157            0 :     using type = std::variant<Excision, InnerSquare>;
     158            0 :     static constexpr Options::String help = {
     159              :         "Specify 'ExciseWithBoundaryCondition' and a boundary condition to "
     160              :         "excise the interior of the sphere, leaving a spherical shell "
     161              :         "(or just 'Excise' if boundary conditions are disabled). "
     162              :         "Or specify 'FillWithSphericity' to fill the interior."};
     163              :   };
     164              : 
     165              :   template <typename BoundaryConditionsBase>
     166            0 :   struct OuterBoundaryCondition {
     167            0 :     using type = std::unique_ptr<BoundaryConditionsBase>;
     168            0 :     static constexpr Options::String help = {
     169              :         "The boundary condition to impose at the outer boundary of the "
     170              :         "domain."};
     171              :   };
     172              : 
     173            0 :   struct RadialDistribution {
     174            0 :     using type = std::variant<CoordinateMaps::Distribution,
     175              :                               std::vector<CoordinateMaps::Distribution>>;
     176            0 :     static constexpr Options::String help = {
     177              :         "Distribution of grid points for the radial direction of the wedges. "
     178              :         "A single value will be applied to all shells, or every shell can be "
     179              :         "specified individually, in which case for N partitions there must be "
     180              :         "N+1 distributions. For anything but linear in the innermost shell, "
     181              :         "the center must be excised."};
     182              :   };
     183              : 
     184            0 :   struct TimeDependence {
     185            0 :     using type =
     186              :         std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>;
     187            0 :     static constexpr Options::String help = {
     188              :         "The time dependence of the moving mesh domain. Specify `None` for no "
     189              :         "time dependant maps."};
     190              :   };
     191              : 
     192            0 :   using basic_options =
     193              :       tmpl::list<InnerRadius, OuterRadius, InitialAngularRefinement,
     194              :                  InitialRadialRefinement, InitialGridPoints, RadialPartitioning,
     195              :                  UseEquiangularMap, Interior, RadialDistribution,
     196              :                  TimeDependence>;
     197              : 
     198              :   template <typename Metavariables>
     199            0 :   using options = tmpl::conditional_t<
     200              :       domain::BoundaryConditions::has_boundary_conditions_base_v<
     201              :           typename Metavariables::system>,
     202              :       tmpl::push_back<
     203              :           basic_options,
     204              :           OuterBoundaryCondition<
     205              :               domain::BoundaryConditions::get_boundary_conditions_base<
     206              :                   typename Metavariables::system>>>,
     207              :       basic_options>;
     208              : 
     209            0 :   static constexpr Options::String help{
     210              :       "Creates a sphere that requires/enforces axial-symmetry.\n"
     211              :       "The computational domain is a 2D half-disk, consisting of an inner\n"
     212              :       "half-square with two half-wedges above and below and a full wedge to\n"
     213              :       "the right. This can be extended to have mulitple shells of wedges by\n"
     214              :       "specifying a radial partition. The inner half-square can be excised,\n"
     215              :       "in which case the inner sphericity is set to 1.\n"
     216              :       "Equiangular coordinates give better gridpoint spacings in the angular\n"
     217              :       "direction, while equidistant coordinates give better gridpoint\n"
     218              :       "spacings in the center half-square.\n"
     219              :       "Elements touching the x=0 axis use ZernikeB1 bases in the x direction\n"
     220              :       "and automatically apply a system's Cartoon-type boundary condition.\n"
     221              :       "Angular refinement must be globally set as the required mortar\n"
     222              :       "projection has not been implemented."};
     223              : 
     224            0 :   CartoonSphere2D(
     225              :       double inner_radius, double outer_radius,
     226              :       size_t initial_angular_refinement,
     227              :       const typename InitialRadialRefinement::type& initial_radial_refinement,
     228              :       std::array<size_t, 2> initial_number_of_grid_points,
     229              :       std::vector<double> radial_partitioning, bool use_equiangular_map,
     230              :       std::variant<Excision, InnerSquare> interior,
     231              :       const typename RadialDistribution::type& radial_distribution,
     232              :       std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
     233              :           time_dependence,
     234              :       std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
     235              :           outer_boundary_condition,
     236              :       std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
     237              :           cartoon_boundary_condition,
     238              :       const Options::Context& context);
     239              : 
     240            0 :   CartoonSphere2D() = default;
     241            0 :   CartoonSphere2D(const CartoonSphere2D&) = delete;
     242            0 :   CartoonSphere2D(CartoonSphere2D&&) = default;
     243            0 :   CartoonSphere2D& operator=(const CartoonSphere2D&) = delete;
     244            0 :   CartoonSphere2D& operator=(CartoonSphere2D&&) = default;
     245            0 :   ~CartoonSphere2D() override = default;
     246              : 
     247            0 :   Domain<3> create_domain() const override;
     248              : 
     249              :   std::vector<DirectionMap<
     250              :       3, std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>>>
     251            1 :   external_boundary_conditions() const override;
     252              : 
     253            1 :   std::vector<std::array<size_t, 3>> initial_extents() const override;
     254              : 
     255            1 :   std::vector<std::array<size_t, 3>> initial_refinement_levels() const override;
     256              : 
     257              :   /// The block names are Shell0_LowerY, Shell0_UpperX, Shell0_UpperY,
     258              :   /// Shell1_LowerY, and so on. The naming and numbering goes from outer-most
     259              :   /// shell, starting from bottom and going counterclockwise, going to inside
     260              :   /// neighboring shell. If the center is included, the "center" half-circle
     261              :   /// follows same numbering with the _HalfSquare being the last block.
     262            1 :   std::vector<std::string> block_names() const override { return block_names_; }
     263              : 
     264              :   /// The block groups are Shell0, Shell1, ... starting from the outermost
     265              :   /// partition and working in.
     266              :   std::unordered_map<std::string, std::unordered_set<std::string>>
     267            1 :   block_groups() const override {
     268              :     return block_groups_;
     269              :   }
     270              : 
     271            1 :   auto functions_of_time(const std::unordered_map<std::string, double>&
     272              :                              initial_expiration_times = {}) const
     273              :       -> std::unordered_map<
     274              :           std::string,
     275              :           std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>> override;
     276              : 
     277              :  private:
     278            0 :   double inner_radius_{};
     279            0 :   double outer_radius_{};
     280            0 :   size_t initial_angular_refinement_{};
     281            0 :   std::vector<size_t> initial_radial_refinement_{};
     282            0 :   std::array<size_t, 2> initial_number_of_grid_points_{};
     283            0 :   std::vector<double> radial_partitioning_{};
     284            0 :   bool use_equiangular_map_{false};
     285            0 :   std::variant<Excision, InnerSquare> interior_{};
     286            0 :   bool fill_interior_{false};
     287              :   std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
     288            0 :       time_dependence_ = nullptr;
     289            0 :   std::vector<CoordinateMaps::Distribution> radial_distributions_{};
     290              :   std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
     291            0 :       outer_boundary_condition_ = nullptr;
     292              :   std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
     293            0 :       cartoon_boundary_condition_ = nullptr;
     294            0 :   std::vector<std::string> block_names_;
     295              :   std::unordered_map<std::string, std::unordered_set<std::string>>
     296            0 :       block_groups_;
     297            0 :   size_t num_shells_{};
     298            0 :   size_t num_blocks_{};
     299              : };
     300              : }  // namespace domain::creators
     301              : 
     302              : namespace domain::creators::detail {
     303              : /// \brief Helper struct for CartoonSphere2D options parsing so the internal
     304              : /// cartoon boundary condition at $x = 0$ is not a required argument.
     305              : ///
     306              : /// \details To get the cartoon-type boundary condition from a system we need
     307              : /// access to the system's metavariables, which is only present when parsing
     308              : /// options. The point of this design is so that the input file does not require
     309              : /// a dummy value for an InnerBoundaryCondition that is always the same for a
     310              : /// given system.
     311              : ///
     312              : /// This helper's constructor does not take an InnerBoundaryCondition, which
     313              : /// means if we parse a CartoonSphere2D as a CartonSphere2DOptionsHelper
     314              : /// by having an options parsing specialization (so the input file values are
     315              : /// the helper's construtor, not CartoonSphere2D's), we can detect the
     316              : /// cartoon-type boundary condition for the given system and only then call the
     317              : /// CartoonSphere2D constructor with the extra information.
     318              : struct CartoonSphere2DOptionsHelper {
     319              :   // Inherit the options template from CartoonSphere2D
     320              :   template <typename Metavariables>
     321              :   using options = typename domain::creators::CartoonSphere2D::template options<
     322              :       Metavariables>;
     323              : 
     324              :   using InitialRadialRefinement =
     325              :       domain::creators::CartoonSphere2D::InitialRadialRefinement;
     326              :   using Interior = domain::creators::CartoonSphere2D::Interior;
     327              : 
     328              :   template <typename BoundaryConditionsBase>
     329              :   using OuterBoundaryCondition =
     330              :       domain::creators::CartoonSphere2D::OuterBoundaryCondition<
     331              :           BoundaryConditionsBase>;
     332              : 
     333              :   static constexpr Options::String help = {"CartoonSphere2DOptionsHelper."};
     334              : 
     335              :   // Default constructor required by Options system
     336              :   CartoonSphere2DOptionsHelper() = default;
     337              : 
     338              :   // Does not take cartoon BC
     339              :   CartoonSphere2DOptionsHelper(
     340              :       double inner_radius, double outer_radius,
     341              :       size_t initial_angular_refinement,
     342              :       typename InitialRadialRefinement::type&& initial_radial_refinement,
     343              :       std::array<size_t, 2> initial_number_of_grid_points,
     344              :       std::vector<double> radial_partitioning, bool use_equiangular_map,
     345              :       std::variant<Excision, InnerSquare> interior,
     346              :       typename domain::creators::CartoonSphere2D::RadialDistribution::type
     347              :           radial_distribution = CoordinateMaps::Distribution::Linear,
     348              :       std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
     349              :           time_dependence = nullptr,
     350              :       std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
     351              :           outer_boundary_condition = nullptr,
     352              :       Options::Context&& context = {});
     353              : 
     354              :   // Same members as in CartoonSphere2D; public, to be extracted
     355              :   double inner_radius_{std::numeric_limits<double>::signaling_NaN()};
     356              :   double outer_radius_{std::numeric_limits<double>::signaling_NaN()};
     357              :   size_t initial_angular_refinement_{0};
     358              :   typename InitialRadialRefinement::type initial_radial_refinement_{};
     359              :   std::array<size_t, 2> initial_number_of_grid_points_{};
     360              :   std::vector<double> radial_partitioning_{};
     361              :   bool use_equiangular_map_{false};
     362              :   typename Interior::type interior_{};
     363              :   typename domain::creators::CartoonSphere2D::RadialDistribution::type
     364              :       radial_distribution_{CoordinateMaps::Distribution::Linear};
     365              :   std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
     366              :       time_dependence_{nullptr};
     367              :   std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
     368              :       outer_boundary_condition_{nullptr};
     369              :   Options::Context context_{};
     370              : };
     371              : }  // namespace domain::creators::detail
     372              : 
     373              : // Options parsing specialization to automate CartoonSphere2D's cartoon
     374              : // boundary condition
     375              : template <>
     376            0 : struct Options::create_from_yaml<domain::creators::CartoonSphere2D> {
     377              :   template <typename Metavariables>
     378            0 :   static domain::creators::CartoonSphere2D create(
     379              :       const Options::Option& options) {
     380              :     auto helper =
     381              :         options.parse_as<domain::creators::detail::CartoonSphere2DOptionsHelper,
     382              :                          Metavariables>();
     383              : 
     384              :     // Create cartoon BC if system supports it, if not will throw parse error in
     385              :     // real constructor
     386              :     std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
     387              :         cartoon_boundary_condition = nullptr;
     388              :     if constexpr (domain::BoundaryConditions::has_boundary_conditions_base_v<
     389              :                       typename Metavariables::system>) {
     390              :       if constexpr (domain::BoundaryConditions::system_has_cartoon_bc_v<
     391              :                         Metavariables>) {
     392              :         cartoon_boundary_condition =
     393              :             domain::BoundaryConditions::make_cartoon_boundary_condition<
     394              :                 Metavariables>();
     395              :       }
     396              :     }
     397              : 
     398              :     // Construct CartoonSphere2D using the helper's parsed data + cartoon BC
     399              :     return domain::creators::CartoonSphere2D(
     400              :         helper.inner_radius_, helper.outer_radius_,
     401              :         helper.initial_angular_refinement_,
     402              :         std::move(helper.initial_radial_refinement_),
     403              :         std::move(helper.initial_number_of_grid_points_),
     404              :         std::move(helper.radial_partitioning_), helper.use_equiangular_map_,
     405              :         std::move(helper.interior_), helper.radial_distribution_,
     406              :         std::move(helper.time_dependence_),
     407              :         std::move(helper.outer_boundary_condition_),
     408              :         std::move(cartoon_boundary_condition), helper.context_);
     409              :   }
     410              : };
        

Generated by: LCOV version 2.0-1