SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/ApparentHorizonFinder - FastFlow.hpp Hit Total Coverage
Commit: 965048f86d23c819715b3af1ca3f880c8145d4bb Lines: 5 73 6.8 %
Date: 2024-05-16 17:00: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 <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 1.14