SpECTRE Documentation Coverage Report
Current view: top level - Elliptic/Systems/Xcts/Events - ObserveAdmIntegrals.hpp Hit Total Coverage
Commit: 1f2210958b4f38fdc0400907ee7c6d5af5111418 Lines: 3 20 15.0 %
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 <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 1.14