SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/ApparentHorizonFinder - FastFlow.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 6.8 % 73 5
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 <limits>
       8              : #include <ostream>
       9              : #include <utility>
      10              : 
      11              : #include "DataStructures/Tensor/TypeAliases.hpp"
      12              : #include "Options/Options.hpp"
      13              : #include "Options/String.hpp"
      14              : #include "Utilities/ForceInline.hpp"
      15              : #include "Utilities/TMPL.hpp"
      16              : 
      17              : /// \cond
      18              : class DataVector;
      19              : namespace PUP {
      20              : class er;
      21              : }  // namespace PUP
      22              : namespace gsl {
      23              : template <class T>
      24              : class not_null;
      25              : }  // namespace gsl
      26              : namespace ylm {
      27              : template <typename>
      28              : class Strahlkorper;
      29              : }  // namespace ylm
      30              : /// \endcond
      31              : 
      32              : /// \ingroup SurfacesGroup
      33              : /// \brief Fast flow method for finding apparent horizons.
      34              : ///
      35              : /// \details Based on \cite Gundlach1997us.
      36              : //  The method is iterative.
      37            1 : class FastFlow {
      38              :  public:
      39            0 :   enum class FlowType { Jacobi, Curvature, Fast };
      40              : 
      41              :   // Error conditions are negative, successes are nonnegative
      42            0 :   enum class Status {
      43              :     // SuccessfulIteration means we should iterate again.
      44              :     SuccessfulIteration = 0,
      45              :     // The following indicate convergence, can stop iterating.
      46              :     AbsTol = 1,
      47              :     TruncationTol = 2,
      48              :     // The following indicate errors.
      49              :     MaxIts = -1,
      50              :     NegativeRadius = -2,
      51              :     DivergenceError = -3,
      52              :     InterpolationFailure = -4
      53              :   };
      54              : 
      55              :   /// Holds information about an iteration of the algorithm.
      56            1 :   struct IterInfo {
      57            0 :     size_t iteration{std::numeric_limits<size_t>::max()};
      58            0 :     double r_min{std::numeric_limits<double>::signaling_NaN()},
      59            0 :         r_max{std::numeric_limits<double>::signaling_NaN()},
      60            0 :         min_residual{std::numeric_limits<double>::signaling_NaN()},
      61            0 :         max_residual{std::numeric_limits<double>::signaling_NaN()},
      62            0 :         residual_ylm{std::numeric_limits<double>::signaling_NaN()},
      63            0 :         residual_mesh{std::numeric_limits<double>::signaling_NaN()};
      64              :   };
      65              : 
      66            0 :   struct Flow {
      67            0 :     using type = FlowType;
      68            0 :     static constexpr Options::String help = {
      69              :         "Flow method: Jacobi, Curvature, or Fast"};
      70            0 :     static type suggested_value() { return FlowType::Fast; }
      71              :   };
      72              : 
      73            0 :   struct Alpha {
      74            0 :     using type = double;
      75            0 :     static constexpr Options::String help = {
      76              :         "Alpha parameter in PRD 57, 863 (1998)"};
      77            0 :     static type suggested_value() { return 1.0; }
      78              :   };
      79              : 
      80            0 :   struct Beta {
      81            0 :     using type = double;
      82            0 :     static constexpr Options::String help = {
      83              :         "Beta parameter in PRD 57, 863 (1998)"};
      84            0 :     static type suggested_value() { return 0.5; }
      85              :   };
      86              : 
      87            0 :   struct AbsTol {
      88            0 :     using type = double;
      89            0 :     static constexpr Options::String help = {
      90              :         "Convergence found if R_{Y_lm} < AbsTol"};
      91            0 :     static type suggested_value() { return 1.e-12; }
      92              :   };
      93              : 
      94            0 :   struct TruncationTol {
      95            0 :     using type = double;
      96            0 :     static constexpr Options::String help = {
      97              :         "Convergence found if R_{Y_lm} < TruncationTol*R_{mesh}"};
      98            0 :     static type suggested_value() { return 1.e-2; }
      99              :   };
     100              : 
     101            0 :   struct DivergenceTol {
     102            0 :     using type = double;
     103            0 :     static constexpr Options::String help = {
     104              :         "Fraction that residual can increase before dying"};
     105            0 :     static type suggested_value() { return 1.2; }
     106            0 :     static type lower_bound() { return 1.0; }
     107              :   };
     108              : 
     109            0 :   struct DivergenceIter {
     110            0 :     using type = size_t;
     111            0 :     static constexpr Options::String help = {
     112              :         "Num iterations residual can increase before dying"};
     113            0 :     static type suggested_value() { return 5; }
     114              :   };
     115              : 
     116            0 :   struct MaxIts {
     117            0 :     using type = size_t;
     118            0 :     static constexpr Options::String help = {"Maximum number of iterations."};
     119            0 :     static type suggested_value() { return 100; }
     120              :   };
     121              : 
     122            0 :   using options = tmpl::list<Flow, Alpha, Beta, AbsTol, TruncationTol,
     123              :                              DivergenceTol, DivergenceIter, MaxIts>;
     124              : 
     125            0 :   static constexpr Options::String help{
     126              :       "Find a Strahlkorper using a 'fast flow' method.\n"
     127              :       "Based on Gundlach, PRD 57, 863 (1998).\n"
     128              :       "Expands the surface in terms of spherical harmonics Y_lm up to a given\n"
     129              :       "l_surface, and varies the coefficients S_lm where 0<=l<=l_surface to\n"
     130              :       "minimize the residual of the apparent horizon equation.  Also keeps\n"
     131              :       "another representation of the surface that is expanded up to\n"
     132              :       "l_mesh > l_surface.  Let R_{Y_lm} be the residual computed using the\n"
     133              :       "surface represented up to l_surface; this residual can in principle be\n"
     134              :       "lowered to machine roundoff by enough iterations. Let R_{mesh} be the\n"
     135              :       "residual computed using the surface represented up to l_mesh; this\n"
     136              :       "residual represents the truncation error, since l_mesh>l_surface and\n"
     137              :       "since coefficients S_lm with l>l_surface are not modified in the\n"
     138              :       "iteration.\n\n"
     139              :       "Convergence is achieved if R_{Y_lm}< TruncationTol*R_{mesh}, or if\n"
     140              :       "R_{Y_lm}<AbsTol, where TruncationTol and AbsTol are input parameters.\n"
     141              :       "If instead |R_{mesh}|_i > DivergenceTol * min_{j}(|R_{mesh}|_j) where\n"
     142              :       "i is the iteration index and j runs from 0 to i-DivergenceIter, then\n"
     143              :       "FastFlow exits with Status::DivergenceError.  Here DivergenceIter and\n"
     144              :       "DivergenceTol are input parameters."};
     145              : 
     146            0 :   FastFlow(Flow::type flow, Alpha::type alpha, Beta::type beta,
     147              :            AbsTol::type abs_tol, TruncationTol::type trunc_tol,
     148              :            DivergenceTol::type divergence_tol,
     149              :            DivergenceIter::type divergence_iter, MaxIts::type max_its);
     150              : 
     151            0 :   FastFlow() : FastFlow(FlowType::Fast, 1.0, 0.5, 1.e-12, 1.e-2, 1.2, 5, 100) {}
     152              : 
     153            0 :   FastFlow(const FastFlow& /*rhs*/) = default;
     154            0 :   FastFlow& operator=(const FastFlow& /*rhs*/) = default;
     155            0 :   FastFlow(FastFlow&& /*rhs*/) = default;
     156            0 :   FastFlow& operator=(FastFlow&& /*rhs*/) = default;
     157            0 :   ~FastFlow() = default;
     158              : 
     159              :   // NOLINTNEXTLINE(google-runtime-references)
     160            0 :   void pup(PUP::er& p);
     161              : 
     162              :   /// Evaluate residuals and compute the next iteration.  If
     163              :   /// Status==SuccessfulIteration, then `current_strahlkorper` is
     164              :   /// modified and `current_iteration()` is incremented.  Otherwise, we
     165              :   /// end with success or failure, and neither `current_strahlkorper`
     166              :   /// nor `current_iteration()` is changed.
     167              :   template <typename Frame>
     168            1 :   std::pair<Status, IterInfo> iterate_horizon_finder(
     169              :       gsl::not_null<ylm::Strahlkorper<Frame>*> current_strahlkorper,
     170              :       const tnsr::II<DataVector, 3, Frame>& upper_spatial_metric,
     171              :       const tnsr::ii<DataVector, 3, Frame>& extrinsic_curvature,
     172              :       const tnsr::Ijj<DataVector, 3, Frame>& christoffel_2nd_kind);
     173              : 
     174            0 :   size_t current_iteration() const { return current_iter_; }
     175              : 
     176              :   /// Given a Strahlkorper defined up to some maximum Y_lm l called
     177              :   /// l_surface, returns a larger value of l, l_mesh, that is used for
     178              :   /// evaluating convergence.
     179              :   template <typename Frame>
     180            1 :   size_t current_l_mesh(const ylm::Strahlkorper<Frame>& strahlkorper) const;
     181              : 
     182              :   /// Resets the finder.
     183            1 :   SPECTRE_ALWAYS_INLINE void reset_for_next_find() {
     184              :     current_iter_ = 0;
     185              :     previous_residual_mesh_norm_ = 0.0;
     186              :     min_residual_mesh_norm_ = std::numeric_limits<double>::max();
     187              :     iter_at_min_residual_mesh_norm_ = 0;
     188              :   }
     189              : 
     190              :  private:
     191            0 :   friend bool operator==(const FastFlow& /*lhs*/, const FastFlow& /*rhs*/);
     192            0 :   double alpha_, beta_, abs_tol_, trunc_tol_, divergence_tol_;
     193            0 :   size_t divergence_iter_, max_its_;
     194            0 :   FlowType flow_;
     195            0 :   size_t current_iter_;
     196            0 :   double previous_residual_mesh_norm_, min_residual_mesh_norm_;
     197            0 :   size_t iter_at_min_residual_mesh_norm_;
     198              : };
     199              : 
     200            0 : SPECTRE_ALWAYS_INLINE bool converged(const FastFlow::Status& status) {
     201              :   return static_cast<int>(status) > 0;
     202              : }
     203              : 
     204            0 : std::ostream& operator<<(std::ostream& os, const FastFlow::FlowType& flow_type);
     205              : 
     206            0 : std::ostream& operator<<(std::ostream& os, const FastFlow::Status& status);
     207              : 
     208            0 : SPECTRE_ALWAYS_INLINE bool operator!=(const FastFlow& lhs,
     209              :                                       const FastFlow& rhs) {
     210              :   return not(lhs == rhs);
     211              : }
     212              : 
     213              : template <>
     214            0 : struct Options::create_from_yaml<FastFlow::FlowType> {
     215              :   template <typename Metavariables>
     216            0 :   static FastFlow::FlowType create(const Options::Option& options) {
     217              :     return create<void>(options);
     218              :   }
     219              : };
     220              : template <>
     221            0 : FastFlow::FlowType Options::create_from_yaml<FastFlow::FlowType>::create<void>(
     222              :     const Options::Option& options);
        

Generated by: LCOV version 2.0-1