SpECTRE Documentation Coverage Report
Current view: top level - IO/Exporter - ModalTimeSeriesReader.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 52.2 % 23 12
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 <memory>
       8              : #include <optional>
       9              : #include <string>
      10              : #include <unordered_map>
      11              : #include <utility>
      12              : #include <variant>
      13              : #include <vector>
      14              : 
      15              : #include "Domain/Structure/ElementId.hpp"
      16              : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
      17              : 
      18              : namespace spectre::Exporter {
      19              : 
      20              : /*!
      21              :  * \brief Reads time series of modal coefficients from volume data files.
      22              :  *
      23              :  * This class reads tensor components written by multiple observations of a
      24              :  * volume data subfile, transforms the nodal data of each element to modal
      25              :  * coefficients, and returns the time series of every modal coefficient one
      26              :  * element at a time. Reading element-by-element keeps memory usage low: only
      27              :  * a single element's time series is held in memory at once, so the volume
      28              :  * data never has to be loaded into memory as a whole.
      29              :  *
      30              :  * Request the time series with `modal_time_series()`, e.g.:
      31              :  *
      32              :  * \snippet Test_ModalTimeSeriesReader.cpp modal_time_series_reader_example
      33              :  *
      34              :  * The observation times must be uniformly spaced. Multiple files can be used
      35              :  * when the elements of each observation are distributed across files, such as
      36              :  * files written by different nodes. All files must contain the same
      37              :  * observations in the requested time interval, and each element must reside
      38              :  * in the same file with the same mesh for all observations. Files from
      39              :  * different simulation segments must be joined first, with overlapping
      40              :  * observations removed. Adaptive mesh refinement and element migration
      41              :  * between files (e.g. by load balancing) are not supported yet and raise
      42              :  * errors.
      43              :  *
      44              :  * Only the Legendre basis is supported for now.
      45              :  *
      46              :  * \note When observing fields on a smaller mesh, use the `ProjectToMesh`
      47              :  * option of the ObserveFields event to ensure the data is truncated cleanly
      48              :  * in modal space. Do not use `InterpolateToMesh` as this creates a
      49              :  * catastrophic aliasing error.
      50              :  */
      51              : template <size_t Dim>
      52            1 : class ModalTimeSeriesReader {
      53              :  public:
      54              :   /// Modal coefficient time series of a single element, indexed as
      55              :   /// `series[component][mode][observation]`. Modes are ordered by the
      56              :   /// collapsed index of the element's mesh.
      57            1 :   using Series = std::vector<std::vector<std::vector<double>>>;
      58              : 
      59              :   /*!
      60              :    * \brief Construct from one or more volume files.
      61              :    *
      62              :    * Reads and validates metadata from all files. The volume data itself is
      63              :    * only read when calling `modal_time_series()`.
      64              :    *
      65              :    * \param volume_files_or_glob A list of volume H5 files, or a glob string
      66              :    *     that resolves to volume files. The files can distribute elements of
      67              :    *     the same observations across nodes, but files from different
      68              :    *     simulation segments must be joined first.
      69              :    * \param subfile_name The name of the volume data subfile in the H5 files.
      70              :    * \param tensor_components Tensor component names to read. Each component
      71              :    *     must exist in every file at every observation.
      72              :    * \param start_time Optional lower bound to restrict observations.
      73              :    * \param end_time Optional upper bound to restrict observations.
      74              :    */
      75            1 :   ModalTimeSeriesReader(const std::variant<std::vector<std::string>,
      76              :                                            std::string>& volume_files_or_glob,
      77              :                         std::string subfile_name,
      78              :                         std::vector<std::string> tensor_components,
      79              :                         std::optional<double> start_time = std::nullopt,
      80              :                         std::optional<double> end_time = std::nullopt);
      81              : 
      82            0 :   ModalTimeSeriesReader(ModalTimeSeriesReader&&);
      83            0 :   ModalTimeSeriesReader& operator=(ModalTimeSeriesReader&&);
      84            0 :   ModalTimeSeriesReader(const ModalTimeSeriesReader&) = delete;
      85            0 :   ModalTimeSeriesReader& operator=(const ModalTimeSeriesReader&) = delete;
      86            0 :   ~ModalTimeSeriesReader();
      87              : 
      88              :   /// Time of the first observation (after filtering by `start_time` and
      89              :   /// `end_time`)
      90            1 :   double start_time() const { return obs_ids_and_times_.front().second; }
      91              : 
      92              :   /// Uniform spacing between observation times
      93            1 :   double time_step() const { return time_step_; }
      94              : 
      95              :   /// Number of observations (after filtering by `start_time` and `end_time`)
      96            1 :   size_t num_observations() const { return obs_ids_and_times_.size(); }
      97              : 
      98              :   /// The tensor components that will be read
      99            1 :   const std::vector<std::string>& tensor_components() const {
     100              :     return tensor_components_;
     101              :   }
     102              : 
     103              :   /*!
     104              :    * \brief All elements in the volume files and their meshes.
     105              :    *
     106              :    * The elements are grouped by the volume file they reside in. Requesting
     107              :    * the `modal_time_series()` in this order avoids re-reading per-file
     108              :    * metadata.
     109              :    */
     110            1 :   const std::vector<std::pair<ElementId<Dim>, Mesh<Dim>>>& elements() const {
     111              :     return elements_;
     112              :   }
     113              : 
     114              :   /*!
     115              :    * \brief The time series of all modal coefficients of all tensor
     116              :    * components of the given element.
     117              :    *
     118              :    * Metadata of the file in which the element resides is cached between
     119              :    * calls, so requesting elements in the order of `elements()` is most
     120              :    * efficient (this is also why this function is not const). Only the subset
     121              :    * of each tensor component dataset belonging to this element is read.
     122              :    */
     123            1 :   Series modal_time_series(const ElementId<Dim>& element_id);
     124              : 
     125              :  private:
     126              :   struct FileCache;
     127              : 
     128            0 :   std::vector<std::string> filenames_;
     129            0 :   std::string subfile_name_;
     130            0 :   std::vector<std::string> tensor_components_;
     131            0 :   std::vector<std::pair<size_t, double>> obs_ids_and_times_;
     132            0 :   double time_step_{};
     133              :   /// Elements grouped by file, in the order they appear in the files
     134            1 :   std::vector<std::pair<ElementId<Dim>, Mesh<Dim>>> elements_;
     135              :   /// Mesh and file index of each element for fast lookup
     136              :   std::unordered_map<ElementId<Dim>, std::pair<Mesh<Dim>, size_t>>
     137            1 :       element_info_;
     138              :   /// Metadata of the most recently accessed file
     139            1 :   std::unique_ptr<FileCache> file_cache_;
     140              : };
     141              : 
     142              : }  // namespace spectre::Exporter
        

Generated by: LCOV version 2.0-1