SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/Cce - WorldtubeBufferUpdater.hpp Hit Total Coverage
Commit: f81419eb45f381cdf5c6c7751685b35483e19db9 Lines: 27 121 22.3 %
Date: 2025-04-20 16:13:24
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 <cstddef>
       7             : #include <limits>
       8             : #include <memory>
       9             : #include <optional>
      10             : #include <string>
      11             : #include <type_traits>
      12             : #include <utility>
      13             : 
      14             : #include "DataStructures/ComplexDataVector.hpp"
      15             : #include "DataStructures/ComplexModalVector.hpp"
      16             : #include "DataStructures/DataBox/PrefixHelpers.hpp"
      17             : #include "DataStructures/DataBox/Prefixes.hpp"
      18             : #include "DataStructures/DataBox/Tag.hpp"
      19             : #include "DataStructures/DataBox/TagName.hpp"
      20             : #include "DataStructures/DataVector.hpp"
      21             : #include "DataStructures/Matrix.hpp"
      22             : #include "Evolution/Systems/Cce/BoundaryData.hpp"
      23             : #include "Evolution/Systems/Cce/Tags.hpp"
      24             : #include "IO/H5/Dat.hpp"
      25             : #include "IO/H5/File.hpp"
      26             : #include "IO/H5/Version.hpp"
      27             : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshTags.hpp"
      28             : #include "Options/Options.hpp"
      29             : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
      30             : #include "Utilities/ErrorHandling/Assert.hpp"
      31             : #include "Utilities/Gsl.hpp"
      32             : #include "Utilities/Serialization/CharmPupable.hpp"
      33             : #include "Utilities/Serialization/PupStlCpp17.hpp"
      34             : #include "Utilities/TMPL.hpp"
      35             : #include "Utilities/TaggedTuple.hpp"
      36             : 
      37             : namespace Cce {
      38             : namespace Tags::detail {
      39             : // tags for use in the buffers for the input worldtube data management classes
      40             : template <typename T>
      41             : using SpatialMetric = gr::Tags::SpatialMetric<T, 3>;
      42             : template <typename T>
      43             : using Shift = gr::Tags::Shift<T, 3>;
      44             : template <typename T>
      45             : using Lapse = gr::Tags::Lapse<T>;
      46             : // This is B^i in the 3+1 equations
      47             : template <typename T>
      48             : struct AuxiliaryShift : db::SimpleTag {
      49             :   using type = tnsr::I<T, 3, ::Frame::Inertial>;
      50             : };
      51             : // This is \Gamma^i in the Z4c equations
      52             : template <typename T>
      53             : struct ConformalChristoffel : db::SimpleTag {
      54             :   using type = tnsr::I<T, 3, ::Frame::Inertial>;
      55             : };
      56             : template <typename T>
      57             : using ExtrinsicCurvature = gr::Tags::ExtrinsicCurvature<T, 3>;
      58             : 
      59             : // The three metric quantities we read in from disk (no derivatives)
      60             : template <typename T>
      61             : using metric_tags = tmpl::list<SpatialMetric<T>, Shift<T>, Lapse<T>>;
      62             : 
      63             : // radial derivative prefix tag to be used with the input worldtube data
      64             : template <typename Tag>
      65             : struct Dr : db::SimpleTag, db::PrefixTag {
      66             :   using type = typename Tag::type;
      67             :   using tag = Tag;
      68             : };
      69             : // For cartesian derivs. Each dataset is stored separately in the file, so it
      70             : // doesn't make sense to use ::Tags::deriv here
      71             : template <typename Tag>
      72             : struct Dx : db::SimpleTag, db::PrefixTag {
      73             :   static constexpr size_t index = 0;
      74             :   using type = typename Tag::type;
      75             : };
      76             : template <typename Tag>
      77             : struct Dy : db::SimpleTag, db::PrefixTag {
      78             :   static constexpr size_t index = 1;
      79             :   using type = typename Tag::type;
      80             : };
      81             : template <typename Tag>
      82             : struct Dz : db::SimpleTag, db::PrefixTag {
      83             :   static constexpr size_t index = 2;
      84             :   using type = typename Tag::type;
      85             : };
      86             : template <typename Tag>
      87             : using cartesian_derivs_t = tmpl::list<Dx<Tag>, Dy<Tag>, Dz<Tag>>;
      88             : 
      89             : // tag for the string for accessing the quantity associated with `Tag` in
      90             : // worldtube h5 file
      91             : template <typename Tag>
      92             : struct InputDataSet : db::SimpleTag, db::PrefixTag {
      93             :   using type = std::string;
      94             :   using tag = Tag;
      95             : };
      96             : 
      97             : // Puts `Tag`, `::Tags::dt<Tag>`, and `Cce::Tags::Dr<Tag>` into a `tmpl::list`
      98             : template <typename Tag>
      99             : struct apply_derivs {
     100             :   using type = tmpl::list<Tag, ::Tags::dt<Tag>, Dr<Tag>>;
     101             : };
     102             : template <typename Tag>
     103             : using apply_derivs_t = typename apply_derivs<Tag>::type;
     104             : 
     105             : // Puts `Tag`, `::Tags::dt<Tag>`, `Dx<Tag>`, `Dy<Tag>`, `Dz<Tag>` into a
     106             : // `tmpl::list`
     107             : template <typename Tag>
     108             : struct apply_derivs_adm {
     109             :   using type =
     110             :       tmpl::flatten<tmpl::list<Tag, ::Tags::dt<Tag>, cartesian_derivs_t<Tag>>>;
     111             : };
     112             : template <typename Tag>
     113             : using apply_derivs_adm_t = typename apply_derivs_adm<Tag>::type;
     114             : }  // namespace Tags::detail
     115             : 
     116             : namespace detail {
     117             : // generates the component dataset name in the worldtube file based on the
     118             : // tensor indices requested. For instance, if called with arguments ("/g", 0,1),
     119             : // it returns the dataset name "/gxy".
     120             : template <typename... T>
     121             : std::string dataset_name_for_component(std::string base_name,
     122             :                                        const T... indices) {  // NOLINT
     123             :   const auto add_index = [&base_name](size_t index) {
     124             :     ASSERT(index < 3, "The character-arithmetic index must be less than 3.");
     125             :     base_name += static_cast<char>('x' + index);
     126             :   };
     127             :   EXPAND_PACK_LEFT_TO_RIGHT(add_index(indices));
     128             :   // void cast so that compilers can tell it's used.
     129             :   (void)add_index;
     130             :   return base_name;
     131             : }
     132             : 
     133             : // creates a pair of indices such that the difference is `2 *
     134             : // interpolator_length + pad`, centered around `time`, and bounded by
     135             : // `lower_bound` and `upper_bound`. If it cannot be centered, it gives a span
     136             : // that is appropriately sized and bounded by the supplied bounds. If the bounds
     137             : // are too constraining for the necessary size, it gives a span that is the
     138             : // correct size starting at `lower bound`, but not constrained by `upper_bound`
     139             : std::pair<size_t, size_t> create_span_for_time_value(
     140             :     double time, size_t pad, size_t interpolator_length, size_t lower_bound,
     141             :     size_t upper_bound, const DataVector& time_buffer);
     142             : 
     143             : // retrieves time stamps and lmax the from the specified file. the bools
     144             : // `is_real`, `is_modal_data`, and `is_complex` are used to predict the number
     145             : // of columns in the dat file and possibly error if that number is incorrect.
     146             : // Note that if `is_modal_data` is true, then we use `is_real` but `is_complex`
     147             : // is unneeded. If `is_modal_data` if false, then `is_complex` is used, but
     148             : // `is_real` is unneeded.
     149             : void set_time_buffer_and_lmax(gsl::not_null<DataVector*> time_buffer,
     150             :                               size_t& l_max, const h5::Dat& data, bool is_real,
     151             :                               bool is_modal_data, bool is_complex);
     152             : 
     153             : // updates `time_span_start` and `time_span_end` based on the provided `time`,
     154             : // and inserts the cooresponding modal data (for `InputTags`) from worldtube H5
     155             : // file into `buffers`. The function is used by Bondi and Klein-Gordon systems.
     156             : template <typename InputTags>
     157             : double update_buffers_for_time(
     158             :     gsl::not_null<Variables<InputTags>*> buffers,
     159             :     gsl::not_null<size_t*> time_span_start,
     160             :     gsl::not_null<size_t*> time_span_end, double time, size_t computation_l_max,
     161             :     size_t l_max, size_t interpolator_length, size_t buffer_depth,
     162             :     const DataVector& time_buffer,
     163             :     const tuples::tagged_tuple_from_typelist<
     164             :         db::wrap_tags_in<Tags::detail::InputDataSet, InputTags>>& dataset_names,
     165             :     const h5::H5File<h5::AccessType::ReadOnly>& cce_data_file);
     166             : }  // namespace detail
     167             : 
     168             : /// the full set of metric tensors to be extracted from the worldtube h5 file
     169             : template <typename T>
     170           1 : using cce_metric_input_tags =
     171             :     tmpl::flatten<tmpl::transform<Tags::detail::metric_tags<T>,
     172             :                                   Tags::detail::apply_derivs<tmpl::_1>>>;
     173             : 
     174             : template <typename T>
     175           0 : using cce_metric_adm_input_tags = tmpl::flatten<tmpl::push_back<
     176             :     tmpl::transform<Tags::detail::metric_tags<T>,
     177             :                     Tags::detail::apply_derivs_adm<tmpl::_1>>,
     178             :     Tags::detail::ExtrinsicCurvature<T>, Tags::detail::AuxiliaryShift<T>,
     179             :     Tags::detail::ConformalChristoffel<T>>>;
     180             : 
     181           0 : using klein_gordon_input_tags =
     182             :     tmpl::list<Spectral::Swsh::Tags::SwshTransform<Tags::KleinGordonPsi>,
     183             :                Spectral::Swsh::Tags::SwshTransform<Tags::KleinGordonPi>>;
     184             : 
     185             : /// \cond
     186             : template <typename T>
     187             : class MetricWorldtubeH5BufferUpdater;
     188             : template <typename T>
     189             : class BondiWorldtubeH5BufferUpdater;
     190             : class KleinGordonWorldtubeH5BufferUpdater;
     191             : /// \endcond
     192             : 
     193             : /*!
     194             :  *  \brief Abstract base class for utilities that are able to perform the buffer
     195             :  *  updating procedure needed by the `WorldtubeDataManager` or by the
     196             :  *  `PreprocessCceWorldtube` executable.
     197             :  *
     198             :  *  \details The methods that are required to be overridden in the derived
     199             :  * classes are:
     200             :  *  - `WorldtubeBufferUpdater::update_buffers_for_time()`:
     201             :  *  updates the buffers passed by pointer and the `time_span_start` and
     202             :  *  `time_span_end` to be appropriate for the requested `time`,
     203             :  *  `interpolator_length`, and `buffer_depth`.
     204             :  *  - `WorldtubeBufferUpdater::get_clone()`
     205             :  *  clone function to obtain a `std::unique_ptr` of the base
     206             :  *  `WorldtubeBufferUpdater`, needed to pass around the factory-created
     207             :  *  object.
     208             :  *  - `WorldtubeBufferUpdater::time_is_outside_range()`
     209             :  *  the override should return `true` if the `time` could be used in a
     210             :  *  `update_buffers_for_time` call given the data available to the derived
     211             :  *  class, and `false` otherwise
     212             :  *  - `WorldtubeBufferUpdater::get_l_max()`
     213             :  *  The override should return the `l_max` it uses in the
     214             :  *  Goldberg modal data placed in the buffers.
     215             :  *  - `WorldtubeBufferUpdater::get_extraction_radius()`
     216             :  *  The override should return the coordinate radius associated with the modal
     217             :  *  worldtube data that it supplies in the buffer update function. This is
     218             :  *  currently assumed to be a single double, but may be generalized in future
     219             :  *  to be time-dependent.
     220             :  *  - `WorldtubeBufferUpdater::get_time_buffer`
     221             :  *  The override should return the vector of times that it can produce
     222             :  *  data at. For instance, if associated with a file input, this will be the
     223             :  *  times at each of the rows of the time-series data.
     224             :  */
     225             : template <typename BufferTags>
     226           1 : class WorldtubeBufferUpdater : public PUP::able {
     227             :  public:
     228           0 :   using creatable_classes =
     229             :       tmpl::list<MetricWorldtubeH5BufferUpdater<ComplexModalVector>,
     230             :                  MetricWorldtubeH5BufferUpdater<DataVector>,
     231             :                  BondiWorldtubeH5BufferUpdater<ComplexModalVector>,
     232             :                  BondiWorldtubeH5BufferUpdater<ComplexDataVector>,
     233             :                  KleinGordonWorldtubeH5BufferUpdater>;
     234             : 
     235           0 :   WRAPPED_PUPable_abstract(WorldtubeBufferUpdater);  // NOLINT
     236             : 
     237           0 :   virtual double update_buffers_for_time(
     238             :       gsl::not_null<Variables<BufferTags>*> buffers,
     239             :       gsl::not_null<size_t*> time_span_start,
     240             :       gsl::not_null<size_t*> time_span_end, double time,
     241             :       size_t computation_l_max, size_t interpolator_length, size_t buffer_depth,
     242             :       bool time_varies_fastest = true) const = 0;
     243             : 
     244           0 :   virtual std::unique_ptr<WorldtubeBufferUpdater> get_clone() const = 0;
     245             : 
     246           0 :   virtual bool time_is_outside_range(double time) const = 0;
     247             : 
     248           0 :   virtual size_t get_l_max() const = 0;
     249             : 
     250           0 :   virtual double get_extraction_radius() const = 0;
     251             : 
     252           0 :   virtual bool has_version_history() const = 0;
     253             : 
     254           0 :   virtual DataVector& get_time_buffer() = 0;
     255             : };
     256             : 
     257             : /*!
     258             :  * \brief A `WorldtubeBufferUpdater` specialized to CCE input worldtube H5 files
     259             :  * that have cartesian metric components stored in either modal or nodal form.
     260             :  *
     261             :  * \details To read in modal data, template this class as
     262             :  * `MetricWorldtubeH5BufferUpdater<ComplexModalVector>`. To read in nodal data,
     263             :  * template the class as `MetricWorldtubeH5BufferUpdater<DataVector>`. This
     264             :  * class also has the ability to read in data specifically written by SpEC.
     265             :  */
     266             : template <typename T>
     267           1 : class MetricWorldtubeH5BufferUpdater
     268             :     : public WorldtubeBufferUpdater<cce_metric_input_tags<T>> {
     269             :   static_assert(std::is_same_v<T, ComplexModalVector> or
     270             :                     std::is_same_v<T, DataVector>,
     271             :                 "Can only use ComplexModalVector or DataVector in a "
     272             :                 "MetricWorldtubeH5BufferUpdater.");
     273             : 
     274             :  public:
     275           0 :   static constexpr bool is_modal = std::is_same_v<T, ComplexModalVector>;
     276             : 
     277             :   /*!
     278             :    * \brief Options needed when reading in the extrinsic curvature and auxiliary
     279             :    * shift (BSSN) or the trace of the conformal christoffel (Z4c) from a non-GH
     280             :    * evolution code.
     281             :    *
     282             :    * \details Can also be used as an option tag
     283             :    */
     284           1 :   struct AdmOptions {
     285           0 :     static std::string name() { return "AdmMetricNodal"; }
     286             : 
     287           0 :     struct Advective {
     288           0 :       using type = bool;
     289           0 :       static constexpr Options::String help =
     290             :           "Add advective term to time derivative.";
     291             :     };
     292             : 
     293           0 :     struct Lapse {
     294           0 :       using type = Lapse;
     295           0 :       Lapse() = default;
     296           0 :       using options = tmpl::list<Advective>;
     297           0 :       static constexpr Options::String help =
     298             :           "Options for 1+log slicing of the lapse.";
     299           0 :       explicit Lapse(const bool advective) : is_advective(advective) {}
     300             : 
     301           0 :       void pup(PUP::er& p) { p | is_advective; }
     302             : 
     303           0 :       bool is_advective;
     304             :     };
     305             : 
     306           0 :     struct Shift {
     307           0 :       using type = Shift;
     308           0 :       struct SecondOrderDriverEta {
     309           0 :         using type = double;
     310           0 :         static constexpr Options::String help =
     311             :             "Factor 'eta' in front of shift vector in Eq. 12 of Hilditch 2013 "
     312             :             "(typically 2/M). To use this, the trace conformal christoffel "
     313             :             "must be dumped.";
     314             :       };
     315           0 :       struct ConformalChristoffelFactor {
     316           0 :         using type = double;
     317           0 :         static constexpr Options::String help =
     318             :             "Factor A in mu_S=A/lapse^2 in front of conformal Christoffel term "
     319             :             "in Eq. 12 of Hilditch 2013 (typically A=1). To use this, the "
     320             :             "trace conformal Christoffel must be dumped.";
     321             :       };
     322           0 :       struct FirstOrderDriverFactor {
     323           0 :         using type = double;
     324           0 :         static constexpr Options::String help =
     325             :             "Factor in front of auxiliary shift vector B^i in left Eq. 4.89 of "
     326             :             "B&S (typically 0.75). To use this, the auxiliary shift vector B^i "
     327             :             "must be dumped. Here mu_S is assumed to be 1/lapse^2.";
     328             :       };
     329           0 :       Shift() = default;
     330           0 :       using options = tmpl::list<
     331             :           Advective,
     332             :           Options::Alternatives<
     333             :               tmpl::list<SecondOrderDriverEta, ConformalChristoffelFactor>,
     334             :               tmpl::list<FirstOrderDriverFactor>>>;
     335             : 
     336           0 :       static constexpr Options::String help =
     337             :           "Options for Gamma driver shift condition.";
     338           0 :       Shift(const bool advective, const double second_order_factor,
     339             :             const double conformal_christoffel_factor_in)
     340             :           : is_advective(advective),
     341             :             is_first_order(false),
     342             :             extra_factor(second_order_factor),
     343             :             conformal_christoffel_factor(conformal_christoffel_factor_in) {}
     344           0 :       Shift(const bool advective, const double first_order_factor)
     345             :           : is_advective(advective),
     346             :             is_first_order(true),
     347             :             extra_factor(first_order_factor),
     348             :             conformal_christoffel_factor(std::numeric_limits<double>::max()) {}
     349             : 
     350           0 :       void pup(PUP::er& p) {
     351             :         p | is_advective;
     352             :         p | is_first_order;
     353             :         p | extra_factor;
     354             :       }
     355             : 
     356           0 :       bool is_advective;
     357           0 :       bool is_first_order;
     358           0 :       double extra_factor;
     359           0 :       double conformal_christoffel_factor;
     360             :     };
     361             : 
     362           0 :     using options = tmpl::list<Lapse, Shift>;
     363           0 :     static constexpr Options::String help =
     364             :         "Gauge options when reading in extrinsic curvature additional variable "
     365             :         "from non-GH evolutions.";
     366             : 
     367           0 :     AdmOptions() = default;
     368           0 :     AdmOptions(const Lapse& lapse_in, const Shift& shift_in)
     369             :         : lapse(lapse_in), shift(shift_in) {}
     370             : 
     371           0 :     void pup(PUP::er& p) {
     372             :       p | lapse;
     373             :       p | shift;
     374             :     }
     375             : 
     376           0 :     Lapse lapse;
     377           0 :     Shift shift;
     378             :   };
     379             : 
     380             :   // charm needs the empty constructor
     381           0 :   MetricWorldtubeH5BufferUpdater() = default;
     382             : 
     383             :   /// The constructor takes the filename of the H5 file that will be used
     384             :   /// for boundary data. The extraction radius can either be passed in directly,
     385             :   /// or if it takes the value `std::nullopt`, then the extraction radius is
     386             :   /// retrieved as an integer in the filename. Also the user can specify if the
     387             :   /// H5 file was written by SpEC or not, because SpEC has some different
     388             :   /// conventions than we use here.
     389           1 :   explicit MetricWorldtubeH5BufferUpdater(
     390             :       const std::string& cce_data_filename,
     391             :       std::optional<double> extraction_radius = std::nullopt,
     392             :       bool descending_m = true,
     393             :       const std::optional<AdmOptions>& adm_options = std::nullopt);
     394             : 
     395             :   // NOLINTNEXTLINE
     396           0 :   WRAPPED_PUPable_decl_base_template(
     397             :       WorldtubeBufferUpdater<cce_metric_input_tags<T>>,
     398             :       MetricWorldtubeH5BufferUpdater);
     399             : 
     400           0 :   explicit MetricWorldtubeH5BufferUpdater(CkMigrateMessage* /*unused*/) {}
     401             : 
     402             :   /// \brief Update the `buffers`, `time_span_start`, and `time_span_end` with
     403             :   /// data (either Goldberg modal data or just nodal data depending on the
     404             :   /// template parameter to this class) and the start and end index in the
     405             :   /// member `time_buffer_` covered by the newly updated `buffers`.
     406             :   ///
     407             :   /// The function returns the next time at which a full update will occur. If
     408             :   /// called again at times earlier than the next full update time, it will
     409             :   /// leave the `buffers` unchanged and again return the next needed time.
     410           1 :   double update_buffers_for_time(
     411             :       gsl::not_null<Variables<cce_metric_input_tags<T>>*> buffers,
     412             :       gsl::not_null<size_t*> time_span_start,
     413             :       gsl::not_null<size_t*> time_span_end, double time,
     414             :       size_t computation_l_max, size_t interpolator_length, size_t buffer_depth,
     415             :       bool time_varies_fastest = true) const override;
     416             : 
     417           0 :   std::unique_ptr<WorldtubeBufferUpdater<cce_metric_input_tags<T>>> get_clone()
     418             :       const override;
     419             : 
     420             :   /// The time can only be supported in the buffer update if it is between the
     421             :   /// first and last time of the input file.
     422           1 :   bool time_is_outside_range(double time) const override;
     423             : 
     424             :   /// retrieves the l_max of the input file
     425           1 :   size_t get_l_max() const override { return l_max_; }
     426             : 
     427             :   /// retrieves the extraction radius
     428           1 :   double get_extraction_radius() const override { return extraction_radius_; }
     429             : 
     430             :   /// The time buffer is supplied by non-const reference to allow views to
     431             :   /// easily point into the buffer.
     432             :   ///
     433             :   /// \warning Altering this buffer outside of the constructor of this class
     434             :   /// results in undefined behavior! This should be supplied by const reference
     435             :   /// once there is a convenient method of producing a const view of a vector
     436             :   /// type.
     437           1 :   DataVector& get_time_buffer() override { return time_buffer_; }
     438             : 
     439           0 :   bool has_version_history() const override { return has_version_history_; }
     440             : 
     441             :   /// Serialization for Charm++.
     442           1 :   void pup(PUP::er& p) override;
     443             : 
     444             :  private:
     445           0 :   void update_radial_formulation(
     446             :       gsl::not_null<Variables<cce_metric_input_tags<T>>*> buffers,
     447             :       size_t computation_l_max, size_t time_span_start, size_t time_span_end,
     448             :       bool time_varies_fastest) const;
     449             :   template <typename U = T>
     450             :   typename std::enable_if_t<std::is_same_v<U, DataVector>>
     451           0 :   update_adm_formulation(
     452             :       gsl::not_null<Variables<cce_metric_input_tags<DataVector>>*> buffers,
     453             :       size_t computation_l_max, size_t time_span_start, size_t time_span_end,
     454             :       bool time_varies_fastest) const;
     455           0 :   void update_buffer(gsl::not_null<T*> buffer_to_update,
     456             :                      const h5::Dat& read_data, size_t computation_l_max,
     457             :                      size_t time_span_start, size_t time_span_end,
     458             :                      bool time_varies_fastest) const;
     459             : 
     460           0 :   bool has_version_history_ = true;
     461           0 :   double extraction_radius_ = std::numeric_limits<double>::signaling_NaN();
     462           0 :   size_t l_max_ = 0;
     463             : 
     464           0 :   h5::H5File<h5::AccessType::ReadOnly> cce_data_file_;
     465           0 :   std::string filename_;
     466           0 :   bool descending_m_ = true;
     467           0 :   std::optional<AdmOptions> adm_options_;
     468             : 
     469             :   tuples::tagged_tuple_from_typelist<db::wrap_tags_in<
     470             :       Tags::detail::InputDataSet,
     471             :       tmpl::remove_duplicates<tmpl::append<cce_metric_input_tags<T>,
     472             :                                            cce_metric_adm_input_tags<T>>>>>
     473           0 :       dataset_names_;
     474             : 
     475             :   // stores all the times in the input file
     476           0 :   DataVector time_buffer_;
     477             : };
     478             : 
     479             : /*!
     480             :  * \brief A `WorldtubeBufferUpdater` specialized to CCE input worldtube H5 files
     481             :  * that have metric data stored in Bondi-Sachs format in either either modal or
     482             :  * nodal form.
     483             :  *
     484             :  * \details To read in modal data, template this class as
     485             :  * `MetricWorldtubeH5BufferUpdater<ComplexModalVector>`. To read in nodal data,
     486             :  * template the class as `MetricWorldtubeH5BufferUpdater<ComplexDataVector>`.
     487             :  */
     488             : template <typename T>
     489           1 : class BondiWorldtubeH5BufferUpdater
     490             :     : public WorldtubeBufferUpdater<tmpl::conditional_t<
     491             :           std::is_same_v<T, ComplexModalVector>,
     492             :           Tags::worldtube_boundary_tags_for_writing<
     493             :               Spectral::Swsh::Tags::SwshTransform>,
     494             :           Tags::worldtube_boundary_tags_for_writing<Tags::BoundaryValue>>> {
     495             :   static_assert(std::is_same_v<T, ComplexModalVector> or
     496             :                     std::is_same_v<T, ComplexDataVector>,
     497             :                 "Can only use ComplexModalVector or ComplexDataVector in a "
     498             :                 "BondiWorldtubeH5BufferUpdater.");
     499             : 
     500             :  public:
     501           0 :   using tags_for_writing = tmpl::conditional_t<
     502             :       std::is_same_v<T, ComplexModalVector>,
     503             :       Tags::worldtube_boundary_tags_for_writing<
     504             :           Spectral::Swsh::Tags::SwshTransform>,
     505             :       Tags::worldtube_boundary_tags_for_writing<Tags::BoundaryValue>>;
     506             : 
     507           0 :   static constexpr bool is_modal = std::is_same_v<T, ComplexModalVector>;
     508             : 
     509             :   // charm needs the empty constructor
     510           0 :   BondiWorldtubeH5BufferUpdater() = default;
     511             : 
     512             :   /// The constructor takes the filename of the H5 file that will be used
     513             :   /// for boundary data. The extraction radius can either be passed in directly,
     514             :   /// or if it takes the value `std::nullopt`, then the extraction radius is
     515             :   /// retrieved as an integer in the filename.
     516           1 :   explicit BondiWorldtubeH5BufferUpdater(
     517             :       const std::string& cce_data_filename,
     518             :       std::optional<double> extraction_radius = std::nullopt);
     519             : 
     520             :   // NOLINTNEXTLINE
     521           0 :   WRAPPED_PUPable_decl_base_template(
     522             :       SINGLE_ARG(WorldtubeBufferUpdater<tags_for_writing>),
     523             :       BondiWorldtubeH5BufferUpdater);
     524             : 
     525           0 :   explicit BondiWorldtubeH5BufferUpdater(CkMigrateMessage* /*unused*/) {}
     526             : 
     527             :   /// update the `buffers`, `time_span_start`, and `time_span_end` with Goldberg
     528             :   /// modal data (either Goldberg modal data or complex nodal data depending on
     529             :   /// the template parameter to this class) and the start and end index in the
     530             :   /// member `time_buffer_` covered by the newly updated `buffers`.
     531           1 :   double update_buffers_for_time(
     532             :       gsl::not_null<Variables<tags_for_writing>*> buffers,
     533             :       gsl::not_null<size_t*> time_span_start,
     534             :       gsl::not_null<size_t*> time_span_end, double time,
     535             :       size_t computation_l_max, size_t interpolator_length, size_t buffer_depth,
     536             :       bool time_varies_fastest = true) const override;
     537             : 
     538           0 :   std::unique_ptr<WorldtubeBufferUpdater<tags_for_writing>> get_clone()
     539             :       const override {
     540             :     return std::make_unique<BondiWorldtubeH5BufferUpdater>(filename_);
     541             :   }
     542             : 
     543             :   /// The time can only be supported in the buffer update if it is between the
     544             :   /// first and last time of the input file.
     545           1 :   bool time_is_outside_range(const double time) const override {
     546             :     return time < time_buffer_[0] or
     547             :            time > time_buffer_[time_buffer_.size() - 1];
     548             :   }
     549             : 
     550             :   /// retrieves the l_max of the input file
     551           1 :   size_t get_l_max() const override { return l_max_; }
     552             : 
     553             :   /// retrieves the extraction radius. In most normal circumstances, this will
     554             :   /// not be needed for Bondi data.
     555           1 :   double get_extraction_radius() const override {
     556             :     if (not extraction_radius_.has_value()) {
     557             :       ERROR(
     558             :           "Extraction radius has not been set, and was not successfully parsed "
     559             :           "from the filename. The extraction radius has been used, so must be "
     560             :           "set either by the input file or via the filename.");
     561             :     }
     562             :     return *extraction_radius_;
     563             :   }
     564             : 
     565             :   /// The time buffer is supplied by non-const reference to allow views to
     566             :   /// easily point into the buffer.
     567             :   ///
     568             :   /// \warning Altering this buffer outside of the constructor of this class
     569             :   /// results in undefined behavior! This should be supplied by const reference
     570             :   /// once there is a convenient method of producing a const view of a vector
     571             :   /// type.
     572           1 :   DataVector& get_time_buffer() override { return time_buffer_; }
     573             : 
     574           0 :   bool has_version_history() const override { return true; }
     575             : 
     576             :   /// Serialization for Charm++.
     577           1 :   void pup(PUP::er& p) override;
     578             : 
     579             :  private:
     580           0 :   std::optional<double> extraction_radius_ = std::nullopt;
     581           0 :   size_t l_max_ = 0;
     582             : 
     583           0 :   h5::H5File<h5::AccessType::ReadOnly> cce_data_file_;
     584           0 :   std::string filename_;
     585             : 
     586             :   tuples::tagged_tuple_from_typelist<
     587             :       db::wrap_tags_in<Tags::detail::InputDataSet, tags_for_writing>>
     588           0 :       dataset_names_;
     589             : 
     590             :   // stores all the times in the input file
     591           0 :   DataVector time_buffer_;
     592             : };
     593             : 
     594             : /// A `WorldtubeBufferUpdater` specialized to the Klein-Gordon input worldtube
     595             : /// H5 file produced by the SpEC format. We assume the scalar field is
     596             : /// real-valued.
     597           1 : class KleinGordonWorldtubeH5BufferUpdater
     598             :     : public WorldtubeBufferUpdater<klein_gordon_input_tags> {
     599             :  public:
     600             :   // charm needs the empty constructor
     601           0 :   KleinGordonWorldtubeH5BufferUpdater() = default;
     602             : 
     603             :   /// The constructor takes the filename of the SpEC h5 file that will be used
     604             :   /// for boundary data. The extraction radius can either be passed in directly,
     605             :   /// or if it takes the value `std::nullopt`, then the extraction radius is
     606             :   /// retrieved as an integer in the filename.
     607           1 :   explicit KleinGordonWorldtubeH5BufferUpdater(
     608             :       const std::string& cce_data_filename,
     609             :       std::optional<double> extraction_radius = std::nullopt);
     610             : 
     611           0 :   WRAPPED_PUPable_decl_template(KleinGordonWorldtubeH5BufferUpdater);  // NOLINT
     612             : 
     613           0 :   explicit KleinGordonWorldtubeH5BufferUpdater(CkMigrateMessage* /*unused*/) {}
     614             : 
     615             :   /// update the `buffers`, `time_span_start`, and `time_span_end` with Goldberg
     616             :   /// modal data and the start and end index in the member `time_buffer_`
     617             :   /// covered by the newly updated `buffers`.
     618           1 :   double update_buffers_for_time(
     619             :       gsl::not_null<Variables<klein_gordon_input_tags>*> buffers,
     620             :       gsl::not_null<size_t*> time_span_start,
     621             :       gsl::not_null<size_t*> time_span_end, double time,
     622             :       size_t computation_l_max, size_t interpolator_length, size_t buffer_depth,
     623             :       bool time_varies_fastest = true) const override;
     624             : 
     625           0 :   std::unique_ptr<WorldtubeBufferUpdater<klein_gordon_input_tags>> get_clone()
     626             :       const override {
     627             :     return std::make_unique<KleinGordonWorldtubeH5BufferUpdater>(filename_);
     628             :   }
     629             : 
     630             :   /// The time can only be supported in the buffer update if it is between the
     631             :   /// first and last time of the input file.
     632           1 :   bool time_is_outside_range(const double time) const override {
     633             :     return time < time_buffer_[0] or
     634             :            time > time_buffer_[time_buffer_.size() - 1];
     635             :   }
     636             : 
     637             :   /// retrieves the l_max of the input file
     638           1 :   size_t get_l_max() const override { return l_max_; }
     639             : 
     640             :   /// retrieves the extraction radius. In most normal circumstances, this will
     641             :   /// not be needed for Klein-Gordon data.
     642           1 :   double get_extraction_radius() const override {
     643             :     if (not static_cast<bool>(extraction_radius_)) {
     644             :       ERROR(
     645             :           "Extraction radius has not been set, and was not successfully parsed "
     646             :           "from the filename. The extraction radius has been used, so must be "
     647             :           "set either by the input file or via the filename.");
     648             :     }
     649             :     return *extraction_radius_;
     650             :   }
     651             : 
     652             :   /// The time buffer is supplied by non-const reference to allow views to
     653             :   /// easily point into the buffer.
     654             :   ///
     655             :   /// \warning Altering this buffer outside of the constructor of this class
     656             :   /// results in undefined behavior! This should be supplied by const reference
     657             :   /// once there is a convenient method of producing a const view of a vector
     658             :   /// type.
     659           1 :   DataVector& get_time_buffer() override { return time_buffer_; }
     660             : 
     661           0 :   bool has_version_history() const override { return true; }
     662             : 
     663             :   /// Serialization for Charm++.
     664           1 :   void pup(PUP::er& p) override;
     665             : 
     666             :  private:
     667           0 :   std::optional<double> extraction_radius_ = std::nullopt;
     668           0 :   size_t l_max_ = 0;
     669             : 
     670           0 :   h5::H5File<h5::AccessType::ReadOnly> cce_data_file_;
     671           0 :   std::string filename_;
     672             : 
     673             :   tuples::tagged_tuple_from_typelist<
     674             :       db::wrap_tags_in<Tags::detail::InputDataSet, klein_gordon_input_tags>>
     675           0 :       dataset_names_;
     676             : 
     677             :   // stores all the times in the input file
     678           0 :   DataVector time_buffer_;
     679             : };
     680             : }  // namespace Cce

Generated by: LCOV version 1.14