SpECTRE Documentation Coverage Report
Current view: top level - Domain/Creators/TimeDependentOptions - BinaryCompactObject.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 24.6 % 61 15
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 <limits>
       8              : #include <memory>
       9              : #include <string>
      10              : #include <type_traits>
      11              : #include <unordered_map>
      12              : 
      13              : #include "Domain/CoordinateMaps/CoordinateMap.hpp"
      14              : #include "Domain/CoordinateMaps/Identity.hpp"
      15              : #include "Domain/CoordinateMaps/TimeDependent/CubicScale.hpp"
      16              : #include "Domain/CoordinateMaps/TimeDependent/RotScaleTrans.hpp"
      17              : #include "Domain/CoordinateMaps/TimeDependent/Rotation.hpp"
      18              : #include "Domain/CoordinateMaps/TimeDependent/Shape.hpp"
      19              : #include "Domain/CoordinateMaps/TimeDependent/ShapeMapTransitionFunctions/ShapeMapTransitionFunction.hpp"
      20              : #include "Domain/CoordinateMaps/TimeDependent/Skew.hpp"
      21              : #include "Domain/Creators/TimeDependentOptions/ExpansionMap.hpp"
      22              : #include "Domain/Creators/TimeDependentOptions/GridCenters.hpp"
      23              : #include "Domain/Creators/TimeDependentOptions/RotationMap.hpp"
      24              : #include "Domain/Creators/TimeDependentOptions/ShapeMap.hpp"
      25              : #include "Domain/Creators/TimeDependentOptions/SkewMap.hpp"
      26              : #include "Domain/Creators/TimeDependentOptions/TranslationMap.hpp"
      27              : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
      28              : #include "Domain/Structure/ObjectLabel.hpp"
      29              : #include "Options/Auto.hpp"
      30              : #include "Options/Context.hpp"
      31              : #include "Options/Options.hpp"
      32              : #include "Options/String.hpp"
      33              : #include "Utilities/GetOutput.hpp"
      34              : #include "Utilities/TMPL.hpp"
      35              : 
      36              : /// \cond
      37              : namespace Frame {
      38              : struct Grid;
      39              : struct Distorted;
      40              : struct Inertial;
      41              : }  // namespace Frame
      42              : /// \endcond
      43              : 
      44              : /// Namespace used to hold things used in both the BinaryCompactObject and
      45              : /// CylindricalBinaryCompactObject domain creators.
      46              : namespace domain::creators::bco {
      47              : namespace detail {
      48              : // Convenience type alias
      49              : template <typename... Maps>
      50              : using gi_map = domain::CoordinateMap<Frame::Grid, Frame::Inertial, Maps...>;
      51              : template <typename... Maps>
      52              : using gd_map = domain::CoordinateMap<Frame::Grid, Frame::Distorted, Maps...>;
      53              : template <typename... Maps>
      54              : using di_map =
      55              :     domain::CoordinateMap<Frame::Distorted, Frame::Inertial, Maps...>;
      56              : 
      57              : template <typename List>
      58              : struct power_set {
      59              :   using rest = typename power_set<tmpl::pop_front<List>>::type;
      60              :   using type = tmpl::append<
      61              :       rest, tmpl::transform<rest, tmpl::lazy::push_front<
      62              :                                       tmpl::_1, tmpl::pin<tmpl::front<List>>>>>;
      63              : };
      64              : 
      65              : template <>
      66              : struct power_set<tmpl::list<>> {
      67              :   using type = tmpl::list<tmpl::list<>>;
      68              : };
      69              : 
      70              : template <typename SourceFrame, typename TargetFrame, typename Maps>
      71              : using produce_all_maps_helper =
      72              :     tmpl::wrap<tmpl::push_front<Maps, SourceFrame, TargetFrame>,
      73              :                domain::CoordinateMap>;
      74              : 
      75              : /*
      76              :  * This will produce all the possible combinations of maps we will need for the
      77              :  * maps_list. It does so using a power set. Say you have 3 maps, Map1, Map2,
      78              :  * Map3. The end result of this will be a list with the following map
      79              :  * combinations where these combinations may not appear in the same position in
      80              :  * the list, but the order of each combination is fixed:
      81              :  *  - Map1
      82              :  *  - Map2
      83              :  *  - Map3
      84              :  *  - Map1, Map2
      85              :  *  - Map1, Map3
      86              :  *  - Map2, Map3
      87              :  *  - Map1, Map2, Map3
      88              :  */
      89              : template <typename SourceFrame, typename TargetFrame, typename... Maps>
      90              : using produce_all_maps = tmpl::transform<
      91              :     tmpl::remove<typename power_set<tmpl::list<Maps...>>::type, tmpl::list<>>,
      92              :     tmpl::bind<produce_all_maps_helper, tmpl::pin<SourceFrame>,
      93              :                tmpl::pin<TargetFrame>, tmpl::_1>>;
      94              : }  // namespace detail
      95              : 
      96              : /*!
      97              :  * \brief This holds all options related to the time dependent maps of the
      98              :  * binary compact object domains.
      99              :  *
     100              :  * \details Since both domains will have the same (overall) time dependent maps,
     101              :  * their options are going to be the same as well. The options won't be exactly
     102              :  * the same though, so there is a \p IsCylindrical template parameter to
     103              :  * distinguish.
     104              :  *
     105              :  * This class will create the FunctionsOfTime needed for the binary compact
     106              :  * object domains as well as the actual CoordinateMap%s themselves
     107              :  *
     108              :  * \note This struct contains no information about what blocks the time
     109              :  * dependent maps will go in.
     110              :  */
     111              : template <bool IsCylindrical>
     112            1 : struct TimeDependentMapOptions {
     113              :  private:
     114              :   template <typename SourceFrame, typename TargetFrame>
     115            0 :   using MapType =
     116              :       std::unique_ptr<domain::CoordinateMapBase<SourceFrame, TargetFrame, 3>>;
     117              :   // Time-dependent maps
     118            0 :   using Expansion = domain::CoordinateMaps::TimeDependent::CubicScale<3>;
     119            0 :   using Rotation = domain::CoordinateMaps::TimeDependent::Rotation<3>;
     120            0 :   using RotScaleTrans = domain::CoordinateMaps::TimeDependent::RotScaleTrans<3>;
     121            0 :   using Skew = domain::CoordinateMaps::TimeDependent::Skew;
     122            0 :   using Shape = domain::CoordinateMaps::TimeDependent::Shape;
     123            0 :   using Identity = domain::CoordinateMaps::Identity<3>;
     124              : 
     125              :  public:
     126            0 :   using maps_list = tmpl::append<
     127              :       // We need this odd-one-out Identity map because all maps are optional to
     128              :       // specify. It's possible to specify a shape map, but no expansion or
     129              :       // rotation map. So we have a grid to distorted map, and need an identity
     130              :       // distorted to inertial map. We don't need an identity grid to distorted
     131              :       // map because if a user requests the grid to distorted frame map with a
     132              :       // distorted frame, but didn't specify shape map options, an error occurs.
     133              :       tmpl::list<detail::di_map<Identity>>,
     134              :       detail::produce_all_maps<Frame::Grid, Frame::Inertial, Shape, Expansion,
     135              :                                Rotation>,
     136              :       detail::produce_all_maps<Frame::Grid, Frame::Distorted, Shape>,
     137              :       detail::produce_all_maps<Frame::Distorted, Frame::Inertial, Expansion,
     138              :                                Rotation>,
     139              :       detail::produce_all_maps<Frame::Grid, Frame::Inertial, Shape,
     140              :                                RotScaleTrans>,
     141              :       detail::produce_all_maps<Frame::Grid, Frame::Inertial, Shape, Skew,
     142              :                                RotScaleTrans>,
     143              :       detail::produce_all_maps<Frame::Distorted, Frame::Inertial,
     144              :                                RotScaleTrans>,
     145              :       detail::produce_all_maps<Frame::Distorted, Frame::Inertial, Skew,
     146              :                                RotScaleTrans>>;
     147              : 
     148              :   /// \brief The initial time of the functions of time.
     149            1 :   struct InitialTime {
     150            0 :     using type = double;
     151            0 :     static constexpr Options::String help = {
     152              :         "The initial time of the functions of time"};
     153              :   };
     154              : 
     155              :   /// \brief Options for the expansion map.
     156              :   /// The outer boundary radius of the map is always set to
     157              :   /// the outer boundary of the Domain, so there is no option
     158              :   /// here to set the outer boundary radius.
     159            1 :   using ExpansionMapOptions =
     160              :       domain::creators::time_dependent_options::ExpansionMapOptions<false>;
     161            0 :   using ExpansionMapOptionType = typename ExpansionMapOptions::type::value_type;
     162              : 
     163              :   /// \brief Options for the rotation map
     164            1 :   using RotationMapOptions =
     165              :       domain::creators::time_dependent_options::RotationMapOptions<false>;
     166            0 :   using RotationMapOptionType = typename RotationMapOptions::type::value_type;
     167              : 
     168              :   /// \brief Options for the Translation Map, the outer radius is always set to
     169              :   /// the outer boundary of the Domain, so there's no option needed for outer
     170              :   /// boundary.
     171            1 :   using TranslationMapOptions =
     172              :       domain::creators::time_dependent_options::TranslationMapOptions<3>;
     173            0 :   using TranslationMapOptionType =
     174              :       typename TranslationMapOptions::type::value_type;
     175              : 
     176              :   /// \brief Options for the Skew map
     177            1 :   using SkewMapOptions =
     178              :       domain::creators::time_dependent_options::SkewMapOptions;
     179            0 :   using SkewMapOptionType = typename SkewMapOptions::type::value_type;
     180              : 
     181              :   /// \brief Options for the shape map
     182              :   template <domain::ObjectLabel Object>
     183            1 :   using ShapeMapOptions =
     184              :       domain::creators::time_dependent_options::ShapeMapOptions<
     185              :           not IsCylindrical, Object>;
     186              :   template <domain::ObjectLabel Object>
     187            0 :   using ShapeMapOptionType = typename ShapeMapOptions<Object>::type::value_type;
     188              : 
     189              :   /// \brief Options for tracking the grid centers.
     190              :   ///
     191              :   /// This is only used in binary neutron star simulations right now.
     192            1 :   using GridCentersOptions = time_dependent_options::GridCentersOptions;
     193            0 :   using GridCentersOptionType =
     194              :       typename GridCentersOptions::type::value_type;
     195              : 
     196            0 :   using options =
     197              :       tmpl::list<InitialTime, ExpansionMapOptions, RotationMapOptions,
     198              :                  TranslationMapOptions, SkewMapOptions,
     199              :                  ShapeMapOptions<domain::ObjectLabel::A>,
     200              :                  ShapeMapOptions<domain::ObjectLabel::B>, GridCentersOptions>;
     201            0 :   static constexpr Options::String help{
     202              :       "The options for all time dependent maps in a binary compact object "
     203              :       "domain. Specify 'None' to not use any time dependent maps."};
     204              : 
     205            0 :   TimeDependentMapOptions() = default;
     206              : 
     207            0 :   TimeDependentMapOptions(
     208              :       double initial_time, ExpansionMapOptionType expansion_map_options,
     209              :       RotationMapOptionType rotation_map_options,
     210              :       TranslationMapOptionType translation_map_options,
     211              :       SkewMapOptionType skew_map_options,
     212              :       ShapeMapOptionType<domain::ObjectLabel::A> shape_options_A,
     213              :       ShapeMapOptionType<domain::ObjectLabel::B> shape_options_B,
     214              :       GridCentersOptionType grid_centers,
     215              :       const Options::Context& context = {});
     216              : 
     217              :   /*!
     218              :    * \brief Create the function of time map using the options that were
     219              :    * provided to this class.
     220              :    *
     221              :    * Currently, this will add:
     222              :    *
     223              :    * - Skew: `PiecewisePolynomial<2>`
     224              :    * - Expansion: `PiecewisePolynomial<2>`
     225              :    * - ExpansionOuterBoundary: `FixedSpeedCubic`
     226              :    * - Rotation: `QuaternionFunctionOfTime<3>`
     227              :    * - Translation: `PiecewisePolynomial<3>`
     228              :    * - SizeA/B: `PiecewisePolynomial<3>`
     229              :    * - ShapeA/B: `PiecewisePolynomial<2>`
     230              :    * - GridCenters: `PiecewisePolynomial<2>`
     231              :    *
     232              :    *  When `UseWorldtube` is set to true, they are
     233              :    *
     234              :    * - Skew: None
     235              :    * - Expansion: `IntegratedFunctionOfTime`
     236              :    * - ExpansionOuterBoundary: `FixedSpeedCubic`
     237              :    * - Rotation: `IntegratedFunctionOfTime`
     238              :    * - Translation: None
     239              :    * - SizeA/B: IntegratedFunctionOfTime
     240              :    * - ShapeA/B: `PiecewisePolynomial<2>`
     241              :    */
     242              :   template <bool UseWorldtube = false>
     243              :   std::unordered_map<std::string,
     244              :                      std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>
     245            1 :   create_functions_of_time(const std::unordered_map<std::string, double>&
     246              :                                initial_expiration_times) const;
     247              : 
     248              :   /*!
     249              :    * \brief Construct the actual maps that will be used.
     250              :    *
     251              :    * Currently, this constructs a:
     252              :    *
     253              :    * - Skew: `domain::CoordinateMaps::TimeDependent::Skew`
     254              :    * - Rotation, Expansion, Translation: `RotScaleTrans<3>`
     255              :    * - ShapeA/B: `Shape` (with size FunctionOfTime)
     256              :    *
     257              :    * If the radii for an object are `std::nullopt`, this means that a Shape map
     258              :    * is not constructed for that object. An identity map will be used instead.
     259              :    * This happens when the object is covered by a Cartesian cube, rather than a
     260              :    * sphere.
     261              :    * If \p IsCylindrical is true, only pass two radii for the inner/outer radius
     262              :    * of the object sphere. If it is false, pass three radii corresponding to the
     263              :    * excision radius, the outer radius of the inner sphere, and the radius of
     264              :    * the surrounding cube.
     265              :    *
     266              :    * If a shape map is requested and the object is excised, then the shape map
     267              :    * will deform the inner excision surface of the object. This deformation
     268              :    * either extends to the outer radius of the sphere, or further to the edge of
     269              :    * the cube that surrounds the sphere, depending on the `TransitionEndsAtCube`
     270              :    * option.
     271              :    * If the object is filled, then the shape map will deform the outer radius of
     272              :    * the sphere that covers the object and the `TransitionEndsAtCube` option
     273              :    * must be `true`.
     274              :    */
     275            1 :   void build_maps(
     276              :       const std::array<std::array<double, 3>, 2>& object_centers,
     277              :       const std::optional<std::array<double, 3>>& cube_A_center,
     278              :       const std::optional<std::array<double, 3>>& cube_B_center,
     279              :       const std::array<double, 3>& center_of_mass,
     280              :       const std::optional<std::array<double, IsCylindrical ? 2 : 3>>&
     281              :           object_A_radii,
     282              :       const std::optional<std::array<double, IsCylindrical ? 2 : 3>>&
     283              :           object_B_radii,
     284              :       bool object_A_filled, bool object_B_filled, double envelope_radius,
     285              :       double domain_outer_radius);
     286              : 
     287              :   /*!
     288              :    * \brief Check whether options were specified in the constructor for the
     289              :    * shape map of this object
     290              :    */
     291            1 :   bool has_distorted_frame_options(domain::ObjectLabel object) const;
     292              : 
     293              :   /*!
     294              :    * \brief Type to pass to `grid_to_distorted_map()` and
     295              :    * `grid_to_inertial_map()`.
     296              :    *
     297              :    * \details If \p IsCylindrical is true, pass a `bool` for whether to include
     298              :    * a shape map or not. If it's false, pass a `std::optional<size_t>`. If this
     299              :    * has a value, then it includes a shape map. The `size_t` represents the
     300              :    * relative block number around each object in the BinaryCompactObject domain.
     301              :    * It should go from 0 to 11 for the 12 blocks surrounding each object.
     302              :    */
     303            1 :   using IncludeDistortedMapType =
     304              :       tmpl::conditional_t<IsCylindrical, bool, std::optional<size_t>>;
     305              : 
     306              :   /*!
     307              :    * \brief This will construct the map from `Frame::Distorted` to
     308              :    * `Frame::Inertial`
     309              :    *
     310              :    * If we are including a shape map, then this will be a `RotScaleTrans` map.
     311              :    * If we aren't, this returns a `nullptr`.
     312              :    *
     313              :    * \see IncludeDistortedMapType
     314              :    */
     315              :   template <domain::ObjectLabel Object>
     316            1 :   MapType<Frame::Distorted, Frame::Inertial> distorted_to_inertial_map(
     317              :       const IncludeDistortedMapType& include_distorted_map,
     318              :       bool use_rigid_map) const;
     319              : 
     320              :   /*!
     321              :    * \brief This will construct the maps from the `Frame::Grid` to the
     322              :    * `Frame::Distorted`.
     323              :    *
     324              :    * If we are including a shape map, then this will be a `Shape` map (with size
     325              :    * FunctionOfTime) for the templated `Object`. If we aren't, then this returns
     326              :    * a `nullptr`.
     327              :    *
     328              :    * \see IncludeDistortedMapType
     329              :    */
     330              :   template <domain::ObjectLabel Object>
     331            1 :   MapType<Frame::Grid, Frame::Distorted> grid_to_distorted_map(
     332              :       const IncludeDistortedMapType& include_distorted_map) const;
     333              : 
     334              :   /*!
     335              :    * \brief This will construct the entire map from the `Frame::Grid` to the
     336              :    * `Frame::Inertial`.
     337              :    *
     338              :    * If we are including a shape map, then this map will have a composition of a
     339              :    * `Shape` (with size FunctionOfTime) and `RotScaleTrans` map. If
     340              :    * not, there will only be a `RotScaleTrans` map.
     341              :    *
     342              :    * If \p return_excision_map is true, this will use a special shape map within
     343              :    * the excision. Also if \p return_excision_map is true, then
     344              :    * \p include_distorted_map must be either 'true' (if \p IsCylindrical is
     345              :    * true) or have a value less than 6, but it doesn't matter what value
     346              :    * (because inside the excision isn't a specific block).
     347              :    *
     348              :    * \see IncludeDistortedMapType
     349              :    */
     350              :   template <domain::ObjectLabel Object>
     351            1 :   MapType<Frame::Grid, Frame::Inertial> grid_to_inertial_map(
     352              :       const IncludeDistortedMapType& include_distorted_map, bool use_rigid_map,
     353              :       bool return_excision_map = false) const;
     354              : 
     355              :   // Names are public because they need to be used when constructing maps in the
     356              :   // BCO domain creators themselves
     357            0 :   inline static const std::string expansion_name{"Expansion"};
     358            0 :   inline static const std::string expansion_outer_boundary_name{
     359              :       "ExpansionOuterBoundary"};
     360            0 :   inline static const std::string rotation_name{"Rotation"};
     361            0 :   inline static const std::string translation_name{"Translation"};
     362            0 :   inline static const std::string skew_name{"Skew"};
     363            0 :   inline static const std::array<std::string, 2> size_names{{"SizeA", "SizeB"}};
     364            0 :   inline static const std::array<std::string, 2> shape_names{
     365              :       {"ShapeA", "ShapeB"}};
     366            0 :   inline static const std::string grid_centers_name{"GridCenters"};
     367              : 
     368              :  private:
     369            0 :   static size_t get_index(domain::ObjectLabel object);
     370              : 
     371            0 :   double initial_time_{std::numeric_limits<double>::signaling_NaN()};
     372            0 :   ExpansionMapOptionType expansion_map_options_;
     373            0 :   RotationMapOptionType rotation_map_options_;
     374            0 :   TranslationMapOptionType translation_map_options_;
     375            0 :   SkewMapOptionType skew_map_options_;
     376            0 :   ShapeMapOptionType<domain::ObjectLabel::A> shape_options_A_{};
     377            0 :   ShapeMapOptionType<domain::ObjectLabel::B> shape_options_B_{};
     378            0 :   GridCentersOptionType grid_centers_options_{};
     379            0 :   std::array<std::optional<double>, 2> deformed_radii_{};
     380              : 
     381              :   // Maps
     382            0 :   std::optional<Expansion> expansion_map_{};
     383            0 :   std::optional<Rotation> rotation_map_{};
     384            0 :   std::optional<std::pair<RotScaleTrans, RotScaleTrans>> rot_scale_trans_map_{};
     385            0 :   std::optional<Skew> skew_map_{};
     386            0 :   using ShapeMapType =
     387              :       tmpl::conditional_t<IsCylindrical, std::array<std::optional<Shape>, 4>,
     388              :                           std::array<std::array<std::optional<Shape>, 13>, 2>>;
     389            0 :   ShapeMapType shape_maps_{};
     390              : 
     391              :   // helper function that creates the functions of time used by the worldtube
     392              :   std::unordered_map<std::string,
     393              :                      std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>
     394            0 :   create_worldtube_functions_of_time() const;
     395              : };
     396              : }  // namespace domain::creators::bco
        

Generated by: LCOV version 2.0-1