SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/ScalarTensor/Actions - SetInitialData.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 10.3 % 39 4
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 <cstddef>
       7              : #include <optional>
       8              : #include <pup.h>
       9              : #include <string>
      10              : #include <variant>
      11              : 
      12              : #include "DataStructures/DataBox/DataBox.hpp"
      13              : #include "DataStructures/DataVector.hpp"
      14              : #include "DataStructures/TaggedTuple.hpp"
      15              : #include "DataStructures/Tensor/EagerMath/DeterminantAndInverse.hpp"
      16              : #include "DataStructures/Tensor/Tensor.hpp"
      17              : #include "Domain/Structure/ElementId.hpp"
      18              : #include "Domain/Tags.hpp"
      19              : #include "Evolution/Initialization/InitialData.hpp"
      20              : #include "Evolution/NumericInitialData.hpp"
      21              : #include "Evolution/Systems/CurvedScalarWave/Actions/SetInitialData.hpp"
      22              : #include "Evolution/Systems/CurvedScalarWave/Tags.hpp"
      23              : #include "Evolution/Systems/GeneralizedHarmonic/Actions/SetInitialData.hpp"
      24              : #include "Evolution/Systems/GeneralizedHarmonic/Tags.hpp"
      25              : #include "IO/Importers/Actions/ReadVolumeData.hpp"
      26              : #include "IO/Importers/ElementDataReader.hpp"
      27              : #include "IO/Importers/Tags.hpp"
      28              : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp"
      29              : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
      30              : #include "Options/String.hpp"
      31              : #include "Parallel/AlgorithmExecution.hpp"
      32              : #include "Parallel/GlobalCache.hpp"
      33              : #include "Parallel/Invoke.hpp"
      34              : #include "PointwiseFunctions/GeneralRelativity/SpatialMetric.hpp"
      35              : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
      36              : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
      37              : #include "PointwiseFunctions/InitialDataUtilities/Tags/InitialData.hpp"
      38              : #include "Utilities/CallWithDynamicType.hpp"
      39              : #include "Utilities/ErrorHandling/Error.hpp"
      40              : #include "Utilities/Gsl.hpp"
      41              : #include "Utilities/Serialization/CharmPupable.hpp"
      42              : #include "Utilities/TMPL.hpp"
      43              : 
      44            1 : namespace ScalarTensor {
      45              : 
      46              : /*!
      47              :  * \brief Numeric initial data loaded from volume data files
      48              :  */
      49            1 : class NumericInitialData : public evolution::initial_data::InitialData,
      50              :                            public evolution::NumericInitialData {
      51              :  private:
      52            0 :   using GhNumericId = gh::NumericInitialData;
      53            0 :   using ScalarNumericId = CurvedScalarWave::NumericInitialData;
      54              : 
      55              :  public:
      56            0 :   using all_vars =
      57              :       tmpl::append<GhNumericId::all_vars, ScalarNumericId::all_vars>;
      58              : 
      59            0 :   struct GhVariables : GhNumericId::Variables {};
      60            0 :   struct ScalarVariables : ScalarNumericId::Variables {};
      61              : 
      62            0 :   using options = tmpl::list<importers::OptionTags::VolumeData, GhVariables,
      63              :                              ScalarVariables>;
      64              : 
      65            0 :   static constexpr Options::String help =
      66              :       "Numeric initial data for the Scalar Tensor system loaded from volume "
      67              :       "data files";
      68              : 
      69            0 :   NumericInitialData() = default;
      70            0 :   NumericInitialData(const NumericInitialData& rhs) = default;
      71            0 :   NumericInitialData& operator=(const NumericInitialData& rhs) = default;
      72            0 :   NumericInitialData(NumericInitialData&& /*rhs*/) = default;
      73            0 :   NumericInitialData& operator=(NumericInitialData&& /*rhs*/) = default;
      74            0 :   ~NumericInitialData() override = default;
      75              : 
      76              :   /// \cond
      77              :   explicit NumericInitialData(CkMigrateMessage* msg);
      78              :   using PUP::able::register_constructor;
      79              :   WRAPPED_PUPable_decl_template(NumericInitialData);
      80              :   /// \endcond
      81              : 
      82            0 :   std::unique_ptr<evolution::initial_data::InitialData> get_clone()
      83              :       const override {
      84              :     return std::make_unique<NumericInitialData>(*this);
      85              :   }
      86              : 
      87            0 :   NumericInitialData(
      88              :       importers::ImporterOptions importer_options,
      89              :       typename GhNumericId::Variables::type gh_selected_variables,
      90              :       typename ScalarNumericId::Variables::type hydro_selected_variables);
      91              : 
      92            0 :   const importers::ImporterOptions& importer_options() const {
      93              :     return gh_numeric_id_.importer_options();
      94              :   }
      95              : 
      96            0 :   const GhNumericId& gh_numeric_id() const { return gh_numeric_id_; }
      97              : 
      98            0 :   const ScalarNumericId& scalar_numeric_id() const {
      99              :     return scalar_numeric_id_;
     100              :   }
     101              : 
     102            0 :   size_t volume_data_id() const;
     103              : 
     104              :   template <typename... AllTags>
     105            0 :   void select_for_import(
     106              :       const gsl::not_null<tuples::TaggedTuple<AllTags...>*> fields) const {
     107              :     gh_numeric_id_.select_for_import(fields);
     108              :     scalar_numeric_id_.select_for_import(fields);
     109              :   }
     110              : 
     111              :   template <typename... AllTags>
     112            0 :   void set_initial_data(
     113              :       const gsl::not_null<tnsr::aa<DataVector, 3>*> spacetime_metric,
     114              :       const gsl::not_null<tnsr::aa<DataVector, 3>*> pi,
     115              :       const gsl::not_null<tnsr::iaa<DataVector, 3>*> phi,
     116              :       const gsl::not_null<Scalar<DataVector>*> psi_scalar,
     117              :       const gsl::not_null<Scalar<DataVector>*> pi_scalar,
     118              :       const gsl::not_null<tnsr::i<DataVector, 3>*> phi_scalar,
     119              :       const gsl::not_null<tuples::TaggedTuple<AllTags...>*> numeric_data,
     120              :       const Mesh<3>& mesh,
     121              :       const InverseJacobian<DataVector, 3, Frame::ElementLogical,
     122              :                             Frame::Inertial>& inv_jacobian,
     123              :       const tnsr::I<DataVector, 3, Frame::Inertial>& inertial_coords) const {
     124              :     gh_numeric_id_.set_initial_data(spacetime_metric, pi, phi, numeric_data,
     125              :                                     mesh, inv_jacobian, inertial_coords);
     126              :     scalar_numeric_id_.set_initial_data(psi_scalar, pi_scalar, phi_scalar,
     127              :                                         numeric_data);
     128              :   }
     129              : 
     130            0 :   void pup(PUP::er& p) override;
     131              : 
     132            0 :   friend bool operator==(const NumericInitialData& lhs,
     133              :                          const NumericInitialData& rhs);
     134              : 
     135              :  private:
     136            0 :   GhNumericId gh_numeric_id_{};
     137            0 :   ScalarNumericId scalar_numeric_id_{};
     138              : };
     139              : 
     140            0 : namespace Actions {
     141              : 
     142              : /*!
     143              :  * \brief Dispatch loading numeric initial data from files.
     144              :  *
     145              :  * Place this action before
     146              :  * ScalarTensor::Actions::SetNumericInitialData in the action list.
     147              :  * See importers::Actions::ReadAllVolumeDataAndDistribute for details, which is
     148              :  * invoked by this action.
     149              :  */
     150            1 : struct SetInitialData {
     151            0 :   using const_global_cache_tags =
     152              :       tmpl::list<evolution::initial_data::Tags::InitialData>;
     153              : 
     154              :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
     155              :             typename ArrayIndex, typename ActionList,
     156              :             typename ParallelComponent>
     157            0 :   static Parallel::iterable_action_return_t apply(
     158              :       db::DataBox<DbTagsList>& box,
     159              :       const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     160              :       Parallel::GlobalCache<Metavariables>& cache,
     161              :       const ArrayIndex& array_index, const ActionList /*meta*/,
     162              :       const ParallelComponent* const parallel_component) {
     163              :     // Dispatch to the correct `apply` overload based on type of initial data
     164              :     using initial_data_classes =
     165              :         tmpl::at<typename Metavariables::factory_creation::factory_classes,
     166              :                  evolution::initial_data::InitialData>;
     167              :     return call_with_dynamic_type<Parallel::iterable_action_return_t,
     168              :                                   initial_data_classes>(
     169              :         &db::get<evolution::initial_data::Tags::InitialData>(box),
     170              :         [&box, &cache, &array_index,
     171              :          &parallel_component](const auto* const initial_data) {
     172              :           return apply(make_not_null(&box), *initial_data, cache, array_index,
     173              :                        parallel_component);
     174              :         });
     175              :   }
     176              : 
     177              :  private:
     178            0 :   static constexpr size_t Dim = 3;
     179              : 
     180              :   // Numeric initial data
     181              :   template <typename DbTagsList, typename Metavariables, typename ArrayIndex,
     182              :             typename ParallelComponent>
     183            0 :   static Parallel::iterable_action_return_t apply(
     184              :       const gsl::not_null<db::DataBox<DbTagsList>*> /*box*/,
     185              :       const NumericInitialData& initial_data,
     186              :       Parallel::GlobalCache<Metavariables>& cache,
     187              :       const ArrayIndex& array_index, const ParallelComponent* const /*meta*/) {
     188              :     // If we are using GH Numeric ID, then we don't have to set Pi and Phi since
     189              :     // we are reading them in. Also we only need to mutate this tag once so do
     190              :     // it on the first element.
     191              :     if (is_zeroth_element(array_index) and
     192              :         std::holds_alternative<gh::NumericInitialData::GhVars>(
     193              :             initial_data.gh_numeric_id().selected_variables())) {
     194              :       Parallel::mutate<gh::Tags::SetPiAndPhiFromConstraints,
     195              :                        gh::gauges::SetPiAndPhiFromConstraintsCacheMutator>(
     196              :           cache, false);
     197              :     }
     198              :     // Select the subset of the available variables that we want to read from
     199              :     // the volume data file
     200              :     tuples::tagged_tuple_from_typelist<db::wrap_tags_in<
     201              :         importers::Tags::Selected, NumericInitialData::all_vars>>
     202              :         selected_fields{};
     203              :     initial_data.select_for_import(make_not_null(&selected_fields));
     204              :     // Dispatch loading the variables from the volume data file
     205              :     // - Not using `ckLocalBranch` here to make sure the simple action
     206              :     //   invocation is asynchronous.
     207              :     auto& reader_component = Parallel::get_parallel_component<
     208              :         importers::ElementDataReader<Metavariables>>(cache);
     209              :     Parallel::simple_action<importers::Actions::ReadAllVolumeDataAndDistribute<
     210              :         3, NumericInitialData::all_vars, ParallelComponent>>(
     211              :         reader_component, initial_data.importer_options(),
     212              :         initial_data.volume_data_id(), std::move(selected_fields));
     213              :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     214              :   }
     215              : 
     216              :   // "AnalyticData"-type initial data
     217              :   template <typename DbTagsList, typename InitialData, typename Metavariables,
     218              :             typename ArrayIndex, typename ParallelComponent>
     219            0 :   static Parallel::iterable_action_return_t apply(
     220              :       const gsl::not_null<db::DataBox<DbTagsList>*> box,
     221              :       const InitialData& initial_data,
     222              :       Parallel::GlobalCache<Metavariables>& /*cache*/,
     223              :       const ArrayIndex& /*array_index*/,
     224              :       const ParallelComponent* const /*meta*/) {
     225              :     // Get ADM + scalar variables from analytic data / solution
     226              :     const auto& [coords, mesh, inv_jacobian] = [&box]() {
     227              :       return std::forward_as_tuple(
     228              :           db::get<domain::Tags::Coordinates<Dim, Frame::Inertial>>(*box),
     229              :           db::get<domain::Tags::Mesh<Dim>>(*box),
     230              :           db::get<domain::Tags::InverseJacobian<Dim, Frame::ElementLogical,
     231              :                                                 Frame::Inertial>>(*box));
     232              :     }();
     233              :     auto vars = evolution::Initialization::initial_data(
     234              :         initial_data, coords, db::get<::Tags::Time>(*box),
     235              :         tmpl::append<tmpl::list<gr::Tags::SpatialMetric<DataVector, 3>,
     236              :                                 gr::Tags::Lapse<DataVector>,
     237              :                                 gr::Tags::Shift<DataVector, 3>,
     238              :                                 gr::Tags::ExtrinsicCurvature<DataVector, 3>>,
     239              :                      // Don't use the scalar gradient
     240              :                      tmpl::list<CurvedScalarWave::Tags::Psi,
     241              :                                 CurvedScalarWave::Tags::Pi>>{});
     242              :     const auto& spatial_metric =
     243              :         get<gr::Tags::SpatialMetric<DataVector, 3>>(vars);
     244              :     const auto& lapse = get<gr::Tags::Lapse<DataVector>>(vars);
     245              : 
     246              :     const auto& shift = get<gr::Tags::Shift<DataVector, 3>>(vars);
     247              : 
     248              :     const auto& extrinsic_curvature =
     249              :         get<gr::Tags::ExtrinsicCurvature<DataVector, 3>>(vars);
     250              : 
     251              :     // Compute GH vars from ADM vars
     252              :     db::mutate<gr::Tags::SpacetimeMetric<DataVector, 3>,
     253              :                gh::Tags::Pi<DataVector, 3>, gh::Tags::Phi<DataVector, 3>>(
     254              :         &gh::initial_gh_variables_from_adm<3>, box, spatial_metric, lapse,
     255              :         shift, extrinsic_curvature, mesh, inv_jacobian, coords);
     256              : 
     257              :     // Move scalar variables and compute gradient
     258              :     db::mutate<CurvedScalarWave::Tags::Psi, CurvedScalarWave::Tags::Pi,
     259              :                CurvedScalarWave::Tags::Phi<3>>(
     260              :         [&vars](const gsl::not_null<Scalar<DataVector>*> psi_scalar,
     261              :                 const gsl::not_null<Scalar<DataVector>*> pi_scalar,
     262              :                 const gsl::not_null<tnsr::i<DataVector, 3>*> phi_scalar,
     263              :                 const Mesh<3>& local_mesh,
     264              :                 const InverseJacobian<DataVector, 3_st, Frame::ElementLogical,
     265              :                                       Frame::Inertial>& local_inv_jacobian) {
     266              :           *psi_scalar = std::move(get<CurvedScalarWave::Tags::Psi>(vars));
     267              :           *pi_scalar = std::move(get<CurvedScalarWave::Tags::Pi>(vars));
     268              :           // Set Phi to the numerical spatial derivative of the scalar
     269              :           partial_derivative(phi_scalar, *psi_scalar, local_mesh,
     270              :                              local_inv_jacobian);
     271              :         },
     272              :         box, mesh, inv_jacobian);
     273              : 
     274              :     // No need to import numeric initial data, so we terminate the phase by
     275              :     // pausing the algorithm on this element
     276              :     return {Parallel::AlgorithmExecution::Pause, std::nullopt};
     277              :   }
     278              : };
     279              : 
     280              : /*!
     281              :  * \brief Receive numeric initial data loaded by
     282              :  * ScalarTensor::Actions::SetInitialData.
     283              :  */
     284            1 : struct ReceiveNumericInitialData {
     285            0 :   static constexpr size_t Dim = 3;
     286            0 :   using inbox_tags =
     287              :       tmpl::list<importers::Tags::VolumeData<NumericInitialData::all_vars>>;
     288              : 
     289              :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
     290              :             typename ActionList, typename ParallelComponent>
     291            0 :   static Parallel::iterable_action_return_t apply(
     292              :       db::DataBox<DbTagsList>& box, tuples::TaggedTuple<InboxTags...>& inboxes,
     293              :       const Parallel::GlobalCache<Metavariables>& /*cache*/,
     294              :       const ElementId<Dim>& /*element_id*/, const ActionList /*meta*/,
     295              :       const ParallelComponent* const /*meta*/) {
     296              :     auto& inbox =
     297              :         tuples::get<importers::Tags::VolumeData<NumericInitialData::all_vars>>(
     298              :             inboxes);
     299              :     const auto& initial_data = dynamic_cast<const NumericInitialData&>(
     300              :         db::get<evolution::initial_data::Tags::InitialData>(box));
     301              :     const size_t volume_data_id = initial_data.volume_data_id();
     302              :     if (inbox.find(volume_data_id) == inbox.end()) {
     303              :       return {Parallel::AlgorithmExecution::Retry, std::nullopt};
     304              :     }
     305              :     auto numeric_data = std::move(inbox.extract(volume_data_id).mapped());
     306              : 
     307              :     const auto& mesh = db::get<domain::Tags::Mesh<Dim>>(box);
     308              :     const auto& inv_jacobian =
     309              :         db::get<domain::Tags::InverseJacobian<Dim, Frame::ElementLogical,
     310              :                                               Frame::Inertial>>(box);
     311              :     const auto& inertial_coords =
     312              :         db::get<domain::Tags::Coordinates<Dim, Frame::Inertial>>(box);
     313              : 
     314              :     db::mutate<gr::Tags::SpacetimeMetric<DataVector, 3>,
     315              :                gh::Tags::Pi<DataVector, 3>, gh::Tags::Phi<DataVector, 3>,
     316              :                CurvedScalarWave::Tags::Psi, CurvedScalarWave::Tags::Pi,
     317              :                CurvedScalarWave::Tags::Phi<3>>(
     318              :         [&initial_data, &numeric_data, &mesh, &inv_jacobian, &inertial_coords](
     319              :             const gsl::not_null<tnsr::aa<DataVector, 3>*> spacetime_metric,
     320              :             const gsl::not_null<tnsr::aa<DataVector, 3>*> pi,
     321              :             const gsl::not_null<tnsr::iaa<DataVector, 3>*> phi,
     322              :             const gsl::not_null<Scalar<DataVector>*> psi_scalar,
     323              :             const gsl::not_null<Scalar<DataVector>*> pi_scalar,
     324              :             const gsl::not_null<tnsr::i<DataVector, 3>*> phi_scalar) {
     325              :           initial_data.set_initial_data(spacetime_metric, pi, phi,
     326              : 
     327              :                                         psi_scalar, pi_scalar, phi_scalar,
     328              : 
     329              :                                         make_not_null(&numeric_data), mesh,
     330              :                                         inv_jacobian, inertial_coords);
     331              :         },
     332              :         make_not_null(&box));
     333              : 
     334              :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     335              :   }
     336              : };
     337              : 
     338              : }  // namespace Actions
     339              : 
     340              : }  // namespace ScalarTensor
        

Generated by: LCOV version 2.0-1