SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/ApparentHorizonFinder/Callbacks - ObserveCenters.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 25.0 % 4 1
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 <array>
       7              : #include <cmath>
       8              : #include <limits>
       9              : #include <tuple>
      10              : 
      11              : #include "DataStructures/DataBox/DataBox.hpp"
      12              : #include "IO/Observer/ObserverComponent.hpp"
      13              : #include "IO/Observer/ReductionActions.hpp"
      14              : #include "NumericalAlgorithms/SphericalHarmonics/Spherepack.hpp"
      15              : #include "NumericalAlgorithms/Strahlkorper/Strahlkorper.hpp"
      16              : #include "NumericalAlgorithms/Strahlkorper/Tags.hpp"
      17              : #include "Parallel/GlobalCache.hpp"
      18              : #include "Parallel/Invoke.hpp"
      19              : #include "Parallel/ParallelComponentHelpers.hpp"
      20              : #include "ParallelAlgorithms/ApparentHorizonFinder/FastFlow.hpp"
      21              : #include "ParallelAlgorithms/ApparentHorizonFinder/Protocols/Callback.hpp"
      22              : #include "ParallelAlgorithms/ApparentHorizonFinder/Tags.hpp"
      23              : #include "PointwiseFunctions/GeneralRelativity/Surfaces/Tags.hpp"
      24              : #include "Utilities/Gsl.hpp"
      25              : #include "Utilities/PrettyType.hpp"
      26              : #include "Utilities/ProtocolHelpers.hpp"
      27              : 
      28              : /// \cond
      29              : namespace Frame {
      30              : struct Grid;
      31              : struct Distorted;
      32              : struct Inertial;
      33              : }  // namespace Frame
      34              : /// \endcond
      35              : 
      36              : namespace ah::callbacks {
      37              : /*!
      38              :  * \brief Writes the center of an apparent horizon to disk in both the
      39              :  * `Frame` template parameter frame and Frame::Inertial frame. Intended to be
      40              :  * used in the `horizon_find_callbacks` list of a
      41              :  * `ah::protocols::HorizonMetavars`.
      42              :  *
      43              :  * The centers will be written to a subfile with the name
      44              :  * `/ApparentHorizons/TargetName_Centers.dat` where `TargetName` is the
      45              :  * pretty_type::name of the \p HorizonMetavars template parameter.
      46              :  *
      47              :  * The columns of the dat file are:
      48              :  * - %Time
      49              :  * - GridCenter_x
      50              :  * - GridCenter_y
      51              :  * - GridCenter_z
      52              :  * - InertialCenter_x
      53              :  * - InertialCenter_y
      54              :  * - InertialCenter_z
      55              :  *
      56              :  * The `Frame` template parameter must be either `::Frame::Grid` or
      57              :  * `::Frame::Distorted`. Even though the template parameter can be
      58              :  * `::Frame::Distorted`, we still write `GridCenter_?` because the centers of
      59              :  * the objects are the same in the Grid and Distorted frames.
      60              :  *
      61              :  * \note Requires `ylm::Tags::Strahlkorper<Frame>` and
      62              :  * `ylm::Tags::CartesianCoords<Frame::Inertial>` and
      63              :  * `ylm::Tags::EuclideanAreaElement<Frame>` to be in the DataBox of the horizon
      64              :  * finder.
      65              :  */
      66              : template <typename HorizonMetavars>
      67            1 : struct ObserveCenters : tt::ConformsTo<ah::protocols::Callback> {
      68              :   template <typename DbTags, typename Metavariables>
      69            0 :   static void apply(const db::DataBox<DbTags>& box,
      70              :                     Parallel::GlobalCache<Metavariables>& cache,
      71              :                     const FastFlow::Status /*status*/) {
      72              :     using frame = typename HorizonMetavars::frame;
      73              :     static_assert(std::is_same_v<frame, ::Frame::Grid> or
      74              :                       std::is_same_v<frame, ::Frame::Distorted>,
      75              :                   "Frame must be either Grid or Distorted.");
      76              :     using HorizonTag = ylm::Tags::Strahlkorper<frame>;
      77              :     using CoordsTag = ylm::Tags::CartesianCoords<::Frame::Inertial>;
      78              :     using EuclideanAreaElementTag = ylm::Tags::EuclideanAreaElement<frame>;
      79              :     static_assert(db::tag_is_retrievable_v<HorizonTag, db::DataBox<DbTags>>,
      80              :                   "DataBox must contain ylm::Tags::Strahlkorper<Frame>");
      81              :     static_assert(db::tag_is_retrievable_v<CoordsTag, db::DataBox<DbTags>>,
      82              :                   "DataBox must contain "
      83              :                   "ylm::Tags::CartesianCoords<Frame::Inertial>");
      84              :     static_assert(
      85              :         db::tag_is_retrievable_v<EuclideanAreaElementTag, db::DataBox<DbTags>>,
      86              :         "DataBox must contain ylm::Tags::EuclideanAreaElement<Frame>");
      87              : 
      88              :     // Only print the centers if we want to.
      89              :     if (not Parallel::get<ah::Tags::ObserveCenters>(cache)) {
      90              :       return;
      91              :     }
      92              : 
      93              :     const auto& grid_horizon = db::get<HorizonTag>(box);
      94              :     const std::array<double, 3> grid_center = grid_horizon.physical_center();
      95              : 
      96              :     // computes the inertial center to be the average value of the
      97              :     // inertial coordinates over the Strahlkorper, where the average is
      98              :     // computed by a surface integral.
      99              :     // Note that we use the Euclidean area element here, since we are trying
     100              :     // to find a geometric center of a surface without regard to GR.
     101              :     const auto& inertial_coords = db::get<CoordsTag>(box);
     102              :     const auto& area_element = db::get<EuclideanAreaElementTag>(box);
     103              :     std::array<double, 3> inertial_center =
     104              :         make_array<3>(std::numeric_limits<double>::signaling_NaN());
     105              :     auto integrand = make_with_value<Scalar<DataVector>>(get(area_element), 0.);
     106              :     const double denominator = grid_horizon.ylm_spherepack().definite_integral(
     107              :         get(area_element).data());
     108              :     for (size_t i = 0; i < 3; ++i) {
     109              :       get(integrand) = get(area_element) * inertial_coords.get(i);
     110              :       gsl::at(inertial_center, i) =
     111              :           grid_horizon.ylm_spherepack().definite_integral(
     112              :               get(integrand).data()) /
     113              :           denominator;
     114              :     }
     115              : 
     116              :     // time, grid_x, grid_y, grid_z, inertial_x, inertial_y, inertial_z
     117              :     const auto& current_time = db::get<ah::Tags::CurrentTime>(box).value();
     118              :     const auto center_tuple = std::make_tuple(
     119              :         current_time.id, grid_center[0], grid_center[1], grid_center[2],
     120              :         inertial_center[0], inertial_center[1], inertial_center[2]);
     121              : 
     122              :     auto& observer_writer_proxy = Parallel::get_parallel_component<
     123              :         observers::ObserverWriter<Metavariables>>(cache);
     124              : 
     125              :     const std::string subfile_path{"/ApparentHorizons/" +
     126              :                                    HorizonMetavars::name() + "_Centers"};
     127              : 
     128              :     Parallel::threaded_action<
     129              :         observers::ThreadedActions::WriteReductionDataRow>(
     130              :         // Node 0 is always the writer
     131              :         observer_writer_proxy[0], subfile_path, legend_, center_tuple);
     132              :   }
     133              : 
     134              :  private:
     135            0 :   const static inline std::vector<std::string> legend_{
     136              :       {"Time", "GridCenter_x", "GridCenter_y", "GridCenter_z",
     137              :        "InertialCenter_x", "InertialCenter_y", "InertialCenter_z"}};
     138              : };
     139              : }  // namespace ah::callbacks
        

Generated by: LCOV version 2.0-1