SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/Interpolation - UniformCardinalBSpline.hpp Hit Total Coverage
Commit: ecb8a275e1aebab77dcce48a5e098ed4e486ab4b Lines: 9 19 47.4 %
Date: 2026-08-22 01:05:40
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 <array>
       7             : #include <boost/math/interpolators/cardinal_cubic_b_spline.hpp>
       8             : #include <cstddef>
       9             : #include <optional>
      10             : #include <utility>
      11             : #include <vector>
      12             : 
      13             : /// \cond
      14             : namespace PUP {
      15             : class er;
      16             : }  // namespace PUP
      17             : /// \endcond
      18             : 
      19             : namespace intrp {
      20             : 
      21             : /*!
      22             :  * \ingroup NumericalAlgorithmsGroup
      23             :  * \brief A cubic B-spline interpolant of uniformly spaced samples
      24             :  *
      25             :  * Interpolates samples \f$f_i = f(t_0 + i \Delta t)\f$, \f$i = 0, \ldots,
      26             :  * N-1\f$, with a cubic B-spline. The interpolation error decreases as
      27             :  * \f$\mathcal{O}(\Delta t^4)\f$ for smooth data. This class wraps
      28             :  * `boost::math::interpolators::cardinal_cubic_b_spline` and adds:
      29             :  *
      30             :  * - Serialization: the samples, start time, and time step fully determine the
      31             :  *   interpolant, so it can be sent in a `pup` and rebuilt on the receiving
      32             :  *   side.
      33             :  * - Clamped evaluation: evaluation is clamped to the bounds of the sampled
      34             :  *   interval, so times that fall outside the interval by roundoff evaluate
      35             :  *   to the boundary values instead of extrapolating the spline. Times
      36             :  *   outside the bounds beyond roundoff trigger an `ASSERT` in debug builds.
      37             :  *
      38             :  * Here is an example how to use this class:
      39             :  *
      40             :  * \snippet Test_UniformCardinalBSpline.cpp uniform_cardinal_b_spline_example
      41             :  *
      42             :  * \note Requires Boost 1.81 or newer at runtime because of an accuracy fix
      43             :  * for the estimate of the derivative at the right endpoint in the Boost
      44             :  * implementation, see
      45             :  * https://github.com/boostorg/math/commit/4809e714d4806c07da3a3def0c4550daa0529b8d.
      46             :  * The constructor raises an error for older Boost versions.
      47             :  */
      48           1 : class UniformCardinalBSpline {
      49             :  public:
      50             :   /*!
      51             :    * \brief Construct from uniformly spaced samples.
      52             :    *
      53             :    * \param values The sampled function values \f$f(t_0 + i \Delta t)\f$. At
      54             :    *     least 5 samples are required.
      55             :    * \param start_time The time \f$t_0\f$ of the first sample.
      56             :    * \param time_step The (positive) spacing \f$\Delta t\f$ between samples.
      57             :    */
      58           1 :   UniformCardinalBSpline(std::vector<double> values, double start_time,
      59             :                          double time_step);
      60             : 
      61           0 :   UniformCardinalBSpline() = default;
      62             : 
      63             :   /// Evaluate the interpolant at `time`, clamped to the `bounds()`
      64           1 :   double operator()(double time) const;
      65             : 
      66             :   /// The sampled function values
      67           1 :   const std::vector<double>& values() const { return values_; }
      68             : 
      69             :   /// The time of the first sample
      70           1 :   double start_time() const { return start_time_; }
      71             : 
      72             :   /// The spacing between samples
      73           1 :   double time_step() const { return time_step_; }
      74             : 
      75             :   /// The first and last sample time
      76           1 :   std::array<double, 2> bounds() const;
      77             : 
      78             :   // NOLINTNEXTLINE(google-runtime-references)
      79           0 :   void pup(PUP::er& p);
      80             : 
      81             :  private:
      82           0 :   void initialize_interpolant();
      83             : 
      84           0 :   std::vector<double> values_{};
      85           0 :   double start_time_{};
      86           0 :   double time_step_{};
      87             :   std::optional<boost::math::interpolators::cardinal_cubic_b_spline<double>>
      88           0 :       interpolant_{};
      89             : };
      90             : 
      91           0 : bool operator==(const UniformCardinalBSpline& lhs,
      92             :                 const UniformCardinalBSpline& rhs);
      93             : 
      94           0 : bool operator!=(const UniformCardinalBSpline& lhs,
      95             :                 const UniformCardinalBSpline& rhs);
      96             : 
      97             : /*!
      98             :  * \ingroup NumericalAlgorithmsGroup
      99             :  * \brief Estimate the maximum interpolation error of a
     100             :  * `intrp::UniformCardinalBSpline` through the given samples.
     101             :  *
     102             :  * Measures the deviation of an interpolant through every other sample from
     103             :  * the sampled values at the sample times, where the error of that coarser
     104             :  * interpolant peaks. For smooth data the interpolation error of a cubic
     105             :  * spline decreases by a factor of 16 when the step size is halved, so the
     106             :  * error of the interpolant through all samples is about 1/16 of the measured
     107             :  * deviation for smooth data in the convergent regime. The deviation is divided
     108             :  * by only 8 to obtain a conservative estimate, accounting for nonsmooth data
     109             :  * that converges slower.
     110             :  *
     111             :  * \param values The sampled function values. At least 9 samples are required
     112             :  *     so the coarser interpolant has at least 5.
     113             :  * \param start_time The time of the first sample.
     114             :  * \param time_step The (positive) spacing between samples.
     115             :  */
     116           1 : double estimate_interpolation_error(const std::vector<double>& values,
     117             :                                     double start_time, double time_step);
     118             : 
     119             : /*!
     120             :  * \ingroup NumericalAlgorithmsGroup
     121             :  * \brief Compress uniformly spaced samples into a
     122             :  * `intrp::UniformCardinalBSpline` with fewer points that reproduces the
     123             :  * samples to the given tolerance.
     124             :  *
     125             :  * Builds a reference interpolant through all samples and resamples it on
     126             :  * coarser uniform grids over the same time interval, starting with 6 points
     127             :  * and doubling until the resampled interpolant reproduces the input samples
     128             :  * to within `absolute_tolerance` at the sample times. This reduces memory
     129             :  * for smooth, densely sampled data, e.g. time series of spectral modes in a
     130             :  * simulation.
     131             :  *
     132             :  * \returns The compressed interpolant and its maximum absolute deviation
     133             :  * from the input samples at the sample times.
     134             :  *
     135             :  * If the tolerance cannot be met with fewer points than the input, the
     136             :  * returned interpolant holds the original samples. Its deviation from the
     137             :  * samples at the sample times vanishes by construction, so the returned
     138             :  * error is the error of the last (coarser) candidate in the doubling search
     139             :  * as a conservative estimate, and may exceed the tolerance. Inputs with 6 or
     140             :  * fewer samples are returned unchanged with zero error.
     141             :  *
     142             :  * \param values The sampled function values. At least 5 samples are required.
     143             :  * \param start_time The time of the first sample.
     144             :  * \param time_step The (positive) spacing between samples.
     145             :  * \param absolute_tolerance Maximum allowed absolute deviation of the
     146             :  *     compressed interpolant from the input samples.
     147             :  */
     148           1 : std::pair<UniformCardinalBSpline, double> compress_to_tolerance(
     149             :     const std::vector<double>& values, double start_time, double time_step,
     150             :     double absolute_tolerance);
     151             : 
     152             : }  // namespace intrp

Generated by: LCOV version 1.14