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

Generated by: LCOV version 2.0-1