SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/Cce - WorldtubeBufferUpdater.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 22.3 % 121 27
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 <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 "DataStructures/TaggedTuple.hpp"
      23              : #include "Evolution/Systems/Cce/BoundaryData.hpp"
      24              : #include "Evolution/Systems/Cce/Tags.hpp"
      25              : #include "IO/H5/Dat.hpp"
      26              : #include "IO/H5/File.hpp"
      27              : #include "IO/H5/Version.hpp"
      28              : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshTags.hpp"
      29              : #include "Options/Options.hpp"
      30              : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
      31              : #include "Utilities/ErrorHandling/Assert.hpp"
      32              : #include "Utilities/Gsl.hpp"
      33              : #include "Utilities/Serialization/CharmPupable.hpp"
      34              : #include "Utilities/Serialization/PupStlCpp17.hpp"
      35              : #include "Utilities/TMPL.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 2.0-1