SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/Cce - WorldtubeDataManager.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 25.0 % 68 17
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 <algorithm>
       7              : #include <cstddef>
       8              : #include <memory>
       9              : #include <utility>
      10              : 
      11              : #include "DataStructures/ComplexModalVector.hpp"
      12              : #include "DataStructures/DataBox/Tag.hpp"
      13              : #include "Evolution/Systems/Cce/BoundaryData.hpp"
      14              : #include "Evolution/Systems/Cce/Tags.hpp"
      15              : #include "Evolution/Systems/Cce/WorldtubeBufferUpdater.hpp"
      16              : #include "NumericalAlgorithms/Interpolation/SpanInterpolator.hpp"
      17              : #include "Parallel/NodeLock.hpp"
      18              : #include "Utilities/ErrorHandling/Error.hpp"
      19              : #include "Utilities/Gsl.hpp"
      20              : #include "Utilities/Serialization/CharmPupable.hpp"
      21              : #include "Utilities/TMPL.hpp"
      22              : 
      23              : namespace Cce {
      24              : 
      25              : namespace detail {
      26              : 
      27              : template <typename InputTags>
      28              : void set_non_pupped_members(
      29              :     gsl::not_null<size_t*> time_span_start,
      30              :     gsl::not_null<size_t*> time_span_end,
      31              :     gsl::not_null<Variables<InputTags>*> coefficients_buffers,
      32              :     gsl::not_null<Variables<InputTags>*> interpolated_coefficients,
      33              :     size_t buffer_depth, size_t interpolator_length, size_t l_max);
      34              : 
      35              : template <typename InputTags>
      36              : void initialize_buffers(
      37              :     gsl::not_null<size_t*> buffer_depth,
      38              :     gsl::not_null<Variables<InputTags>*> coefficients_buffers,
      39              :     size_t buffer_size, size_t interpolator_length, size_t l_max);
      40              : 
      41              : template <typename InputTags, typename OutputTags>
      42              : void populate_hypersurface_boundary_data(
      43              :     gsl::not_null<Variables<OutputTags>*> boundary_data_variables,
      44              :     gsl::not_null<Variables<InputTags>*> interpolated_coefficients,
      45              :     gsl::not_null<Variables<InputTags>*> coefficients_buffers,
      46              :     gsl::not_null<size_t*> time_span_start,
      47              :     gsl::not_null<size_t*> time_span_end,
      48              :     gsl::not_null<Parallel::NodeLock*> hdf5_lock, double time,
      49              :     const std::unique_ptr<intrp::SpanInterpolator>& interpolator,
      50              :     const std::unique_ptr<WorldtubeBufferUpdater<InputTags>>& buffer_updater,
      51              :     size_t l_max, size_t buffer_depth);
      52              : }  // namespace detail
      53              : 
      54              : /// \cond
      55              : class MetricWorldtubeDataManager;
      56              : class BondiWorldtubeDataManager;
      57              : class KleinGordonWorldtubeDataManager;
      58              : /// \endcond
      59              : 
      60              : /*!
      61              :  *  \brief Abstract base class for managers of CCE worldtube data that is
      62              :  * provided in large time-series chunks, especially the type provided by input
      63              :  * h5 files. `BoundaryTags` is a `tmpl::list` of tags on the worldtube boundary.
      64              :  *
      65              :  *  \details The methods that are required to be overridden in the derived
      66              :  * classes are:
      67              :  *
      68              :  * - `WorldtubeDataManager::populate_hypersurface_boundary_data()`:
      69              :  *   updates the Variables passed by pointer to contain correct boundary data
      70              :  *   for the time value passed in. This function should update all of the tags
      71              :  *   in `Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>`.
      72              :  * - `WorldtubeDataManager::get_clone()`: clone function to obtain a
      73              :  *   `std::unique_ptr` of the base `WorldtubeDataManager`, needed to pass around
      74              :  *   the factory-created object.
      75              :  * - `WorldtubeDataManager::get_l_max()`: The override should return the
      76              :  *   `l_max` that it computes for the collocation data calculated during
      77              :  *   `WorldtubeDataManager::populate_hypersurface_boundary_data()`.
      78              :  * - `WorldtubeBufferUpdater::get_time_span()`: The override should return the
      79              :  *   `std::pair` of indices that represent the start and end point of the
      80              :  *   underlying data source. This is primarily used for monitoring the frequency
      81              :  *   and size of the buffer updates.
      82              :  */
      83              : template <typename BoundaryTags>
      84            1 : class WorldtubeDataManager : public PUP::able {
      85              :  public:
      86            0 :   using creatable_classes =
      87              :       tmpl::list<MetricWorldtubeDataManager, BondiWorldtubeDataManager,
      88              :                  KleinGordonWorldtubeDataManager>;
      89              : 
      90            0 :   WRAPPED_PUPable_abstract(WorldtubeDataManager);  // NOLINT
      91              : 
      92            0 :   virtual bool populate_hypersurface_boundary_data(
      93              :       gsl::not_null<Variables<BoundaryTags>*> boundary_data_variables,
      94              :       double time, gsl::not_null<Parallel::NodeLock*> hdf5_lock) const = 0;
      95              : 
      96            0 :   virtual std::unique_ptr<WorldtubeDataManager> get_clone() const = 0;
      97              : 
      98            0 :   virtual size_t get_l_max() const = 0;
      99              : 
     100            0 :   virtual std::pair<size_t, size_t> get_time_span() const = 0;
     101              : 
     102              :   /// \brief Use `interpolator` in place of the one supplied at construction
     103              :   /// when building the boundary value of `Du<Dr<BondiJ>>`.
     104              :   ///
     105              :   /// \details That boundary value is consumed only by the initial-data
     106              :   /// generator, which may want a different time-interpolation order from the
     107              :   /// one the evolution runs with. A manager that does not produce
     108              :   /// `Du<Dr<BondiJ>>` at all cannot honor the request, so rather than drop it
     109              :   /// silently the default implementation aborts; `nullptr` (nothing was asked
     110              :   /// for) is always accepted.
     111            1 :   virtual void set_du_dr_j_interpolator(
     112              :       std::unique_ptr<intrp::SpanInterpolator> interpolator) {
     113              :     if (interpolator != nullptr) {
     114              :       ERROR(
     115              :           "A `DuDrJInterpolator` was requested, but this worldtube data "
     116              :           "manager does not produce the `Du<Dr<BondiJ>>` boundary value that "
     117              :           "the option controls, so the request would have no effect. Only the "
     118              :           "Bondi-type worldtube data manager supports it; remove the option or "
     119              :           "supply Bondi-Sachs worldtube data.");
     120              :     }
     121              :   }
     122              : };
     123              : 
     124              : /*!
     125              :  * \brief Manages the cached buffer data associated with a CCE worldtube and
     126              :  * interpolates to requested time points to provide worldtube boundary data to
     127              :  * the main evolution routines.
     128              :  *
     129              :  * \details The maintained buffer will be maintained at a length that is set by
     130              :  * the `Interpolator` and the `buffer_depth` also passed to the constructor. A
     131              :  * longer depth will ensure that the buffer updater is called less frequently,
     132              :  * which is useful for slow updaters (e.g. those that perform file access).
     133              :  * The main functionality is provided by the
     134              :  * `WorldtubeDataManager::populate_hypersurface_boundary_data()` member
     135              :  * function that handles buffer updating and boundary computation.
     136              :  */
     137            1 : class MetricWorldtubeDataManager
     138              :     : public WorldtubeDataManager<
     139              :           Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>> {
     140            0 :   using input_tags = cce_metric_input_tags<ComplexModalVector>;
     141              : 
     142              :  public:
     143              :   // charm needs an empty constructor.
     144            0 :   MetricWorldtubeDataManager() = default;
     145              : 
     146            0 :   MetricWorldtubeDataManager(
     147              :       std::unique_ptr<WorldtubeBufferUpdater<input_tags>> buffer_updater,
     148              :       size_t l_max, size_t buffer_depth,
     149              :       std::unique_ptr<intrp::SpanInterpolator> interpolator,
     150              :       bool fix_spec_normalization);
     151              : 
     152            0 :   WRAPPED_PUPable_decl_template(MetricWorldtubeDataManager);  // NOLINT
     153              : 
     154            0 :   explicit MetricWorldtubeDataManager(CkMigrateMessage* /*unused*/) {}
     155              : 
     156              :   /*!
     157              :    * \brief Update the `boundary_data_box` entries for all tags in
     158              :    * `Tags::characteristic_worldtube_boundary_tags` to the boundary data at
     159              :    * `time`.
     160              :    *
     161              :    * \details First, if the stored buffer requires updating, it will be updated
     162              :    * via the `buffer_updater_` supplied in the constructor. Then, each of the
     163              :    * spatial metric, shift, lapse, and each of their radial and time derivatives
     164              :    * are interpolated across buffer points to the requested time value (via the
     165              :    * `Interpolator` provided in the constructor). Finally, that data is supplied
     166              :    * to the `create_bondi_boundary_data()`, which updates the
     167              :    * `boundary_data_box` with the Bondi spin-weighted scalars determined from
     168              :    * the interpolated Cartesian data.
     169              :    *
     170              :    * Returns `true` if the time can be supplied from the `buffer_updater_`, and
     171              :    * `false` otherwise. No tags are updated if `false` is returned.
     172              :    */
     173            1 :   bool populate_hypersurface_boundary_data(
     174              :       gsl::not_null<Variables<
     175              :           Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>>*>
     176              :           boundary_data_variables,
     177              :       double time, gsl::not_null<Parallel::NodeLock*> hdf5_lock) const override;
     178              : 
     179            0 :   std::unique_ptr<WorldtubeDataManager> get_clone() const override;
     180              : 
     181              :   /// retrieves the l_max that will be supplied to the \ref DataBoxGroup in
     182              :   /// `populate_hypersurface_boundary_data()`
     183            1 :   size_t get_l_max() const override { return l_max_; }
     184              : 
     185              :   /// retrieves the current time span associated with the `buffer_updater_` for
     186              :   /// diagnostics
     187            1 :   std::pair<size_t, size_t> get_time_span() const override;
     188              : 
     189              :   /// Serialization for Charm++.
     190            1 :   void pup(PUP::er& p) override;  // NOLINT
     191              : 
     192              :  private:
     193            0 :   std::unique_ptr<WorldtubeBufferUpdater<input_tags>> buffer_updater_;
     194              :   // NOLINTNEXTLINE(spectre-mutable)
     195            0 :   mutable size_t time_span_start_ = 0;
     196              :   // NOLINTNEXTLINE(spectre-mutable)
     197            0 :   mutable size_t time_span_end_ = 0;
     198            0 :   size_t l_max_ = 0;
     199            0 :   bool fix_spec_normalization_ = false;
     200              : 
     201              :   // These buffers are just kept around to avoid allocations; they're
     202              :   // updated every time a time is requested
     203              :   // NOLINTNEXTLINE(spectre-mutable)
     204            0 :   mutable Variables<input_tags> interpolated_coefficients_;
     205              : 
     206              :   // note: buffers store data in a 'time-varies-fastest' manner
     207              :   // NOLINTNEXTLINE(spectre-mutable)
     208            0 :   mutable Variables<input_tags> coefficients_buffers_;
     209              : 
     210            0 :   size_t buffer_depth_ = 0;
     211              : 
     212            0 :   std::unique_ptr<intrp::SpanInterpolator> interpolator_;
     213              : };
     214              : 
     215              : /*!
     216              :  * \brief Manages the bondi cached buffer dataset associated with a CCE
     217              :  * worldtube and interpolates to requested time points to provide worldtube
     218              :  * boundary data to the main evolution routines.
     219              :  *
     220              :  * \details The maintained buffer will be kept at a length that is set by
     221              :  * the `Interpolator` and the `buffer_depth` also passed to the constructor. A
     222              :  * longer depth will ensure that the buffer updater is called less frequently,
     223              :  * which is useful for slow updaters (e.g. those that perform file access).
     224              :  * The main functionality is provided by the
     225              :  * `WorldtubeDataManager::populate_hypersurface_boundary_data()` member
     226              :  * function that handles buffer updating and boundary computation. This version
     227              :  * of the data manager handles the 9 scalars of
     228              :  * `worldtube_boundary_tags_for_writing<Spectral::Swsh::Tags::SwshTransform>`,
     229              :  * rather than direct metric components handled by `WorldtubeDataManager`. The
     230              :  * set of 9 scalars is a far leaner (factor of ~4) data storage format.
     231              :  */
     232            1 : class BondiWorldtubeDataManager
     233              :     : public WorldtubeDataManager<
     234              :           Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>> {
     235              :  public:
     236              :   // charm needs an empty constructor.
     237            0 :   BondiWorldtubeDataManager() = default;
     238              : 
     239            0 :   BondiWorldtubeDataManager(
     240              :       std::unique_ptr<
     241              :           WorldtubeBufferUpdater<Tags::worldtube_boundary_tags_for_writing<
     242              :               Spectral::Swsh::Tags::SwshTransform>>>
     243              :           buffer_updater,
     244              :       size_t l_max, size_t buffer_depth,
     245              :       std::unique_ptr<intrp::SpanInterpolator> interpolator);
     246              : 
     247            0 :   WRAPPED_PUPable_decl_template(BondiWorldtubeDataManager);  // NOLINT
     248              : 
     249            0 :   explicit BondiWorldtubeDataManager(CkMigrateMessage* /*unused*/) {}
     250              : 
     251              :   /*!
     252              :    * \brief Update the `boundary_data_box` entries for all tags in
     253              :    * `Tags::characteristic_worldtube_boundary_tags` to the boundary data at
     254              :    * `time`.
     255              :    *
     256              :    * \details First, if the stored buffer requires updating, it will be updated
     257              :    * via the `buffer_updater_` supplied in the constructor. Then, each of the
     258              :    * 9 spin-weighted scalars in
     259              :    * `worldtube_boundary_tags_for_writing<Spectral::Swsh::Tags::SwshTransform>`
     260              :    * are interpolated across buffer points to the requested time value (via the
     261              :    * `Interpolator` provided in the constructor). Finally, the remaining two
     262              :    * scalars not directly supplied in the input file are calculated in-line and
     263              :    * put in the \ref DataBoxGroup.
     264              :    *
     265              :    * Returns `true` if the time can be supplied from the `buffer_updater_`, and
     266              :    * `false` otherwise. No tags are updated if `false` is returned.
     267              :    */
     268            1 :   bool populate_hypersurface_boundary_data(
     269              :       gsl::not_null<Variables<
     270              :           Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>>*>
     271              :           boundary_data_variables,
     272              :       double time, gsl::not_null<Parallel::NodeLock*> hdf5_lock) const override;
     273              : 
     274            0 :   std::unique_ptr<WorldtubeDataManager> get_clone() const override;
     275              : 
     276              :   /// retrieves the l_max that will be supplied to the \ref DataBoxGroup in
     277              :   /// `populate_hypersurface_boundary_data()`
     278            1 :   size_t get_l_max() const override { return l_max_; }
     279              : 
     280              :   /// retrieves the current time span associated with the `buffer_updater_` for
     281              :   /// diagnostics
     282            1 :   std::pair<size_t, size_t> get_time_span() const override;
     283              : 
     284              :   /// \brief Use `interpolator` in place of `interpolator_` for the time
     285              :   /// derivative that produces the `Du<Dr<BondiJ>>` boundary value.
     286              :   ///
     287              :   /// \details Passing `nullptr` (the default state) leaves that derivative on
     288              :   /// `interpolator_`. This derivative is taken inside the window the evolution
     289              :   /// already caches, which `interpolator_` sizes, so `interpolator` must not
     290              :   /// need a wider stencil than `interpolator_` does; it is meant for a *lower*
     291              :   /// order than the evolution runs with. A wider one is rejected here rather
     292              :   /// than left to fail deep inside the interpolator.
     293            1 :   void set_du_dr_j_interpolator(
     294              :       std::unique_ptr<intrp::SpanInterpolator> interpolator) override;
     295              : 
     296              :   /// Serialization for Charm++.
     297            1 :   void pup(PUP::er& p) override;  // NOLINT
     298              : 
     299              :  private:
     300              :   // Compute the boundary value of `Du<Dr<BondiJ>>` at the requested time by
     301              :   // numerically time-differentiating the buffered `Dr<BondiJ>` with
     302              :   // `interpolator_`, holding the angular coordinate fixed (i.e. following the
     303              :   // worldtube). This is the time derivative at constant numerical coordinate
     304              :   // y = -1, i.e. d_ubreve d_r J|_Gamma = d/du (d_r J|_Gamma), and is *not* a
     305              :   // derivative at constant Bondi r.
     306            0 :   void populate_boundary_du_dr_j(
     307              :       gsl::not_null<Variables<
     308              :           Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>>*>
     309              :           boundary_data_variables,
     310              :       double time) const;
     311              : 
     312              :   std::unique_ptr<
     313              :       WorldtubeBufferUpdater<Tags::worldtube_boundary_tags_for_writing<
     314              :           Spectral::Swsh::Tags::SwshTransform>>>
     315            0 :       buffer_updater_;
     316              :   // NOLINTNEXTLINE(spectre-mutable)
     317            0 :   mutable size_t time_span_start_ = 0;
     318              :   // NOLINTNEXTLINE(spectre-mutable)
     319            0 :   mutable size_t time_span_end_ = 0;
     320            0 :   size_t l_max_ = 0;
     321              : 
     322              :   // These buffers are just kept around to avoid allocations; they're
     323              :   // updated every time a time is requested
     324              :   // NOLINTNEXTLINE(spectre-mutable)
     325              :   mutable Variables<Tags::worldtube_boundary_tags_for_writing<
     326              :       Spectral::Swsh::Tags::SwshTransform>>
     327            0 :       interpolated_coefficients_;
     328              : 
     329              :   // note: buffers store data in an 'time-varies-fastest' manner
     330              :   // NOLINTNEXTLINE(spectre-mutable)
     331              :   mutable Variables<Tags::worldtube_boundary_tags_for_writing<
     332              :       Spectral::Swsh::Tags::SwshTransform>>
     333            0 :       coefficients_buffers_;
     334              : 
     335            0 :   size_t buffer_depth_ = 0;
     336              : 
     337            0 :   std::unique_ptr<intrp::SpanInterpolator> interpolator_;
     338              : 
     339              :   // Used instead of `interpolator_` for the `Du<Dr<BondiJ>>` time derivative
     340              :   // when the initial-data generator asks for its own; null otherwise.
     341            0 :   std::unique_ptr<intrp::SpanInterpolator> du_dr_j_interpolator_;
     342              : };
     343              : 
     344            0 : class KleinGordonWorldtubeDataManager
     345              :     : public WorldtubeDataManager<Tags::klein_gordon_worldtube_boundary_tags> {
     346              :  public:
     347              :   // charm needs an empty constructor.
     348            0 :   KleinGordonWorldtubeDataManager() = default;
     349              : 
     350            0 :   KleinGordonWorldtubeDataManager(
     351              :       std::unique_ptr<WorldtubeBufferUpdater<klein_gordon_input_tags>>
     352              :           buffer_updater,
     353              :       size_t l_max, size_t buffer_depth,
     354              :       std::unique_ptr<intrp::SpanInterpolator> interpolator);
     355              : 
     356            0 :   WRAPPED_PUPable_decl_template(KleinGordonWorldtubeDataManager);  // NOLINT
     357              : 
     358            0 :   explicit KleinGordonWorldtubeDataManager(CkMigrateMessage* /*unused*/) {}
     359              : 
     360              :   /*!
     361              :    * \brief Update the `boundary_data_box` entries for all tags in
     362              :    * `Tags::klein_gordon_worldtube_boundary_tags` to the boundary data at
     363              :    * `time`.
     364              :    *
     365              :    * \details First, if the stored buffer requires updating, it will be updated
     366              :    * via the `buffer_updater_` supplied in the constructor. Then, each of the
     367              :    * 2 spin-weighted scalars in `Tags::klein_gordon_worldtube_boundary_tags`
     368              :    * are interpolated across buffer points to the requested time value (via the
     369              :    * `Interpolator` provided in the constructor).
     370              :    *
     371              :    * Returns `true` if the time can be supplied from the `buffer_updater_`, and
     372              :    * `false` otherwise. No tags are updated if `false` is returned.
     373              :    */
     374            1 :   bool populate_hypersurface_boundary_data(
     375              :       gsl::not_null<Variables<Tags::klein_gordon_worldtube_boundary_tags>*>
     376              :           boundary_data_variables,
     377              :       double time, gsl::not_null<Parallel::NodeLock*> hdf5_lock) const override;
     378              : 
     379            0 :   std::unique_ptr<WorldtubeDataManager> get_clone() const override;
     380              : 
     381              :   /// retrieves the l_max that will be supplied to the \ref DataBoxGroup in
     382              :   /// `populate_hypersurface_boundary_data()`
     383            1 :   size_t get_l_max() const override { return l_max_; }
     384              : 
     385              :   /// retrieves the current time span associated with the `buffer_updater_` for
     386              :   /// diagnostics
     387            1 :   std::pair<size_t, size_t> get_time_span() const override;
     388              : 
     389              :   /// Serialization for Charm++.
     390            1 :   void pup(PUP::er& p) override;  // NOLINT
     391              : 
     392              :  private:
     393              :   std::unique_ptr<WorldtubeBufferUpdater<klein_gordon_input_tags>>
     394            0 :       buffer_updater_;
     395              :   // NOLINTNEXTLINE(spectre-mutable)
     396            0 :   mutable size_t time_span_start_ = 0;
     397              :   // NOLINTNEXTLINE(spectre-mutable)
     398            0 :   mutable size_t time_span_end_ = 0;
     399            0 :   size_t l_max_ = 0;
     400              : 
     401              :   // These buffers are just kept around to avoid allocations; they're
     402              :   // updated every time a time is requested
     403              :   // NOLINTNEXTLINE(spectre-mutable)
     404            0 :   mutable Variables<klein_gordon_input_tags> interpolated_coefficients_;
     405              : 
     406              :   // note: buffers store data in an 'time-varies-fastest' manner
     407              :   // NOLINTNEXTLINE(spectre-mutable)
     408            0 :   mutable Variables<klein_gordon_input_tags> coefficients_buffers_;
     409              : 
     410            0 :   size_t buffer_depth_ = 0;
     411              : 
     412            0 :   std::unique_ptr<intrp::SpanInterpolator> interpolator_;
     413              : };
     414              : }  // namespace Cce
        

Generated by: LCOV version 2.0-1