SpECTRE Documentation Coverage Report
Current view: top level - Elliptic/Systems/Xcts/Events - ObserveAdmIntegrals.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 15.0 % 20 3
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 <optional>
       7              : #include <pup.h>
       8              : #include <string>
       9              : #include <vector>
      10              : 
      11              : #include "DataStructures/DataVector.hpp"
      12              : #include "DataStructures/Tensor/Tensor.hpp"
      13              : #include "Domain/Structure/ElementId.hpp"
      14              : #include "Domain/Tags.hpp"
      15              : #include "Domain/Tags/FaceNormal.hpp"
      16              : #include "Domain/Tags/Faces.hpp"
      17              : #include "Elliptic/Systems/Xcts/Tags.hpp"
      18              : #include "IO/Observer/GetSectionObservationKey.hpp"
      19              : #include "IO/Observer/ObservationId.hpp"
      20              : #include "IO/Observer/ObserverComponent.hpp"
      21              : #include "IO/Observer/ReductionActions.hpp"
      22              : #include "IO/Observer/TypeOfObservation.hpp"
      23              : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
      24              : #include "Options/String.hpp"
      25              : #include "Parallel/ArrayIndex.hpp"
      26              : #include "Parallel/GlobalCache.hpp"
      27              : #include "Parallel/Reduction.hpp"
      28              : #include "Parallel/TypeTraits.hpp"
      29              : #include "ParallelAlgorithms/Events/Tags.hpp"
      30              : #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
      31              : #include "Utilities/Serialization/CharmPupable.hpp"
      32              : 
      33            0 : namespace Events {
      34              : 
      35              : /// @{
      36              : /*!
      37              :  * \brief Computes the ADM integrals locally (within one element).
      38              :  *
      39              :  * To get the total ADM integrals, the results need to be summed over in a
      40              :  * reduction.
      41              :  */
      42            1 : void local_adm_integrals(
      43              :     gsl::not_null<Scalar<double>*> adm_mass,
      44              :     gsl::not_null<tnsr::I<double, 3>*> adm_linear_momentum,
      45              :     gsl::not_null<Scalar<double>*> adm_angular_momentum_z,
      46              :     gsl::not_null<tnsr::I<double, 3>*> center_of_mass,
      47              :     const Scalar<DataVector>& conformal_factor,
      48              :     const Scalar<DataVector>& conformal_factor_minus_one,
      49              :     const tnsr::i<DataVector, 3>& deriv_conformal_factor,
      50              :     const tnsr::ii<DataVector, 3>& conformal_metric,
      51              :     const tnsr::II<DataVector, 3>& inv_conformal_metric,
      52              :     const tnsr::Ijj<DataVector, 3>& conformal_christoffel_second_kind,
      53              :     const tnsr::i<DataVector, 3>& conformal_christoffel_contracted,
      54              :     const tnsr::ii<DataVector, 3>& spatial_metric,
      55              :     const tnsr::II<DataVector, 3>& inv_spatial_metric,
      56              :     const tnsr::ii<DataVector, 3>& extrinsic_curvature,
      57              :     const Scalar<DataVector>& trace_extrinsic_curvature,
      58              :     const tnsr::I<DataVector, 3, Frame::Inertial>& inertial_coords,
      59              :     const InverseJacobian<DataVector, 3, Frame::ElementLogical,
      60              :                           Frame::Inertial>& inv_jacobian,
      61              :     const Mesh<3>& mesh, const Element<3>& element,
      62              :     const DirectionMap<3, tnsr::i<DataVector, 3>>& conformal_face_normals);
      63              : /// @}
      64              : 
      65              : /// @{
      66              : /*!
      67              :  * \brief Observe ADM integrals after the XCTS solve.
      68              :  *
      69              :  * The surface integrals are taken over the outer boundary, which is defined as
      70              :  * the domain boundary in the upper logical zeta direction.
      71              :  *
      72              :  * Writes reduction quantities:
      73              :  * - Number of points in the domain
      74              :  * - ADM mass
      75              :  * - ADM linear momentum
      76              :  * - ADM angular momentum (z-component)
      77              :  * - Center of mass
      78              :  */
      79              : template <typename ArraySectionIdTag = void>
      80            1 : class ObserveAdmIntegrals : public Event {
      81              :  private:
      82            0 :   using ReductionData = Parallel::ReductionData<
      83              :       // Number of points
      84              :       Parallel::ReductionDatum<size_t, funcl::Plus<>>,
      85              :       // ADM Mass
      86              :       Parallel::ReductionDatum<double, funcl::Plus<>>,
      87              :       // ADM Linear Momentum (x-component)
      88              :       Parallel::ReductionDatum<double, funcl::Plus<>>,
      89              :       // ADM Linear Momentum (y-component)
      90              :       Parallel::ReductionDatum<double, funcl::Plus<>>,
      91              :       // ADM Linear Momentum (z-component)
      92              :       Parallel::ReductionDatum<double, funcl::Plus<>>,
      93              :       // ADM Angular Momentum (z-component)
      94              :       Parallel::ReductionDatum<double, funcl::Plus<>>,
      95              :       // Center of Mass (x-component)
      96              :       Parallel::ReductionDatum<double, funcl::Plus<>, funcl::Divides<>,
      97              :                                std::index_sequence<1>>,
      98              :       // Center of Mass (y-component)
      99              :       Parallel::ReductionDatum<double, funcl::Plus<>, funcl::Divides<>,
     100              :                                std::index_sequence<1>>,
     101              :       // Center of Mass (z-component)
     102              :       Parallel::ReductionDatum<double, funcl::Plus<>, funcl::Divides<>,
     103              :                                std::index_sequence<1>>>;
     104              : 
     105              :  public:
     106              :   /// \cond
     107              :   explicit ObserveAdmIntegrals(CkMigrateMessage* msg) : Event(msg) {}
     108              :   using PUP::able::register_constructor;
     109              :   WRAPPED_PUPable_decl_template(ObserveAdmIntegrals);  // NOLINT
     110              :   /// \endcond
     111              : 
     112            0 :   using options = tmpl::list<>;
     113            0 :   static constexpr Options::String help =
     114              :       "Observe ADM integrals after the XCTS solve.\n"
     115              :       "\n"
     116              :       "Writes reduction quantities:\n"
     117              :       "- Number of points in the domain\n"
     118              :       "- ADM mass\n"
     119              :       "- ADM linear momentum\n"
     120              :       "- ADM angular momentum (z-component)\n"
     121              :       "- Center of mass";
     122              : 
     123            0 :   ObserveAdmIntegrals() = default;
     124              : 
     125            0 :   using observed_reduction_data_tags =
     126              :       observers::make_reduction_data_tags<tmpl::list<ReductionData>>;
     127              : 
     128            0 :   using compute_tags_for_observation_box = tmpl::list<>;
     129              : 
     130            0 :   using return_tags = tmpl::list<>;
     131              : 
     132            0 :   using argument_tags = tmpl::list<
     133              :       Xcts::Tags::ConformalFactor<DataVector>,
     134              :       Xcts::Tags::ConformalFactorMinusOne<DataVector>,
     135              :       ::Tags::deriv<Xcts::Tags::ConformalFactor<DataVector>, tmpl::size_t<3>,
     136              :                     Frame::Inertial>,
     137              :       Xcts::Tags::ConformalMetric<DataVector, 3, Frame::Inertial>,
     138              :       Xcts::Tags::InverseConformalMetric<DataVector, 3, Frame::Inertial>,
     139              :       Xcts::Tags::ConformalChristoffelSecondKind<DataVector, 3,
     140              :                                                  Frame::Inertial>,
     141              :       Xcts::Tags::ConformalChristoffelContracted<DataVector, 3,
     142              :                                                  Frame::Inertial>,
     143              :       gr::Tags::SpatialMetric<DataVector, 3, Frame::Inertial>,
     144              :       gr::Tags::InverseSpatialMetric<DataVector, 3, Frame::Inertial>,
     145              :       gr::Tags::ExtrinsicCurvature<DataVector, 3, Frame::Inertial>,
     146              :       gr::Tags::TraceExtrinsicCurvature<DataVector>,
     147              :       domain::Tags::Coordinates<3, Frame::Inertial>,
     148              :       domain::Tags::InverseJacobian<3, Frame::ElementLogical, Frame::Inertial>,
     149              :       domain::Tags::Mesh<3>, domain::Tags::Element<3>,
     150              :       domain::Tags::Faces<3, domain::Tags::FaceNormal<3>>,
     151              :       ::Tags::ObservationBox>;
     152              : 
     153              :   template <typename DataBoxType, typename ComputeTagsList,
     154              :             typename Metavariables, typename ArrayIndex,
     155              :             typename ParallelComponent>
     156            0 :   void operator()(
     157              :       const Scalar<DataVector>& conformal_factor,
     158              :       const Scalar<DataVector>& conformal_factor_minus_one,
     159              :       const tnsr::i<DataVector, 3>& deriv_conformal_factor,
     160              :       const tnsr::ii<DataVector, 3>& conformal_metric,
     161              :       const tnsr::II<DataVector, 3>& inv_conformal_metric,
     162              :       const tnsr::Ijj<DataVector, 3>& conformal_christoffel_second_kind,
     163              :       const tnsr::i<DataVector, 3>& conformal_christoffel_contracted,
     164              :       const tnsr::ii<DataVector, 3>& spatial_metric,
     165              :       const tnsr::II<DataVector, 3>& inv_spatial_metric,
     166              :       const tnsr::ii<DataVector, 3>& extrinsic_curvature,
     167              :       const Scalar<DataVector>& trace_extrinsic_curvature,
     168              :       const tnsr::I<DataVector, 3, Frame::Inertial>& inertial_coords,
     169              :       const InverseJacobian<DataVector, 3, Frame::ElementLogical,
     170              :                             Frame::Inertial>& inv_jacobian,
     171              :       const Mesh<3>& mesh, const Element<3>& element,
     172              :       const DirectionMap<3, tnsr::i<DataVector, 3>>& conformal_face_normals,
     173              :       const ObservationBox<DataBoxType, ComputeTagsList>& box,
     174              :       Parallel::GlobalCache<Metavariables>& cache,
     175              :       const ArrayIndex& array_index, const ParallelComponent* const /*meta*/,
     176              :       const ObservationValue& observation_value) const {
     177              :     // Skip observation on elements that are not part of a section
     178              :     const std::optional<std::string> section_observation_key =
     179              :         observers::get_section_observation_key<ArraySectionIdTag>(box);
     180              :     if (not section_observation_key.has_value()) {
     181              :       return;
     182              :     }
     183              :     const std::string subfile_path = subfile_path_ + *section_observation_key;
     184              : 
     185              :     Scalar<double> adm_mass;
     186              :     tnsr::I<double, 3> adm_linear_momentum;
     187              :     Scalar<double> adm_angular_momentum_z;
     188              :     tnsr::I<double, 3> center_of_mass;
     189              :     local_adm_integrals(
     190              :         make_not_null(&adm_mass), make_not_null(&adm_linear_momentum),
     191              :         make_not_null(&adm_angular_momentum_z), make_not_null(&center_of_mass),
     192              :         conformal_factor, conformal_factor_minus_one, deriv_conformal_factor,
     193              :         conformal_metric, inv_conformal_metric,
     194              :         conformal_christoffel_second_kind, conformal_christoffel_contracted,
     195              :         spatial_metric, inv_spatial_metric, extrinsic_curvature,
     196              :         trace_extrinsic_curvature, inertial_coords, inv_jacobian, mesh, element,
     197              :         conformal_face_normals);
     198              : 
     199              :     // Save components of linear momentum as reduction data
     200              :     ReductionData reduction_data{
     201              :         mesh.number_of_grid_points(), get(adm_mass),
     202              :         get<0>(adm_linear_momentum),  get<1>(adm_linear_momentum),
     203              :         get<2>(adm_linear_momentum),  get(adm_angular_momentum_z),
     204              :         get<0>(center_of_mass),       get<1>(center_of_mass),
     205              :         get<2>(center_of_mass)};
     206              :     std::vector<std::string> legend{
     207              :         "NumberOfPoints",      "AdmMass",
     208              :         "AdmLinearMomentum_x", "AdmLinearMomentum_y",
     209              :         "AdmLinearMomentum_z", "AdmAngularMomentum_z",
     210              :         "CenterOfMass_x",      "CenterOfMass_y",
     211              :         "CenterOfMass_z"};
     212              : 
     213              :     // Get information required for reduction
     214              :     auto& local_observer = *Parallel::local_branch(
     215              :         Parallel::get_parallel_component<
     216              :             tmpl::conditional_t<Parallel::is_nodegroup_v<ParallelComponent>,
     217              :                                 observers::ObserverWriter<Metavariables>,
     218              :                                 observers::Observer<Metavariables>>>(cache));
     219              :     observers::ObservationId observation_id{observation_value.value,
     220              :                                             subfile_path + ".dat"};
     221              :     Parallel::ArrayComponentId array_component_id{
     222              :         std::add_pointer_t<ParallelComponent>{nullptr},
     223              :         Parallel::ArrayIndex<ElementId<3>>(array_index)};
     224              : 
     225              :     // Send reduction action
     226              :     if constexpr (Parallel::is_nodegroup_v<ParallelComponent>) {
     227              :       Parallel::threaded_action<
     228              :           observers::ThreadedActions::CollectReductionDataOnNode>(
     229              :           local_observer, std::move(observation_id),
     230              :           std::move(array_component_id), subfile_path, std::move(legend),
     231              :           std::move(reduction_data));
     232              :     } else {
     233              :       Parallel::simple_action<observers::Actions::ContributeReductionData>(
     234              :           local_observer, std::move(observation_id),
     235              :           std::move(array_component_id), subfile_path, std::move(legend),
     236              :           std::move(reduction_data));
     237              :     }
     238              :   }
     239              : 
     240            0 :   using observation_registration_tags = tmpl::list<::Tags::DataBox>;
     241              : 
     242              :   template <typename DbTagsList>
     243              :   std::optional<
     244              :       std::pair<observers::TypeOfObservation, observers::ObservationKey>>
     245            0 :   get_observation_type_and_key_for_registration(
     246              :       const db::DataBox<DbTagsList>& box) const {
     247              :     const std::optional<std::string> section_observation_key =
     248              :         observers::get_section_observation_key<ArraySectionIdTag>(box);
     249              :     if (not section_observation_key.has_value()) {
     250              :       return std::nullopt;
     251              :     }
     252              :     return {{observers::TypeOfObservation::Reduction,
     253              :              observers::ObservationKey(
     254              :                  subfile_path_ + section_observation_key.value() + ".dat")}};
     255              :   }
     256              : 
     257            0 :   using is_ready_argument_tags = tmpl::list<>;
     258              : 
     259              :   template <typename Metavariables, typename ArrayIndex, typename Component>
     260            0 :   bool is_ready(Parallel::GlobalCache<Metavariables>& /*cache*/,
     261              :                 const ArrayIndex& /*array_index*/,
     262              :                 const Component* const /*meta*/) const {
     263              :     return true;
     264              :   }
     265              : 
     266            1 :   bool needs_evolved_variables() const override { return false; }
     267              : 
     268              :   // NOLINTNEXTLINE(google-runtime-references)
     269            0 :   void pup(PUP::er& p) override {
     270              :     Event::pup(p);
     271              :     p | subfile_path_;
     272              :   }
     273              : 
     274              :  private:
     275            0 :   std::string subfile_path_ = "/AdmIntegrals";
     276              : };
     277              : /// @}
     278              : 
     279              : /// \cond
     280              : template <typename ArraySectionIdTag>
     281              : PUP::able::PUP_ID ObserveAdmIntegrals<ArraySectionIdTag>::my_PUP_ID =
     282              :     0;  // NOLINT
     283              : /// \endcond
     284              : 
     285              : }  // namespace Events
        

Generated by: LCOV version 2.0-1