SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/ApparentHorizonFinder - InterpolationTarget.hpp Hit Total Coverage
Commit: 1f2210958b4f38fdc0400907ee7c6d5af5111418 Lines: 6 64 9.4 %
Date: 2025-12-05 05:03:31
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 <string>
       9             : #include <tuple>
      10             : #include <type_traits>
      11             : #include <unordered_map>
      12             : #include <unordered_set>
      13             : #include <utility>
      14             : 
      15             : #include "DataStructures/DataBox/DataBox.hpp"
      16             : #include "DataStructures/DataBox/Tag.hpp"
      17             : #include "DataStructures/Tags/TempTensor.hpp"
      18             : #include "DataStructures/Variables.hpp"
      19             : #include "Domain/Creators/DomainCreator.hpp"
      20             : #include "Domain/Creators/OptionTags.hpp"
      21             : #include "Domain/Structure/BlockGroups.hpp"
      22             : #include "IO/Logging/Tags.hpp"
      23             : #include "IO/Logging/Verbosity.hpp"
      24             : #include "NumericalAlgorithms/SphericalHarmonics/Strahlkorper.hpp"
      25             : #include "NumericalAlgorithms/SphericalHarmonics/StrahlkorperFunctions.hpp"
      26             : #include "NumericalAlgorithms/SphericalHarmonics/Tags.hpp"
      27             : #include "Options/Context.hpp"
      28             : #include "Options/String.hpp"
      29             : #include "Parallel/GlobalCache.hpp"
      30             : #include "ParallelAlgorithms/ApparentHorizonFinder/FastFlow.hpp"
      31             : #include "ParallelAlgorithms/ApparentHorizonFinder/OptionTags.hpp"
      32             : #include "ParallelAlgorithms/ApparentHorizonFinder/Tags.hpp"
      33             : #include "ParallelAlgorithms/Initialization/MutateAssign.hpp"
      34             : #include "ParallelAlgorithms/Interpolation/InterpolationTargetDetail.hpp"
      35             : #include "ParallelAlgorithms/Interpolation/Protocols/ComputeTargetPoints.hpp"
      36             : #include "ParallelAlgorithms/Interpolation/Tags.hpp"
      37             : #include "PointwiseFunctions/GeneralRelativity/Surfaces/Tags.hpp"
      38             : #include "Utilities/Gsl.hpp"
      39             : #include "Utilities/PrettyType.hpp"
      40             : #include "Utilities/ProtocolHelpers.hpp"
      41             : #include "Utilities/Requires.hpp"
      42             : #include "Utilities/TMPL.hpp"
      43             : #include "Utilities/TaggedTuple.hpp"
      44             : 
      45             : /// \cond
      46             : class DataVector;
      47             : 
      48             : namespace PUP {
      49             : class er;
      50             : }  // namespace PUP
      51             : namespace db {
      52             : template <typename TagsList>
      53             : class DataBox;
      54             : }  // namespace db
      55             : namespace intrp {
      56             : template <class Metavariables, typename InterpolationTargetTag>
      57             : struct InterpolationTarget;
      58             : namespace Tags {
      59             : template <typename TemporalId>
      60             : struct TemporalIds;
      61             : }  // namespace Tags
      62             : }  // namespace intrp
      63             : namespace Tags {
      64             : struct Verbosity;
      65             : }  // namespace Tags
      66             : /// \endcond
      67             : 
      68             : namespace ah {
      69           0 : namespace OptionHolders {
      70             : /// Options for finding an apparent horizon.
      71             : template <typename Frame>
      72           1 : struct ApparentHorizon {
      73             :  private:
      74           0 :   struct All {};
      75             : 
      76             :  public:
      77             :   /// See Strahlkorper for suboptions.
      78           1 :   struct InitialGuess {
      79           0 :     static constexpr Options::String help = {"Initial guess"};
      80           0 :     using type = ylm::Strahlkorper<Frame>;
      81             :   };
      82             :   /// See ::FastFlow for suboptions.
      83           1 :   struct FastFlow {
      84           0 :     static constexpr Options::String help = {"FastFlow options"};
      85           0 :     using type = ::FastFlow;
      86             :   };
      87           0 :   struct Verbosity {
      88           0 :     static constexpr Options::String help = {"Verbosity"};
      89           0 :     using type = ::Verbosity;
      90             :   };
      91           0 :   struct MaxInterpolationRetries {
      92           0 :     static constexpr Options::String help = {
      93             :         "Number of times to retry the interpolation where, with each retry, "
      94             :         "the two previous surfaces are averaged and that new surface is used."};
      95           0 :     using type = size_t;
      96             :   };
      97           0 :   struct BlocksForInterpolation {
      98           0 :     static constexpr Options::String help = {
      99             :         "Volume data will be sent to the interpolator for these block group "
     100             :         "names. Set to 'All' to send volume data from the entire domain."};
     101           0 :     using type = Options::Auto<std::vector<std::string>, All>;
     102             :   };
     103           0 :   using options = tmpl::list<InitialGuess, FastFlow, Verbosity,
     104             :                              MaxInterpolationRetries, BlocksForInterpolation>;
     105           0 :   static constexpr Options::String help = {
     106             :       "Provide an initial guess for the apparent horizon surface\n"
     107             :       "(Strahlkorper) and apparent-horizon-finding-algorithm (FastFlow)\n"
     108             :       "options."};
     109             : 
     110           0 :   ApparentHorizon(
     111             :       ylm::Strahlkorper<Frame> initial_guess_in, ::FastFlow fast_flow_in,
     112             :       ::Verbosity verbosity_in, size_t max_interpolation_retries_in,
     113             :       std::optional<std::vector<std::string>> blocks_for_interpolation_in);
     114             : 
     115           0 :   ApparentHorizon() = default;
     116           0 :   ApparentHorizon(const ApparentHorizon& /*rhs*/) = default;
     117           0 :   ApparentHorizon& operator=(const ApparentHorizon& /*rhs*/) = delete;
     118           0 :   ApparentHorizon(ApparentHorizon&& /*rhs*/) = default;
     119           0 :   ApparentHorizon& operator=(ApparentHorizon&& /*rhs*/) = default;
     120           0 :   ~ApparentHorizon() = default;
     121             : 
     122             :   // NOLINTNEXTLINE(google-runtime-references)
     123           0 :   void pup(PUP::er& p);
     124             : 
     125           0 :   ylm::Strahlkorper<Frame> initial_guess{};
     126           0 :   ::FastFlow fast_flow{};
     127           0 :   ::Verbosity verbosity{::Verbosity::Quiet};
     128           0 :   size_t max_interpolation_retries{};
     129           0 :   std::optional<std::vector<std::string>> blocks_for_interpolation;
     130             : };
     131             : 
     132             : template <typename Frame>
     133           0 : bool operator==(const ApparentHorizon<Frame>& lhs,
     134             :                 const ApparentHorizon<Frame>& rhs);
     135             : template <typename Frame>
     136           0 : bool operator!=(const ApparentHorizon<Frame>& lhs,
     137             :                 const ApparentHorizon<Frame>& rhs);
     138             : 
     139             : }  // namespace OptionHolders
     140             : 
     141           0 : namespace OptionTags {
     142             : template <typename InterpolationTargetTag, typename Frame>
     143           0 : struct ApparentHorizon {
     144           0 :   using type = OptionHolders::ApparentHorizon<Frame>;
     145           0 :   static constexpr Options::String help{
     146             :       "Options for interpolation onto apparent horizon."};
     147           0 :   static std::string name() {
     148             :     return pretty_type::name<InterpolationTargetTag>();
     149             :   }
     150           0 :   using group = ApparentHorizonGroup;
     151             : };
     152             : }  // namespace OptionTags
     153             : 
     154           1 : namespace Tags {
     155             : template <typename InterpolationTargetTag, typename Frame>
     156           0 : struct ApparentHorizon : db::SimpleTag {
     157           0 :   using type = OptionHolders::ApparentHorizon<Frame>;
     158           0 :   using option_tags =
     159             :       tmpl::list<OptionTags::ApparentHorizon<InterpolationTargetTag, Frame>>;
     160             : 
     161           0 :   static constexpr bool pass_metavariables = false;
     162           0 :   static type create_from_options(const type& option) { return option; }
     163             : };
     164             : 
     165             : namespace detail {
     166             : template <typename InterpolationTargetTags>
     167             : struct get_horizon_options;
     168             : 
     169             : template <typename... InterpolationTargetTags>
     170             : struct get_horizon_options<tmpl::list<InterpolationTargetTags...>> {
     171             :   using type = tmpl::list<OptionTags::ApparentHorizon<
     172             :       InterpolationTargetTags,
     173             :       typename InterpolationTargetTags::compute_target_points::frame>...>;
     174             : };
     175             : 
     176             : CREATE_GET_TYPE_ALIAS_OR_DEFAULT(component_being_mocked)
     177             : }  // namespace detail
     178             : 
     179             : /*!
     180             :  * \brief Holds a map between interpolation target tag name (aka a horizon) and
     181             :  * a set of block names that should be used for interpolation for that target.
     182             :  */
     183           1 : struct BlocksForInterpolation : db::SimpleTag {
     184           0 :   using type = std::unordered_map<std::string, std::unordered_set<std::string>>;
     185             :   template <typename Metavariables>
     186           0 :   using option_tags = tmpl::push_front<
     187             :       typename detail::get_horizon_options<
     188             :           intrp::InterpolationTarget_detail::get_sequential_target_tags<
     189             :               Metavariables>>::type,
     190             :       ::domain::OptionTags::DomainCreator<Metavariables::volume_dim>>;
     191             : 
     192           0 :   static constexpr bool pass_metavariables = true;
     193             :   template <typename Metavariables, typename... HorizonOptions>
     194           0 :   static type create_from_options(
     195             :       const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>&
     196             :           domain_creator,
     197             :       const HorizonOptions&... all_horizon_options) {
     198             :     return create_from_options_impl<Metavariables>(
     199             :         domain_creator, std::forward_as_tuple(all_horizon_options...),
     200             :         std::make_index_sequence<sizeof...(HorizonOptions)>{});
     201             :   }
     202             : 
     203             :  private:
     204             :   // Need the names of the target tags which are in the option tags, but not the
     205             :   // horizon options themselves. This just expands a tuple to be able to index
     206             :   // the `option_tags` type alias so we can get the name of the target horizon
     207             :   template <typename Metavariables, typename HorizonOptionsTuple, size_t... Is>
     208           0 :   static type create_from_options_impl(
     209             :       const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>&
     210             :           domain_creator,
     211             :       const HorizonOptionsTuple& all_horizon_options,
     212             :       const std::index_sequence<Is...>& /*index_sequence*/
     213             :   ) {
     214             :     std::unordered_map<std::string, std::unordered_set<std::string>> result{};
     215             : 
     216             :     const auto block_names = domain_creator->block_names();
     217             :     const auto block_groups = domain_creator->block_groups();
     218             : 
     219             :     const auto append_to_result = [&](const std::string& name,
     220             :                                       const auto& horizon_options) {
     221             :       if (horizon_options.blocks_for_interpolation.has_value()) {
     222             :         result[name] = domain::expand_block_groups_to_block_names(
     223             :             horizon_options.blocks_for_interpolation.value(), block_names,
     224             :             block_groups);
     225             :       } else {
     226             :         // Insert all blocks
     227             :         result[name].insert(block_names.begin(), block_names.end());
     228             :       }
     229             : 
     230             :       // Needed for the expand_pack below
     231             :       return 0;
     232             :     };
     233             : 
     234             :     expand_pack(
     235             :         append_to_result(tmpl::at_c<option_tags<Metavariables>, Is + 1>::name(),
     236             :                          std::get<Is>(all_horizon_options))...);
     237             : 
     238             :     return result;
     239             :   }
     240             : };
     241             : }  // namespace Tags
     242             : 
     243           0 : namespace TargetPoints {
     244             : /// \brief Computes points on a trial apparent horizon`.
     245             : ///
     246             : /// This differs from `KerrHorizon` in the following ways:
     247             : /// - It supplies points on a prolonged Strahlkorper, at a higher resolution
     248             : ///   than the Strahlkorper in the DataBox, as needed for horizon finding.
     249             : /// - It uses a `FastFlow` in the DataBox.
     250             : /// - It has different options (including those for `FastFlow`).
     251             : ///
     252             : /// Conforms to the intrp::protocols::ComputeTargetPoints protocol
     253             : ///
     254             : /// For requirements on InterpolationTargetTag, see
     255             : /// intrp::protocols::InterpolationTargetTag
     256             : template <typename InterpolationTargetTag, typename Frame>
     257           1 : struct ApparentHorizon : tt::ConformsTo<intrp::protocols::ComputeTargetPoints> {
     258           0 :   using const_global_cache_tags =
     259             :       tmpl::list<Tags::BlocksForInterpolation,
     260             :                  Tags::ApparentHorizon<InterpolationTargetTag, Frame>>;
     261           0 :   using is_sequential = std::true_type;
     262           0 :   using frame = Frame;
     263             : 
     264           0 :   using common_tags =
     265             :       tmpl::push_back<ylm::Tags::items_tags<Frame>, ::ah::Tags::FastFlow,
     266             :                       logging::Tags::Verbosity<InterpolationTargetTag>,
     267             :                       ylm::Tags::PreviousStrahlkorpers<Frame>,
     268             :                       ::ah::Tags::PreviousIterationStrahlkorper<Frame>,
     269             :                       ::ah::Tags::FailedInterpolationIterations>;
     270           0 :   using simple_tags = tmpl::append<
     271             :       common_tags,
     272             :       tmpl::conditional_t<
     273             :           std::is_same_v<Frame, ::Frame::Inertial>, tmpl::list<>,
     274             :           tmpl::list<ylm::Tags::CartesianCoords<::Frame::Inertial>>>>;
     275           0 :   using compute_tags =
     276             :       tmpl::append<typename ylm::Tags::compute_items_tags<Frame>,
     277             :                    ylm::Tags::TimeDerivStrahlkorperCompute<Frame>>;
     278             : 
     279             :   template <typename DbTags, typename Metavariables>
     280           0 :   static void initialize(const gsl::not_null<db::DataBox<DbTags>*> box,
     281             :                          const Parallel::GlobalCache<Metavariables>& cache) {
     282             :     const auto& options =
     283             :         Parallel::get<Tags::ApparentHorizon<InterpolationTargetTag, Frame>>(
     284             :             cache);
     285             : 
     286             :     // Put Strahlkorper and its ComputeItems, FastFlow, and verbosity
     287             :     // into a new DataBox.
     288             :     //
     289             :     // Note that if frame is not inertial,
     290             :     // ylm::Tags::Strahlkorper<::Frame::Inertial> is already
     291             :     // default initialized so there is no need to do anything special
     292             :     // here for ylm::Tags::Strahlkorper<::Frame::Inertial>.
     293             :     Initialization::mutate_assign<common_tags>(
     294             :         box, options.initial_guess, options.fast_flow, options.verbosity,
     295             :         std::deque<std::pair<double, ylm::Strahlkorper<Frame>>>{},
     296             :         options.initial_guess, 0_st);
     297             :   }
     298             : 
     299             :   template <typename Metavariables, typename DbTags, typename TemporalId>
     300           0 :   static tnsr::I<DataVector, 3, Frame> points(
     301             :       db::DataBox<DbTags>& box, const tmpl::type_<Metavariables>& /*meta*/,
     302             :       const TemporalId& temporal_id) {
     303             :     const auto& fast_flow = db::get<::ah::Tags::FastFlow>(box);
     304             : 
     305             :     if (fast_flow.current_iteration() == 0) {
     306             :       // Put new initial guess into ylm::Tags::Strahlkorper<Frame>.
     307             :       // We need to do this now, and not at the end of the previous horizon
     308             :       // search, because only now do we know the temporal_id of this horizon
     309             :       // search.
     310             :       db::mutate<ylm::Tags::Strahlkorper<Frame>>(
     311             :           [&temporal_id](
     312             :               const gsl::not_null<ylm::Strahlkorper<Frame>*> strahlkorper,
     313             :               const std::deque<std::pair<double, ylm::Strahlkorper<Frame>>>&
     314             :                   previous_strahlkorpers) {
     315             :             // If we have zero previous_strahlkorpers, then the
     316             :             // initial guess is already in strahlkorper, so do
     317             :             // nothing.
     318             :             //
     319             :             // If we have one previous_strahlkorper, then we have had
     320             :             // a successful horizon find, and the initial guess for the
     321             :             // next horizon find is already in strahlkorper, so
     322             :             // again we do nothing.
     323             :             //
     324             :             // If we have 2 valid previous_strahlkorpers, then
     325             :             // we set the initial guess by linear extrapolation in time
     326             :             // using the last 2 previous_strahlkorpers.
     327             :             //
     328             :             // If we have 3 valid previous_strahlkorpers, then
     329             :             // we set the initial guess by quadratic extrapolation in time
     330             :             // using the last 3 previous_strahlkorpers.
     331             :             //
     332             :             // For extrapolation, we assume that
     333             :             // * Expansion center of all the Strahlkorpers are equal.
     334             :             // * Maximum L of all the Strahlkorpers are equal.
     335             :             // It is easy to relax the max L assumption once we start
     336             :             // adaptively changing the L of the strahlkorpers.
     337             :             if (LIKELY(previous_strahlkorpers.size() > 2)) {
     338             :               // Quadratic extrapolation
     339             :               const double new_time =
     340             :                   intrp::InterpolationTarget_detail::get_temporal_id_value(
     341             :                       temporal_id);
     342             :               const double dt_0 = previous_strahlkorpers[0].first - new_time;
     343             :               const double dt_1 = previous_strahlkorpers[1].first - new_time;
     344             :               const double dt_2 = previous_strahlkorpers[2].first - new_time;
     345             :               const double fac_0 =
     346             :                   dt_1 * dt_2 / ((dt_1 - dt_0) * (dt_2 - dt_0));
     347             :               const double fac_1 =
     348             :                   dt_0 * dt_2 / ((dt_2 - dt_1) * (dt_0 - dt_1));
     349             :               const double fac_2 = 1.0 - fac_0 - fac_1;
     350             :               strahlkorper->coefficients() =
     351             :                   fac_0 * previous_strahlkorpers[0].second.coefficients() +
     352             :                   fac_1 * previous_strahlkorpers[1].second.coefficients() +
     353             :                   fac_2 * previous_strahlkorpers[2].second.coefficients();
     354             :             } else if (previous_strahlkorpers.size() > 1) {
     355             :               // Linear extrapolation
     356             :               const double new_time =
     357             :                   intrp::InterpolationTarget_detail::get_temporal_id_value(
     358             :                       temporal_id);
     359             :               const double dt_0 = previous_strahlkorpers[0].first - new_time;
     360             :               const double dt_1 = previous_strahlkorpers[1].first - new_time;
     361             :               const double fac_0 = dt_1 / (dt_1 - dt_0);
     362             :               const double fac_1 = 1.0 - fac_0;
     363             :               strahlkorper->coefficients() =
     364             :                   fac_0 * previous_strahlkorpers[0].second.coefficients() +
     365             :                   fac_1 * previous_strahlkorpers[1].second.coefficients();
     366             :             }
     367             :           },
     368             :           make_not_null(&box),
     369             :           db::get<ylm::Tags::PreviousStrahlkorpers<Frame>>(box));
     370             :     }
     371             : 
     372             :     const auto& strahlkorper = db::get<ylm::Tags::Strahlkorper<Frame>>(box);
     373             : 
     374             :     const size_t L_mesh = fast_flow.current_l_mesh(strahlkorper);
     375             : 
     376             :     const auto prolonged_strahlkorper =
     377             :         ylm::Strahlkorper<Frame>(L_mesh, L_mesh, strahlkorper);
     378             : 
     379             :     return ylm::cartesian_coords(prolonged_strahlkorper);
     380             :   }
     381             : };
     382             : 
     383             : }  // namespace TargetPoints
     384             : }  // namespace ah

Generated by: LCOV version 1.14