SpECTRE Documentation Coverage Report
Current view: top level - Domain/Creators/TimeDependentOptions - ShapeMap.hpp Hit Total Coverage
Commit: 3ffcbc8ecf43797401b60bcca17d6040ee06f013 Lines: 10 113 8.8 %
Date: 2026-03-03 02:01:44
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 <limits>
       9             : #include <optional>
      10             : #include <string>
      11             : #include <variant>
      12             : 
      13             : #include "DataStructures/DataVector.hpp"
      14             : #include "Domain/Creators/TimeDependentOptions/FromVolumeFile.hpp"
      15             : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
      16             : #include "Domain/Structure/ObjectLabel.hpp"
      17             : #include "NumericalAlgorithms/SphericalHarmonics/IO/ReadSurfaceYlm.hpp"
      18             : #include "NumericalAlgorithms/SphericalHarmonics/Strahlkorper.hpp"
      19             : #include "Options/Auto.hpp"
      20             : #include "Options/Context.hpp"
      21             : #include "Options/String.hpp"
      22             : #include "Utilities/Gsl.hpp"
      23             : #include "Utilities/TMPL.hpp"
      24             : 
      25             : namespace domain::creators::time_dependent_options {
      26             : /*!
      27             :  * \brief Mass and spin necessary for calculating the \f$ Y_{lm} \f$
      28             :  * coefficients of a Kerr horizon of certain Boyer-Lindquist radius for the
      29             :  * shape map of the Sphere domain creator.
      30             :  */
      31           1 : struct KerrSchildFromBoyerLindquist {
      32             :   /// \brief The mass of the Kerr black hole.
      33           1 :   struct Mass {
      34           0 :     using type = double;
      35           0 :     static constexpr Options::String help = {"The mass of the Kerr BH."};
      36             :   };
      37             :   /// \brief The dimensionless spin of the Kerr black hole.
      38           1 :   struct Spin {
      39           0 :     using type = std::array<double, 3>;
      40           0 :     static constexpr Options::String help = {
      41             :         "The dim'less spin of the Kerr BH."};
      42             :   };
      43             : 
      44           0 :   using options = tmpl::list<Mass, Spin>;
      45             : 
      46           0 :   static constexpr Options::String help = {
      47             :       "Conform to an ellipsoid of constant Boyer-Lindquist radius in "
      48             :       "Kerr-Schild coordinates. This Boyer-Lindquist radius is chosen as the "
      49             :       "value of the 'InnerRadius'. To conform to the outer Kerr horizon, "
      50             :       "choose an 'InnerRadius' of r_+ = M + sqrt(M^2-a^2)."};
      51             : 
      52           0 :   KerrSchildFromBoyerLindquist();
      53           0 :   KerrSchildFromBoyerLindquist(double mass_in, std::array<double, 3> spin_in);
      54             : 
      55           0 :   double mass{std::numeric_limits<double>::signaling_NaN()};
      56           0 :   std::array<double, 3> spin{std::numeric_limits<double>::signaling_NaN(),
      57             :                              std::numeric_limits<double>::signaling_NaN(),
      58             :                              std::numeric_limits<double>::signaling_NaN()};
      59             : };
      60             : 
      61             : /// Label for shape map options
      62           1 : struct Spherical {};
      63             : 
      64           0 : struct YlmsFromFile {
      65           0 :   struct H5Filename {
      66           0 :     using type = std::string;
      67           0 :     static constexpr Options::String help =
      68             :         "Path to the data file containing the ylm coefficients and their "
      69             :         "derivatives.";
      70             :   };
      71             : 
      72           0 :   struct SubfileNames {
      73           0 :     using type = std::vector<std::string>;
      74           0 :     static constexpr Options::String help =
      75             :         "Subfile names for the different order derivatives of the ylm "
      76             :         "coefficients. You must specify the subfile name for the ylm "
      77             :         "coefficients themselves, and can optionally specify the subfile name "
      78             :         "for the first and second time derivatives as well, in that order. If "
      79             :         "you don't specify a derivative subfile, those coefficients will be "
      80             :         "defaulted to zero.";
      81           0 :     static size_t lower_bound_on_size() { return 1; }
      82           0 :     static size_t upper_bound_on_size() { return 3; }
      83             :   };
      84             : 
      85           0 :   struct MatchTime {
      86           0 :     using type = double;
      87           0 :     static constexpr Options::String help =
      88             :         "Time in the H5File to get the coefficients at. Will likely be the "
      89             :         "same as the initial time";
      90             :   };
      91             : 
      92           0 :   struct MatchTimeEpsilon {
      93           0 :     using type = Options::Auto<double>;
      94           0 :     static constexpr Options::String help =
      95             :         "Look for times in the H5File within this epsilon of the match time. "
      96             :         "This is to avoid having to know the exact time to all digits. Default "
      97             :         "is 1e-12.";
      98             :   };
      99             : 
     100           0 :   struct SetL1CoefsToZero {
     101           0 :     using type = bool;
     102           0 :     static constexpr Options::String help =
     103             :         "Whether to set the L=1 coefs to zero or not. This may be desirable "
     104             :         "because L=1 is degenerate with a translation of the BH.";
     105             :   };
     106             : 
     107           0 :   struct CheckFrame {
     108           0 :     using type = bool;
     109           0 :     static constexpr Options::String help =
     110             :         "Whether to check if the frame of the Strahlkorper in the file matches "
     111             :         "the Distorted frame.";
     112             :   };
     113             : 
     114           0 :   using options = tmpl::list<H5Filename, SubfileNames, MatchTime,
     115             :                              MatchTimeEpsilon, SetL1CoefsToZero, CheckFrame>;
     116             : 
     117           0 :   static constexpr Options::String help = {
     118             :       "Read the Y_lm coefficients of a Strahlkorper from file and use those to "
     119             :       "initialize the coefficients of a shape map."};
     120           0 :   YlmsFromFile();
     121           0 :   YlmsFromFile(std::string h5_filename_in,
     122             :                std::vector<std::string> subfile_names_in, double match_time_in,
     123             :                std::optional<double> match_time_epsilon_in,
     124             :                bool set_l1_coefs_to_zero_in, bool check_frame_in = true);
     125             : 
     126           0 :   std::string h5_filename;
     127           0 :   std::vector<std::string> subfile_names;
     128           0 :   double match_time{};
     129           0 :   std::optional<double> match_time_epsilon;
     130           0 :   bool set_l1_coefs_to_zero{};
     131           0 :   bool check_frame{true};
     132             : };
     133             : 
     134           0 : struct YlmsFromSpEC {
     135           0 :   struct DatFilename {
     136           0 :     using type = std::string;
     137           0 :     static constexpr Options::String help =
     138             :         "Name of the SpEC dat file holding the coefficients. Note that this "
     139             :         "isn't a Dat file within an H5 file. This must be an actual '.dat' "
     140             :         "file on disk.";
     141             :   };
     142             : 
     143           0 :   struct MatchTime {
     144           0 :     using type = double;
     145           0 :     static constexpr Options::String help =
     146             :         "Time in the H5File to get the coefficients at. Will likely be the "
     147             :         "same as the initial time";
     148             :   };
     149             : 
     150           0 :   struct MatchTimeEpsilon {
     151           0 :     using type = Options::Auto<double>;
     152           0 :     static constexpr Options::String help =
     153             :         "Look for times in the H5File within this epsilon of the match time. "
     154             :         "This is to avoid having to know the exact time to all digits. Default "
     155             :         "is 1e-12.";
     156             :   };
     157             : 
     158           0 :   struct SetL1CoefsToZero {
     159           0 :     using type = bool;
     160           0 :     static constexpr Options::String help =
     161             :         "Whether to set the L=1 coefs to zero or not. This may be desirable "
     162             :         "because L=1 is degenerate with a translation of the BH.";
     163             :   };
     164             : 
     165           0 :   using options =
     166             :       tmpl::list<DatFilename, MatchTime, MatchTimeEpsilon, SetL1CoefsToZero>;
     167             : 
     168           0 :   static constexpr Options::String help = {
     169             :       "Read the Y_lm coefficients of a Strahlkorper from file and use those to "
     170             :       "initialize the coefficients of a shape map."};
     171           0 :   YlmsFromSpEC();
     172           0 :   YlmsFromSpEC(std::string dat_filename_in, double match_time_in,
     173             :                std::optional<double> match_time_epsilon_in,
     174             :                bool set_l1_coefs_to_zero_in);
     175             : 
     176           0 :   std::string dat_filename;
     177           0 :   double match_time{};
     178           0 :   std::optional<double> match_time_epsilon;
     179           0 :   bool set_l1_coefs_to_zero{};
     180             : };
     181             : 
     182             : namespace detail {
     183             : struct TransitionEndsAtCube {
     184             :   using type = bool;
     185             :   static constexpr Options::String help = {
     186             :       "If 'true', the shape map transition function will be 0 at the cubical "
     187             :       "boundary around the object. If 'false' the transition function will "
     188             :       "be 0 at the outer radius of the inner sphere around the object"};
     189             : };
     190             : }  // namespace detail
     191             : 
     192             : /*!
     193             :  * \brief Specialized version of `FromVolumeFile` for the shape map
     194             :  *
     195             :  * \details This is needed because the regular `FromVolumeFile` doesn't have
     196             :  * options for domain settings like `TransitionEndsAtCube` or `LMax`.
     197             :  */
     198             : template <ObjectLabel Object>
     199           1 : struct FromVolumeFileShapeSize : public FromVolumeFile {
     200             :  public:
     201           0 :   struct CoefficientTruncationLimit {
     202           0 :     using type = double;
     203           0 :     static constexpr Options::String help = {
     204             :         "Coefficients below this absolute value will be truncated from the "
     205             :         "Shape map. Set to 0.0 to disable truncation."};
     206           0 :     static constexpr type default_value = 0.0;
     207             :   };
     208           0 :   struct LMax {
     209           0 :     using type = Options::Auto<size_t>;
     210           0 :     static constexpr Options::String help = {
     211             :         "LMax used for the number of spherical harmonic coefficients of the "
     212             :         "distortion map. If set to 'Auto', will use the LMax from the shape "
     213             :         "function of time in the volume file."};
     214             :   };
     215           0 :   using options = tmpl::push_front<FromVolumeFile::options, LMax,
     216             :                                    CoefficientTruncationLimit,
     217             :                                    detail::TransitionEndsAtCube>;
     218             : 
     219           0 :   FromVolumeFileShapeSize() = default;
     220           0 :   FromVolumeFileShapeSize(const std::optional<size_t>& l_max_in,
     221             :                           double coefficient_truncation_limit_in,
     222             :                           bool transition_ends_at_cube_in,
     223             :                           std::string h5_filename, std::string subfile_name,
     224             :                           const Options::Context& context = {});
     225             : 
     226           0 :   size_t l_max{};
     227           0 :   double coefficient_truncation_limit{0.0};
     228           0 :   bool transition_ends_at_cube{};
     229             : 
     230             :  private:
     231           0 :   std::string h5_filename_;
     232           0 :   std::string subfile_name_;
     233             : };
     234             : 
     235             : /*!
     236             :  * \brief Class to be used as an option for initializing shape map coefficients.
     237             :  *
     238             :  * \details This class can also be used as an option tag with the \p type type
     239             :  * alias, `name()` function, and \p help string.
     240             :  *
     241             :  * \tparam IncludeTransitionEndsAtCube This is mainly added for the
     242             :  * `domain::creators::BinaryCompactObject` domain.
     243             :  * \tparam Object Which object that this shape map represents. Use
     244             :  * `domain::ObjectLabel::None` if there is only a single object in your
     245             :  * simulation.
     246             :  */
     247             : template <bool IncludeTransitionEndsAtCube, domain::ObjectLabel Object>
     248           1 : struct ShapeMapOptions {
     249           0 :   struct CoefficientTruncationLimit {
     250           0 :     using type = double;
     251           0 :     static constexpr Options::String help = {
     252             :         "Coefficients below this absolute value will be truncated from the "
     253             :         "Shape map. Set to 0.0 to disable truncation."};
     254           0 :     static constexpr type default_value = 0.0;
     255             :   };
     256           0 :   using type = Options::Auto<
     257             :       std::variant<ShapeMapOptions<IncludeTransitionEndsAtCube, Object>,
     258             :                    FromVolumeFileShapeSize<Object>>,
     259             :       Options::AutoLabel::None>;
     260           0 :   static std::string name() { return "ShapeMap" + get_output(Object); }
     261           0 :   static constexpr Options::String help = {
     262             :       "Options for a time-dependent distortion (shape) map about the "
     263             :       "specified object. Specify 'None' to not use this map."};
     264             : 
     265           0 :   struct LMax {
     266           0 :     using type = size_t;
     267           0 :     static constexpr Options::String help = {
     268             :         "LMax used for the number of spherical harmonic coefficients of the "
     269             :         "distortion map."};
     270             :   };
     271             : 
     272           0 :   struct InitialValues {
     273           0 :     using type = Options::Auto<
     274             :         std::variant<KerrSchildFromBoyerLindquist, YlmsFromFile, YlmsFromSpEC>,
     275             :         Spherical>;
     276           0 :     static constexpr Options::String help = {
     277             :         "Initial Ylm coefficients for the shape map. Specify 'Spherical' for "
     278             :         "all coefficients to be initialized to zero."};
     279             :   };
     280             : 
     281           0 :   struct SizeInitialValues {
     282           0 :     using type = Options::Auto<std::array<double, 3>>;
     283           0 :     static constexpr Options::String help = {
     284             :         "Initial value and two derivatives of the 00 coefficient. Specify "
     285             :         "'Auto' to use the 00 coefficient specified in the 'InitialValues' "
     286             :         "option. If you specify 'Auto', the deformed sphere will match the "
     287             :         "'InitialValues' surface exactly, and the original radius will only "
     288             :         "set the radius of the sphere in the grid frame (before deformation)."};
     289             :   };
     290             : 
     291           0 :   using common_options = tmpl::list<LMax, InitialValues, SizeInitialValues,
     292             :                                     CoefficientTruncationLimit>;
     293             : 
     294           0 :   using options = tmpl::conditional_t<
     295             :       IncludeTransitionEndsAtCube,
     296             :       tmpl::push_back<common_options, detail::TransitionEndsAtCube>,
     297             :       common_options>;
     298           0 :   ShapeMapOptions() = default;
     299           0 :   ShapeMapOptions(size_t l_max_in,
     300             :                   std::optional<std::variant<KerrSchildFromBoyerLindquist,
     301             :                                              YlmsFromFile, YlmsFromSpEC>>
     302             :                       initial_values_in,
     303             :                   std::optional<std::array<double, 3>> initial_size_values_in =
     304             :                       std::nullopt,
     305             :                   double coefficient_truncation_limit_in = 0.0,
     306             :                   bool transition_ends_at_cube_in = false)
     307             :       : l_max(l_max_in),
     308             :         initial_values(std::move(initial_values_in)),
     309             :         initial_size_values(initial_size_values_in),
     310             :         coefficient_truncation_limit(coefficient_truncation_limit_in),
     311             :         transition_ends_at_cube(transition_ends_at_cube_in) {}
     312             : 
     313           0 :   size_t l_max{};
     314             :   std::optional<
     315             :       std::variant<KerrSchildFromBoyerLindquist, YlmsFromFile, YlmsFromSpEC>>
     316           0 :       initial_values;
     317           0 :   std::optional<std::array<double, 3>> initial_size_values;
     318           0 :   double coefficient_truncation_limit{0.0};
     319           0 :   bool transition_ends_at_cube{false};
     320             : };
     321             : 
     322             : /*!
     323             :  * \brief Helper function to get LMax from the different variants that the shape
     324             :  * map options could be.
     325             :  */
     326             : template <bool IncludeTransitionEndsAtCube, domain::ObjectLabel Object>
     327           1 : size_t l_max_from_shape_options(
     328             :     const std::variant<ShapeMapOptions<IncludeTransitionEndsAtCube, Object>,
     329             :                        FromVolumeFileShapeSize<Object>>& shape_map_options);
     330             : 
     331             : /*!
     332             :  * \brief Helper function to get the coefficient truncation limit from the
     333             :  * different variants that the shape map options could be.
     334             :  */
     335             : template <bool IncludeTransitionEndsAtCube, domain::ObjectLabel Object>
     336           1 : double coefficient_truncation_limit_from_shape_options(
     337             :     const std::variant<ShapeMapOptions<IncludeTransitionEndsAtCube, Object>,
     338             :                        FromVolumeFileShapeSize<Object>>& shape_map_options);
     339             : 
     340             : /*!
     341             :  * \brief Helper function to get whether the shape map transition function ends
     342             :  * at the cube from the different variants that the shape map options could be.
     343             :  */
     344             : template <bool IncludeTransitionEndsAtCube, domain::ObjectLabel Object>
     345           1 : bool transition_ends_at_cube_from_shape_options(
     346             :     const std::variant<ShapeMapOptions<IncludeTransitionEndsAtCube, Object>,
     347             :                        FromVolumeFileShapeSize<Object>>& shape_map_options);
     348             : 
     349             : /*!
     350             :  * \brief Helper function that takes the variant of the shape map options, and
     351             :  * returns the fully constructed shape and size functions of time.
     352             :  *
     353             :  * \details Even if the functions of time are read from a file, they will have a
     354             :  * new \p initial_time, \p shape_expiration_time, and \p size_expiration_time.
     355             :  * The \p deformed_radius is only used for the non-volume file variants.
     356             :  */
     357             : template <bool IncludeTransitionEndsAtCube, domain::ObjectLabel Object>
     358           1 : FunctionsOfTimeMap get_shape_and_size(
     359             :     const std::variant<ShapeMapOptions<IncludeTransitionEndsAtCube, Object>,
     360             :                        FromVolumeFileShapeSize<Object>>& shape_map_options,
     361             :     double initial_time, double shape_expiration_time,
     362             :     double size_expiration_time, double deformed_radius);
     363             : }  // namespace domain::creators::time_dependent_options

Generated by: LCOV version 1.14