SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/Convergence - HasConverged.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 45.8 % 24 11
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 <iosfwd>
       8              : #include <limits>
       9              : #include <optional>
      10              : #include <string>
      11              : 
      12              : #include "NumericalAlgorithms/Convergence/Criteria.hpp"
      13              : #include "NumericalAlgorithms/Convergence/Reason.hpp"
      14              : 
      15              : /// \cond
      16              : namespace PUP {
      17              : class er;
      18              : }  // namespace PUP
      19              : /// \endcond
      20              : 
      21              : namespace Convergence {
      22              : 
      23              : /*!
      24              :  * \brief Determine whether the `criteria` are met.
      25              :  *
      26              :  * \note This function assumes the `iteration_id` is that of the latest
      27              :  * completed step and that it is zero-indexed, where zero indicates the initial
      28              :  * state of the algorithm. Therefore, the `MaxIteration` criterion will match if
      29              :  * the `iteration_id` is equal or higher. For example, a `MaxIteration` of 0
      30              :  * means the algorithm should run no iterations, so it matches if the
      31              :  * `iteration_id` is 0 or higher since that's the initial state before any
      32              :  * steps have been performed. A `MaxIteration` of 1 matches if the
      33              :  * `iteration_id` is 1 or higher since one iteration is complete. At this point,
      34              :  * also the `residual_magnitude` reflects the state of the algorithm after
      35              :  * completion of the first iteration. The `initial_residual_magnitude` always
      36              :  * refers to the state before the first iteration has begun, i.e. where the
      37              :  * `iteration_id` is zero.
      38              :  *
      39              :  * \returns A `Convergence::Reason` if the criteria are met, or
      40              :  * `std::nullopt` otherwise. The possible convergence reasons are:
      41              :  *
      42              :  * - `Convergence::Reason::AbsoluteResidual` if the `residual_magnitude`
      43              :  *   meets the convergence criteria's `absolute_residual`.
      44              :  * - `Convergence::Reason::RelativeResidual` if `residual_magnitude /
      45              :  *   initial_residual_magnitude` meets the convergence criteria's
      46              :  *   `relative_residual`.
      47              :  * - `Convergence::Reason::MaxIterations` if the `iteration_id` is the
      48              :  *   convergence_criteria's `max_iterations` or higher. This is often
      49              :  *   interpreted as an error because the algorithm did not converge in the
      50              :  *   alloted number of iterations.
      51              :  */
      52            1 : std::optional<Reason> criteria_match(const Criteria& criteria,
      53              :                                      size_t iteration_id,
      54              :                                      double residual_magnitude,
      55              :                                      double initial_residual_magnitude);
      56              : 
      57              : /*!
      58              :  * \brief Signals convergence or termination of the algorithm.
      59              :  *
      60              :  * \details Evaluates to `true` if the algorithm has converged or terminated and
      61              :  * no further iterations should be performed. In this case, the `reason()`
      62              :  * member function provides more information. If `false`, calling `reason()` is
      63              :  * an error.
      64              :  *
      65              :  * The stream operator provides a human-readable description of the convergence
      66              :  * status.
      67              :  *
      68              :  * This type default-constructs to a state that signals the algorithm has
      69              :  * not yet converged.
      70              :  */
      71            1 : struct HasConverged {
      72              :  public:
      73            0 :   HasConverged() = default;
      74              :   /*!
      75              :    * \brief Determine whether the \p criteria are met by means of
      76              :    * `Convergence::criteria_match`.
      77              :    */
      78            1 :   HasConverged(const Criteria& criteria, size_t iteration_id,
      79              :                double residual_magnitude, double initial_residual_magnitude);
      80              : 
      81              :   /// Construct at a state where `iteration_id` iterations of a total of
      82              :   /// `num_iterations` have completed. Use when the algorithm is intended to run
      83              :   /// for a fixed number of iterations. The convergence `reason()` will be
      84              :   /// `Convergence::Reason::NumIterations`.
      85            1 :   HasConverged(size_t num_iterations, size_t iteration_id);
      86              : 
      87              :   /*!
      88              :    * \brief Construct a state manually.
      89              :    *
      90              :    * Currently only allows to construct a state with `Reason::Error`. Use the
      91              :    * other constructors for the other `Reason`s.
      92              :    */
      93            1 :   HasConverged(Reason reason, std::optional<std::string> error_message,
      94              :                size_t iteration_id);
      95              : 
      96            0 :   explicit operator bool() const { return static_cast<bool>(reason_); }
      97              : 
      98              :   /*!
      99              :    * \brief The reason the algorithm has converged.
     100              :    *
     101              :    * \warning Calling this function is an error if the algorithm has not yet
     102              :    * converged.
     103              :    */
     104            1 :   Reason reason() const;
     105              : 
     106              :   /*!
     107              :    * \brief Error message if reason is `Reason::Error`
     108              :    *
     109              :    * \warning You may only call this function if the `reason()` is
     110              :    * `Reason::Error`.
     111              :    */
     112            1 :   const std::string& error_message() const;
     113              : 
     114              :   /// The number of iterations the algorithm has completed
     115            1 :   size_t num_iterations() const;
     116              : 
     117              :   /// The residual magnitude after the last iteration. NaN if no iteration has
     118              :   /// completed yet.
     119            1 :   double residual_magnitude() const;
     120              : 
     121              :   /// The residual magnitude before the first iteration. NaN if this information
     122              :   /// is not available yet.
     123            1 :   double initial_residual_magnitude() const;
     124              : 
     125              :   /// Throw an exception if the `reason()` is `Reason::Error`.
     126            1 :   void check_for_error() const;
     127              : 
     128              :   // NOLINTNEXTLINE(google-runtime-references)
     129            0 :   void pup(PUP::er& p);
     130              : 
     131            0 :   friend bool operator==(const HasConverged& lhs, const HasConverged& rhs);
     132            0 :   friend bool operator!=(const HasConverged& lhs, const HasConverged& rhs);
     133              : 
     134            0 :   friend std::ostream& operator<<(std::ostream& os,
     135              :                                   const HasConverged& has_converged);
     136              : 
     137              :  private:
     138            0 :   std::optional<Reason> reason_{};
     139            0 :   std::optional<std::string> error_message_ = std::nullopt;
     140            0 :   Criteria criteria_{};
     141            0 :   size_t iteration_id_{};
     142            0 :   double residual_magnitude_ = std::numeric_limits<double>::quiet_NaN();
     143            0 :   double initial_residual_magnitude_ = std::numeric_limits<double>::quiet_NaN();
     144              : };
     145              : 
     146              : }  // namespace Convergence
        

Generated by: LCOV version 2.0-1