SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/GeneralizedHarmonic/Actions - SetInitialData.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 16.0 % 50 8
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 <pup.h>
       8              : #include <string>
       9              : #include <variant>
      10              : #include <vector>
      11              : 
      12              : #include "DataStructures/DataBox/DataBox.hpp"
      13              : #include "DataStructures/DataBox/Tag.hpp"
      14              : #include "DataStructures/DataBox/TagName.hpp"
      15              : #include "DataStructures/DataVector.hpp"
      16              : #include "DataStructures/TaggedTuple.hpp"
      17              : #include "DataStructures/Tensor/Tensor.hpp"
      18              : #include "Domain/Structure/ElementId.hpp"
      19              : #include "Domain/Tags.hpp"
      20              : #include "Evolution/Initialization/InitialData.hpp"
      21              : #include "Evolution/Systems/GeneralizedHarmonic/GaugeSourceFunctions/SetPiAndPhiFromConstraints.hpp"
      22              : #include "Evolution/Systems/GeneralizedHarmonic/System.hpp"
      23              : #include "Evolution/Systems/GeneralizedHarmonic/Tags.hpp"
      24              : #include "IO/Importers/Actions/ReadVolumeData.hpp"
      25              : #include "IO/Importers/ElementDataReader.hpp"
      26              : #include "IO/Importers/Tags.hpp"
      27              : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp"
      28              : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
      29              : #include "Parallel/AlgorithmExecution.hpp"
      30              : #include "Parallel/GlobalCache.hpp"
      31              : #include "Parallel/Invoke.hpp"
      32              : #include "PointwiseFunctions/AnalyticData/AnalyticData.hpp"
      33              : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp"
      34              : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
      35              : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
      36              : #include "PointwiseFunctions/InitialDataUtilities/Tags/InitialData.hpp"
      37              : #include "PointwiseFunctions/InitialDataUtilities/WithNoise.hpp"
      38              : #include "Utilities/Algorithm.hpp"
      39              : #include "Utilities/CallWithDynamicType.hpp"
      40              : #include "Utilities/ErrorHandling/Error.hpp"
      41              : #include "Utilities/Gsl.hpp"
      42              : #include "Utilities/Serialization/CharmPupable.hpp"
      43              : #include "Utilities/TMPL.hpp"
      44              : 
      45              : /// \cond
      46              : namespace Tags {
      47              : struct Time;
      48              : }  // namespace Tags
      49              : /// \endcond
      50              : 
      51              : namespace gh {
      52              : 
      53              : /*!
      54              :  * \brief Compute initial GH variables from ADM variables
      55              :  *
      56              :  * - The spacetime metric is assembled from the spatial metric, lapse, and
      57              :  *   shift. See `gr::spacetime_metric` for details.
      58              :  * - Phi is set to the numerical derivative of the spacetime metric. This
      59              :  *   ensures that the 3-index constraint is initially satisfied.
      60              :  * - Pi is computed by choosing the time derivatives of lapse and shift to be
      61              :  *   zero. The `gh::gauges::SetPiAndPhiFromConstraints` mutator exists to
      62              :  *   override Pi later in the algorithm (it should be combined with this
      63              :  *   function).
      64              :  */
      65              : template <size_t Dim>
      66            1 : void initial_gh_variables_from_adm(
      67              :     gsl::not_null<tnsr::aa<DataVector, Dim>*> spacetime_metric,
      68              :     gsl::not_null<tnsr::aa<DataVector, Dim>*> pi,
      69              :     gsl::not_null<tnsr::iaa<DataVector, Dim>*> phi,
      70              :     const tnsr::ii<DataVector, Dim>& spatial_metric,
      71              :     const Scalar<DataVector>& lapse, const tnsr::I<DataVector, Dim>& shift,
      72              :     const tnsr::ii<DataVector, Dim>& extrinsic_curvature, const Mesh<Dim>& mesh,
      73              :     const InverseJacobian<DataVector, Dim, Frame::ElementLogical,
      74              :                           Frame::Inertial>& inv_jacobian,
      75              :     const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords);
      76              : 
      77              : /*!
      78              :  * \brief Numeric initial data loaded from volume data files
      79              :  *
      80              :  * This class can be factory-created in the input file to start an evolution
      81              :  * from numeric initial data. It selects the set of variables to load from
      82              :  * the volume data file (ADM or GH variables).
      83              :  */
      84            1 : class NumericInitialData : public evolution::initial_data::InitialData {
      85              :  public:
      86              :   /// Name of a variable in the volume data file
      87              :   template <typename Tag>
      88            1 :   struct VarName {
      89            0 :     using tag = Tag;
      90            0 :     static std::string name() { return db::tag_name<Tag>(); }
      91            0 :     using type = std::string;
      92            0 :     static constexpr Options::String help =
      93              :         "Name of the variable in the volume data file";
      94              :   };
      95              : 
      96              :   // These are the sets of variables that we support loading from volume data
      97              :   // files:
      98              :   // - ADM variables
      99            0 :   using adm_vars =
     100              :       tmpl::list<gr::Tags::SpatialMetric<DataVector, 3>,
     101              :                  gr::Tags::Lapse<DataVector>, gr::Tags::Shift<DataVector, 3>,
     102              :                  gr::Tags::ExtrinsicCurvature<DataVector, 3>>;
     103            0 :   struct AdmVars : tuples::tagged_tuple_from_typelist<
     104              :                        db::wrap_tags_in<VarName, adm_vars>> {
     105            0 :     static constexpr Options::String help =
     106              :         "ADM variables: 'Lapse', 'Shift', 'SpatialMetric' and "
     107              :         "'ExtrinsicCurvature'. The initial GH variables will be computed "
     108              :         "from these numeric fields, as well as their numeric spatial "
     109              :         "derivatives on the computational grid. The GH variable Pi will be set "
     110              :         "to satisfy the gauge constraint using the evolution gauge. The GH "
     111              :         "variable Phi will be set to satisfy the 3-index constraint.";
     112            0 :     using options = tags_list;
     113              :     using TaggedTuple::TaggedTuple;
     114              :   };
     115              : 
     116              :   // - Generalized harmonic variables
     117            0 :   using gh_vars = tmpl::list<gr::Tags::SpacetimeMetric<DataVector, 3>,
     118              :                              Tags::Pi<DataVector, 3>, Tags::Phi<DataVector, 3>>;
     119            0 :   struct GhVars
     120              :       : tuples::tagged_tuple_from_typelist<db::wrap_tags_in<VarName, gh_vars>> {
     121            0 :     static constexpr Options::String help =
     122              :         "GH variables: 'SpacetimeMetric', 'Pi', and 'Phi'. These variables are "
     123              :         "used to set the initial data directly.";
     124            0 :     using options = tags_list;
     125              :     using TaggedTuple::TaggedTuple;
     126              :   };
     127              : 
     128              :   // Collect all variables that we support loading from volume data files.
     129              :   // Remember to `tmpl::remove_duplicates` when adding overlapping sets of
     130              :   // vars.
     131            0 :   using all_vars = tmpl::append<adm_vars, gh_vars>;
     132              : 
     133              :   // Input-file options
     134            0 :   struct Variables {
     135              :     // The user can supply any of these choices of variables in the input
     136              :     // file
     137            0 :     using type = std::variant<AdmVars, GhVars>;
     138            0 :     static constexpr Options::String help =
     139              :         "Set of initial data variables from which the generalized harmonic "
     140              :         "system variables are computed.";
     141              :   };
     142              : 
     143            0 :   using options = tmpl::list<importers::OptionTags::VolumeData, Variables>;
     144              : 
     145            0 :   static constexpr Options::String help =
     146              :       "Numeric initial data loaded from volume data files";
     147              : 
     148            0 :   NumericInitialData() = default;
     149            0 :   NumericInitialData(const NumericInitialData& rhs) = default;
     150            0 :   NumericInitialData& operator=(const NumericInitialData& rhs) = default;
     151            0 :   NumericInitialData(NumericInitialData&& /*rhs*/) = default;
     152            0 :   NumericInitialData& operator=(NumericInitialData&& /*rhs*/) = default;
     153            0 :   ~NumericInitialData() = default;
     154              : 
     155              :   /// \cond
     156              :   explicit NumericInitialData(CkMigrateMessage* msg);
     157              :   using PUP::able::register_constructor;
     158              :   WRAPPED_PUPable_decl_template(NumericInitialData);
     159              :   /// \endcond
     160              : 
     161            0 :   std::unique_ptr<evolution::initial_data::InitialData> get_clone()
     162              :       const override {
     163              :     return std::make_unique<NumericInitialData>(*this);
     164              :   }
     165              : 
     166            0 :   NumericInitialData(importers::ImporterOptions importer_options,
     167              :                      std::variant<AdmVars, GhVars> selected_variables);
     168              : 
     169            0 :   const importers::ImporterOptions& importer_options() const {
     170              :     return importer_options_;
     171              :   }
     172              : 
     173            0 :   const std::variant<AdmVars, GhVars>& selected_variables() const {
     174              :     return selected_variables_;
     175              :   }
     176              : 
     177              :   /*!
     178              :    * \brief Unique identifier for loading this volume data
     179              :    *
     180              :    * Involves a hash of the type name and the volume data file names.
     181              :    */
     182            1 :   size_t volume_data_id() const;
     183              : 
     184              :   /*!
     185              :    * \brief Selects which of the `fields` to import based on the choices in the
     186              :    * input-file options
     187              :    *
     188              :    * The `fields` are all datasets that are available to import, represented by
     189              :    * `importers::Tags::Selected<Tag>` tags. We select only those that we need by
     190              :    * setting their dataset name.
     191              :    */
     192              :   template <typename... AllTags>
     193            1 :   void select_for_import(
     194              :       const gsl::not_null<tuples::TaggedTuple<AllTags...>*> fields) const {
     195              :     // Select the subset of the available variables that we want to read from
     196              :     // the volume data file
     197              :     std::visit(
     198              :         [&fields](const auto& vars) {
     199              :           // This lambda is invoked with the set of vars selected in the input
     200              :           // file, which map to the tensor names that should be read from the H5
     201              :           // file
     202              :           using selected_vars = std::decay_t<decltype(vars)>;
     203              :           // Get the mapped tensor name from the input file and select it in the
     204              :           // set of all possible vars.
     205              :           tmpl::for_each<typename selected_vars::tags_list>(
     206              :               [&fields, &vars](const auto tag_v) {
     207              :                 using tag = typename std::decay_t<decltype(tag_v)>::type::tag;
     208              :                 get<importers::Tags::Selected<tag>>(*fields) =
     209              :                     get<VarName<tag>>(vars);
     210              :               });
     211              :         },
     212              :         selected_variables_);
     213              :   }
     214              : 
     215              :   /*!
     216              :    * \brief Set GH initial data given numeric data loaded from files
     217              :    *
     218              :    * The `numeric_data` contains the datasets selected above (and possibly
     219              :    * more). We either set the GH variables directly, or compute them from the
     220              :    * ADM variables.
     221              :    */
     222              :   template <typename... AllTags>
     223            1 :   void set_initial_data(
     224              :       const gsl::not_null<tnsr::aa<DataVector, 3>*> spacetime_metric,
     225              :       const gsl::not_null<tnsr::aa<DataVector, 3>*> pi,
     226              :       const gsl::not_null<tnsr::iaa<DataVector, 3>*> phi,
     227              :       const gsl::not_null<tuples::TaggedTuple<AllTags...>*> numeric_data,
     228              :       const Mesh<3>& mesh,
     229              :       const InverseJacobian<DataVector, 3, Frame::ElementLogical,
     230              :                             Frame::Inertial>& inv_jacobian,
     231              :       const tnsr::I<DataVector, 3, Frame::Inertial> inertial_coords) const {
     232              :     if (std::holds_alternative<NumericInitialData::GhVars>(
     233              :             selected_variables_)) {
     234              :       // We have loaded the GH system variables from the file, so just move the
     235              :       // data for spacetime_metric and Pi into the DataBox directly, with no
     236              :       // conversion needed. Set Phi to the spatial derivative of the spacetime
     237              :       // metric to enforce the 3-index constraint.
     238              :       *spacetime_metric = std::move(
     239              :           get<gr::Tags::SpacetimeMetric<DataVector, 3>>(*numeric_data));
     240              :       *pi = std::move(get<Tags::Pi<DataVector, 3>>(*numeric_data));
     241              :       *phi = get<Tags::Phi<DataVector, 3>>(*numeric_data);
     242              :     } else if (std::holds_alternative<NumericInitialData::AdmVars>(
     243              :                    selected_variables_)) {
     244              :       // We have loaded ADM variables from the file. Convert to GH variables.
     245              :       const auto& spatial_metric =
     246              :           get<gr::Tags::SpatialMetric<DataVector, 3>>(*numeric_data);
     247              :       const auto& lapse = get<gr::Tags::Lapse<DataVector>>(*numeric_data);
     248              :       const auto& shift = get<gr::Tags::Shift<DataVector, 3>>(*numeric_data);
     249              :       const auto& extrinsic_curvature =
     250              :           get<gr::Tags::ExtrinsicCurvature<DataVector, 3>>(*numeric_data);
     251              : 
     252              :       initial_gh_variables_from_adm(spacetime_metric, pi, phi, spatial_metric,
     253              :                                     lapse, shift, extrinsic_curvature, mesh,
     254              :                                     inv_jacobian, inertial_coords);
     255              :     } else {
     256              :       ERROR(
     257              :           "These initial data variables are not implemented yet. Please add "
     258              :           "an implementation to gh::NumericInitialData.");
     259              :     }
     260              :   }
     261              : 
     262            0 :   void pup(PUP::er& p) override;
     263              : 
     264            0 :   friend bool operator==(const NumericInitialData& lhs,
     265              :                          const NumericInitialData& rhs);
     266              : 
     267              :  private:
     268            0 :   importers::ImporterOptions importer_options_;
     269            0 :   std::variant<AdmVars, GhVars> selected_variables_{};
     270              : };
     271              : 
     272            0 : namespace Actions {
     273              : 
     274              : /*!
     275              :  * \brief Dispatch loading numeric initial data from files or set analytic
     276              :  * initial data.
     277              :  *
     278              :  * Place this action before
     279              :  * gh::Actions::ReceiveNumericInitialData in the action list.
     280              :  * See importers::Actions::ReadAllVolumeDataAndDistribute for details, which is
     281              :  * invoked by this action.
     282              :  * Analytic initial data is set directly by this action and terminates the
     283              :  * phase.
     284              :  */
     285            1 : struct SetInitialData {
     286            0 :   using const_global_cache_tags =
     287              :       tmpl::list<evolution::initial_data::Tags::InitialData>;
     288              : 
     289              :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
     290              :             typename ArrayIndex, typename ActionList,
     291              :             typename ParallelComponent>
     292            0 :   static Parallel::iterable_action_return_t apply(
     293              :       db::DataBox<DbTagsList>& box,
     294              :       const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     295              :       Parallel::GlobalCache<Metavariables>& cache,
     296              :       const ArrayIndex& array_index, const ActionList /*meta*/,
     297              :       const ParallelComponent* const parallel_component) {
     298              :     // Dispatch to the correct `apply` overload based on type of initial data
     299              :     using initial_data_classes =
     300              :         tmpl::at<typename Metavariables::factory_creation::factory_classes,
     301              :                  evolution::initial_data::InitialData>;
     302              :     return call_with_dynamic_type<Parallel::iterable_action_return_t,
     303              :                                   initial_data_classes>(
     304              :         &db::get<evolution::initial_data::Tags::InitialData>(box),
     305              :         [&box, &cache, &array_index,
     306              :          &parallel_component](const auto* const initial_data) {
     307              :           return apply(make_not_null(&box), *initial_data, cache, array_index,
     308              :                        parallel_component);
     309              :         });
     310              :   }
     311              : 
     312              :  private:
     313              :   // Numeric initial data
     314              :   template <typename DbTagsList, typename Metavariables, typename ArrayIndex,
     315              :             typename ParallelComponent>
     316            0 :   static Parallel::iterable_action_return_t apply(
     317              :       const gsl::not_null<db::DataBox<DbTagsList>*> /*box*/,
     318              :       const NumericInitialData& initial_data,
     319              :       Parallel::GlobalCache<Metavariables>& cache,
     320              :       const ArrayIndex& array_index, const ParallelComponent* const /*meta*/) {
     321              :     // If we are using GH Numeric ID, then we don't have to set Pi and Phi since
     322              :     // we are reading them in. Also we only need to mutate this tag once so do
     323              :     // it on the first element.
     324              :     if (is_zeroth_element(array_index) and
     325              :         std::holds_alternative<NumericInitialData::GhVars>(
     326              :             initial_data.selected_variables())) {
     327              :       Parallel::mutate<Tags::SetPiAndPhiFromConstraints,
     328              :                        gh::gauges::SetPiAndPhiFromConstraintsCacheMutator>(
     329              :           cache, false);
     330              :     }
     331              : 
     332              :     // Select the subset of the available variables that we want to read from
     333              :     // the volume data file
     334              :     tuples::tagged_tuple_from_typelist<db::wrap_tags_in<
     335              :         importers::Tags::Selected, NumericInitialData::all_vars>>
     336              :         selected_fields{};
     337              :     initial_data.select_for_import(make_not_null(&selected_fields));
     338              :     // Dispatch loading the variables from the volume data file
     339              :     // - Not using `ckLocalBranch` here to make sure the simple action
     340              :     //   invocation is asynchronous.
     341              :     auto& reader_component = Parallel::get_parallel_component<
     342              :         importers::ElementDataReader<Metavariables>>(cache);
     343              :     Parallel::simple_action<importers::Actions::ReadAllVolumeDataAndDistribute<
     344              :         3, NumericInitialData::all_vars, ParallelComponent>>(
     345              :         reader_component, initial_data.importer_options(),
     346              :         initial_data.volume_data_id(), std::move(selected_fields));
     347              :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     348              :   }
     349              : 
     350              :   // WithNoise initial data — applies analytic inner solution then adds noise
     351              :   template <typename DbTagsList, typename Metavariables, typename ArrayIndex,
     352              :             typename ParallelComponent>
     353            0 :   static Parallel::iterable_action_return_t apply(
     354              :       const gsl::not_null<db::DataBox<DbTagsList>*> box,
     355              :       const evolution::initial_data::WithNoise& with_noise,
     356              :       Parallel::GlobalCache<Metavariables>& cache,
     357              :       const ArrayIndex& array_index,
     358              :       const ParallelComponent* const parallel_component) {
     359              :     static constexpr size_t Dim = Metavariables::volume_dim;
     360              :     // Dispatch on the inner solution to set GH variables normally.
     361              :     using initial_data_classes =
     362              :         tmpl::at<typename Metavariables::factory_creation::factory_classes,
     363              :                  evolution::initial_data::InitialData>;
     364              :     const auto result =
     365              :         call_with_dynamic_type<Parallel::iterable_action_return_t,
     366              :                                initial_data_classes>(
     367              :             &with_noise.solution(),
     368              :             [&box, &cache, &array_index, &parallel_component](
     369              :                 const auto* const inner) -> Parallel::iterable_action_return_t {
     370              :               using inner_type = std::decay_t<decltype(*inner)>;
     371              :               if constexpr (is_analytic_data_v<inner_type> or
     372              :                             is_analytic_solution_v<inner_type>) {
     373              :                 return apply(box, *inner, cache, array_index,
     374              :                              parallel_component);
     375              :               } else {
     376              :                 ERROR(
     377              :                     "WithNoise: the inner Solution must be an analytic "
     378              :                     "solution or analytic data. Numeric initial data "
     379              :                     "cannot be wrapped by WithNoise.");
     380              :               }
     381              :             });
     382              :     // Compute inertial-coordinate-based per-element seed.
     383              :     const size_t element_seed = evolution::initial_data::make_element_seed(
     384              :         with_noise.seed(),
     385              :         db::get<domain::Tags::Coordinates<Dim, Frame::Inertial>>(*box));
     386              :     // Apply noise to each evolved GH variable.
     387              :     using evolved_vars_list =
     388              :         typename gh::System<Dim>::variables_tag::tags_list;
     389              :     const auto& targets = with_noise.variables();
     390              :     const bool noise_all = alg::found(targets, std::string{"All"});
     391              :     // Validate variable names against the system's evolved variables.
     392              :     if (not noise_all) {
     393              :       std::vector<std::string> valid_names{};
     394              :       tmpl::for_each<evolved_vars_list>(
     395              :           [&valid_names]<typename Tag>(tmpl::type_<Tag> /*meta*/) {
     396              :             valid_names.push_back(db::tag_name<Tag>());
     397              :           });
     398              :       for (const auto& target : targets) {
     399              :         if (not alg::found(valid_names, target)) {
     400              :           ERROR("WithNoise: unknown variable name '"
     401              :                 << target << "'. Valid names for this system are: "
     402              :                 << valid_names << ". Use [\"All\"] to noise every variable.");
     403              :         }
     404              :       }
     405              :     }
     406              :     size_t component_offset = 0;
     407              :     tmpl::for_each<evolved_vars_list>(
     408              :         [&]<typename Tag>(tmpl::type_<Tag> /*meta*/) {
     409              :           const size_t this_offset = component_offset;
     410              :           if (noise_all or alg::found(targets, db::tag_name<Tag>())) {
     411              :             db::mutate<Tag>(
     412              :                 [&with_noise, element_seed,
     413              :                  this_offset](const gsl::not_null<typename Tag::type*> tensor) {
     414              :                   evolution::initial_data::add_noise_to_tensor(
     415              :                       tensor, with_noise.amplitude(),
     416              :                       with_noise.amplitude_type(), element_seed, this_offset);
     417              :                 },
     418              :                 box);
     419              :           }
     420              :           component_offset += std::decay_t<typename Tag::type>::size();
     421              :         });
     422              :     return result;
     423              :   }
     424              : 
     425              :   // "AnalyticData"-type initial data
     426              :   template <typename DbTagsList, typename InitialData, typename Metavariables,
     427              :             typename ArrayIndex, typename ParallelComponent>
     428            0 :   static Parallel::iterable_action_return_t apply(
     429              :       const gsl::not_null<db::DataBox<DbTagsList>*> box,
     430              :       const InitialData& initial_data,
     431              :       Parallel::GlobalCache<Metavariables>& /*cache*/,
     432              :       const ArrayIndex& /*array_index*/,
     433              :       const ParallelComponent* const /*meta*/) {
     434              :     static constexpr size_t Dim = Metavariables::volume_dim;
     435              : 
     436              :     // Get ADM variables from analytic data / solution
     437              :     const auto& x =
     438              :         db::get<domain::Tags::Coordinates<Dim, Frame::Inertial>>(*box);
     439              :     const auto adm_vars = evolution::Initialization::initial_data(
     440              :         initial_data, x, db::get<::Tags::Time>(*box),
     441              :         tmpl::list<gr::Tags::SpatialMetric<DataVector, Dim>,
     442              :                    gr::Tags::Lapse<DataVector>,
     443              :                    gr::Tags::Shift<DataVector, Dim>,
     444              :                    gr::Tags::ExtrinsicCurvature<DataVector, Dim>>{});
     445              :     const auto& spatial_metric =
     446              :         get<gr::Tags::SpatialMetric<DataVector, Dim>>(adm_vars);
     447              :     const auto& lapse = get<gr::Tags::Lapse<DataVector>>(adm_vars);
     448              :     const auto& shift = get<gr::Tags::Shift<DataVector, Dim>>(adm_vars);
     449              :     const auto& extrinsic_curvature =
     450              :         get<gr::Tags::ExtrinsicCurvature<DataVector, Dim>>(adm_vars);
     451              : 
     452              :     // Compute GH vars from ADM vars
     453              :     const auto& mesh = db::get<domain::Tags::Mesh<Dim>>(*box);
     454              :     const auto& inv_jacobian =
     455              :         db::get<domain::Tags::InverseJacobian<Dim, Frame::ElementLogical,
     456              :                                               Frame::Inertial>>(*box);
     457              :     const auto& inertial_coords =
     458              :         db::get<domain::Tags::Coordinates<Dim, Frame::Inertial>>(*box);
     459              :     db::mutate<gr::Tags::SpacetimeMetric<DataVector, Dim>,
     460              :                Tags::Pi<DataVector, Dim>, Tags::Phi<DataVector, Dim>>(
     461              :         &gh::initial_gh_variables_from_adm<Dim>, box, spatial_metric, lapse,
     462              :         shift, extrinsic_curvature, mesh, inv_jacobian, inertial_coords);
     463              : 
     464              :     // No need to import numeric initial data, so we terminate the phase by
     465              :     // pausing the algorithm on this element
     466              :     return {Parallel::AlgorithmExecution::Pause, std::nullopt};
     467              :   }
     468              : };
     469              : 
     470              : /*!
     471              :  * \brief Receive numeric initial data loaded by gh::Actions::SetInitialData.
     472              :  *
     473              :  * Place this action in the action list after
     474              :  * gh::Actions::SetInitialData to wait until the data
     475              :  * for this element has arrived, and then transform the data to GH variables and
     476              :  * store it in the DataBox to be used as initial data.
     477              :  *
     478              :  * This action modifies the following tags in the DataBox:
     479              :  * - gr::Tags::SpacetimeMetric<DataVector, 3>
     480              :  * - gh::Tags::Pi<DataVector, 3>
     481              :  * - gh::Tags::Phi<DataVector, 3>
     482              :  */
     483            1 : struct ReceiveNumericInitialData {
     484            0 :   static constexpr size_t Dim = 3;
     485            0 :   using inbox_tags =
     486              :       tmpl::list<importers::Tags::VolumeData<NumericInitialData::all_vars>>;
     487              : 
     488              :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
     489              :             typename ActionList, typename ParallelComponent>
     490            0 :   static Parallel::iterable_action_return_t apply(
     491              :       db::DataBox<DbTagsList>& box, tuples::TaggedTuple<InboxTags...>& inboxes,
     492              :       const Parallel::GlobalCache<Metavariables>& /*cache*/,
     493              :       const ElementId<Dim>& /*element_id*/, const ActionList /*meta*/,
     494              :       const ParallelComponent* const /*meta*/) {
     495              :     auto& inbox =
     496              :         tuples::get<importers::Tags::VolumeData<NumericInitialData::all_vars>>(
     497              :             inboxes);
     498              :     const auto& initial_data = dynamic_cast<const NumericInitialData&>(
     499              :         db::get<evolution::initial_data::Tags::InitialData>(box));
     500              :     const auto& volume_data_id = initial_data.volume_data_id();
     501              :     if (inbox.find(volume_data_id) == inbox.end()) {
     502              :       return {Parallel::AlgorithmExecution::Retry, std::nullopt};
     503              :     }
     504              :     auto numeric_data = std::move(inbox.extract(volume_data_id).mapped());
     505              : 
     506              :     const auto& mesh = db::get<domain::Tags::Mesh<Dim>>(box);
     507              :     const auto& inv_jacobian =
     508              :         db::get<domain::Tags::InverseJacobian<Dim, Frame::ElementLogical,
     509              :                                               Frame::Inertial>>(box);
     510              :     const auto& inertial_coords =
     511              :         db::get<domain::Tags::Coordinates<Dim, Frame::Inertial>>(box);
     512              : 
     513              :     db::mutate<gr::Tags::SpacetimeMetric<DataVector, 3>,
     514              :                Tags::Pi<DataVector, 3>, Tags::Phi<DataVector, 3>>(
     515              :         [&initial_data, &numeric_data, &mesh, &inv_jacobian, &inertial_coords](
     516              :             const gsl::not_null<tnsr::aa<DataVector, 3>*> spacetime_metric,
     517              :             const gsl::not_null<tnsr::aa<DataVector, 3>*> pi,
     518              :             const gsl::not_null<tnsr::iaa<DataVector, 3>*> phi) {
     519              :           initial_data.set_initial_data(spacetime_metric, pi, phi,
     520              :                                         make_not_null(&numeric_data), mesh,
     521              :                                         inv_jacobian, inertial_coords);
     522              :         },
     523              :         make_not_null(&box));
     524              :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     525              :   }
     526              : };
     527              : 
     528              : }  // namespace Actions
     529              : }  // namespace gh
        

Generated by: LCOV version 2.0-1