SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/GeneralizedHarmonic/Actions - NumericInitialData.hpp Hit Total Coverage
Commit: cd74d65bdc718fd7e344eaec61dc6334dd4d366b Lines: 3 10 30.0 %
Date: 2022-08-12 23:56:47
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 <limits>
       8             : #include <optional>
       9             : #include <tuple>
      10             : 
      11             : #include "DataStructures/DataBox/DataBox.hpp"
      12             : #include "DataStructures/Tensor/Tensor.hpp"
      13             : #include "Domain/Structure/ElementId.hpp"
      14             : #include "Domain/Tags.hpp"
      15             : #include "Evolution/Systems/GeneralizedHarmonic/Tags.hpp"
      16             : #include "IO/Importers/Actions/ReadVolumeData.hpp"
      17             : #include "IO/Importers/ElementDataReader.hpp"
      18             : #include "IO/Importers/Tags.hpp"
      19             : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp"
      20             : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.tpp"
      21             : #include "Parallel/AlgorithmExecution.hpp"
      22             : #include "Parallel/GlobalCache.hpp"
      23             : #include "Parallel/Invoke.hpp"
      24             : #include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/Phi.hpp"
      25             : #include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/Pi.hpp"
      26             : #include "PointwiseFunctions/GeneralRelativity/SpacetimeMetric.hpp"
      27             : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
      28             : #include "PointwiseFunctions/GeneralRelativity/TimeDerivativeOfSpatialMetric.hpp"
      29             : #include "Utilities/ErrorHandling/Error.hpp"
      30             : #include "Utilities/Gsl.hpp"
      31             : #include "Utilities/Literals.hpp"
      32             : #include "Utilities/TMPL.hpp"
      33             : #include "Utilities/TaggedTuple.hpp"
      34             : 
      35           1 : namespace GeneralizedHarmonic {
      36             : 
      37             : namespace detail {
      38             : namespace OptionTags {
      39             : template <typename Tag>
      40             : struct VarName {
      41             :   using tag = Tag;
      42             :   static std::string name() { return db::tag_name<Tag>(); }
      43             :   using type = std::string;
      44             :   static constexpr Options::String help =
      45             :       "Name of the variable in the volume data file";
      46             : };
      47             : }  // namespace OptionTags
      48             : 
      49             : // These are the sets of variables that we support loading from volume data
      50             : // files:
      51             : // - ADM variables
      52             : using adm_vars =
      53             :     tmpl::list<gr::Tags::SpatialMetric<3, Frame::Inertial, DataVector>,
      54             :                gr::Tags::Lapse<DataVector>,
      55             :                gr::Tags::Shift<3, Frame::Inertial, DataVector>,
      56             :                gr::Tags::ExtrinsicCurvature<3, Frame::Inertial, DataVector>>;
      57             : struct Adm : tuples::tagged_tuple_from_typelist<
      58             :                  db::wrap_tags_in<OptionTags::VarName, adm_vars>> {
      59             :   using Base = tuples::tagged_tuple_from_typelist<
      60             :       db::wrap_tags_in<OptionTags::VarName, adm_vars>>;
      61             :   static constexpr Options::String help =
      62             :       "ADM variables: 'Lapse', 'Shift', 'SpatialMetric' and "
      63             :       "'ExtrinsicCurvature'. The initial GH variables will be computed from "
      64             :       "these numeric fields, as well as their numeric spatial derivatives on "
      65             :       "the computational grid.";
      66             :   using options = db::wrap_tags_in<OptionTags::VarName, adm_vars>;
      67             :   using Base::TaggedTuple;
      68             : };
      69             : // - Generalized harmonic variables
      70             : using gh_vars =
      71             :     tmpl::list<gr::Tags::SpacetimeMetric<3, Frame::Inertial, DataVector>,
      72             :                Tags::Pi<3, Frame::Inertial>, Tags::Phi<3, Frame::Inertial>>;
      73             : struct GeneralizedHarmonic
      74             :     : tuples::tagged_tuple_from_typelist<
      75             :           db::wrap_tags_in<OptionTags::VarName, gh_vars>> {
      76             :   using Base = tuples::tagged_tuple_from_typelist<
      77             :       db::wrap_tags_in<OptionTags::VarName, gh_vars>>;
      78             :   static constexpr Options::String help =
      79             :       "GH variables: 'SpacetimeMetric', 'Pi' and 'Phi'. These variables are "
      80             :       "used to set the initial data directly.";
      81             :   using options = db::wrap_tags_in<OptionTags::VarName, gh_vars>;
      82             :   using Base::TaggedTuple;
      83             : };
      84             : 
      85             : // Collect all variables that we support loading from volume data files.
      86             : // Remember to `tmpl::remove_duplicates` when adding overlapping sets of vars.
      87             : using all_numeric_vars = tmpl::append<adm_vars, gh_vars>;
      88             : 
      89             : namespace OptionTags {
      90             : template <typename ImporterOptionsGroup>
      91             : struct NumericInitialDataVariables {
      92             :   static std::string name() { return "Variables"; }
      93             :   // The user can supply any of these choices of variables in the input file
      94             :   using type = std::variant<Adm, GeneralizedHarmonic>;
      95             :   static constexpr Options::String help =
      96             :       "Set of initial data variables from which the generalized harmonic "
      97             :       "system variables are computed.";
      98             :   using group = ImporterOptionsGroup;
      99             : };
     100             : }  // namespace OptionTags
     101             : 
     102             : namespace Tags {
     103             : template <typename ImporterOptionsGroup>
     104             : struct NumericInitialDataVariables : db::SimpleTag {
     105             :   using type = typename OptionTags::NumericInitialDataVariables<
     106             :       ImporterOptionsGroup>::type;
     107             :   using option_tags =
     108             :       tmpl::list<OptionTags::NumericInitialDataVariables<ImporterOptionsGroup>>;
     109             :   static constexpr bool pass_metavariables = false;
     110             :   static type create_from_options(const type& value) { return value; }
     111             : };
     112             : }  // namespace Tags
     113             : }  // namespace detail
     114             : 
     115           0 : namespace Actions {
     116             : 
     117             : /*!
     118             :  * \brief Dispatch loading numeric initial data from files.
     119             :  *
     120             :  * Place this action before GeneralizedHarmonic::Actions::SetNumericInitialData
     121             :  * in the action list. See importers::Actions::ReadAllVolumeDataAndDistribute
     122             :  * for details, which is invoked by this action.
     123             :  *
     124             :  * \tparam ImporterOptionsGroup Option group in which options are placed.
     125             :  */
     126             : template <typename ImporterOptionsGroup>
     127           1 : struct ReadNumericInitialData {
     128           0 :   using const_global_cache_tags = tmpl::list<
     129             :       importers::Tags::FileGlob<ImporterOptionsGroup>,
     130             :       importers::Tags::Subgroup<ImporterOptionsGroup>,
     131             :       importers::Tags::ObservationValue<ImporterOptionsGroup>,
     132             :       detail::Tags::NumericInitialDataVariables<ImporterOptionsGroup>>;
     133             : 
     134             :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
     135             :             typename ArrayIndex, typename ActionList,
     136             :             typename ParallelComponent>
     137           0 :   static Parallel::iterable_action_return_t apply(
     138             :       db::DataBox<DbTagsList>& box,
     139             :       const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     140             :       Parallel::GlobalCache<Metavariables>& cache,
     141             :       const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
     142             :       const ParallelComponent* const /*meta*/) {
     143             :     // Select the subset of the available variables that we want to read from
     144             :     // the volume data file
     145             :     const auto& selected_initial_data_vars =
     146             :         get<detail::Tags::NumericInitialDataVariables<ImporterOptionsGroup>>(
     147             :             box);
     148             :     tuples::tagged_tuple_from_typelist<
     149             :         db::wrap_tags_in<importers::Tags::Selected, detail::all_numeric_vars>>
     150             :         selected_fields{};
     151             :     std::visit(
     152             :         [&selected_fields](const auto& vars) {
     153             :           // This lambda is invoked with the set of vars selected in the input
     154             :           // file, which map to the tensor names that should be read from the H5
     155             :           // file
     156             :           using selected_vars = std::decay_t<decltype(vars)>;
     157             :           // Get the mapped tensor name from the input file and select it in the
     158             :           // set of all possible vars.
     159             :           tmpl::for_each<typename selected_vars::tags_list>(
     160             :               [&selected_fields, &vars](const auto tag_v) {
     161             :                 using tag = typename std::decay_t<decltype(tag_v)>::type::tag;
     162             :                 get<importers::Tags::Selected<tag>>(selected_fields) =
     163             :                     get<detail::OptionTags::VarName<tag>>(vars);
     164             :               });
     165             :         },
     166             :         selected_initial_data_vars);
     167             :     // Dispatch loading the variables from the volume data file
     168             :     // - Not using `ckLocalBranch` here to make sure the simple action
     169             :     //   invocation is asynchronous.
     170             :     auto& reader_component = Parallel::get_parallel_component<
     171             :         importers::ElementDataReader<Metavariables>>(cache);
     172             :     Parallel::simple_action<importers::Actions::ReadAllVolumeDataAndDistribute<
     173             :         ImporterOptionsGroup, detail::all_numeric_vars, ParallelComponent>>(
     174             :         reader_component, std::move(selected_fields));
     175             :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     176             :   }
     177             : };
     178             : 
     179             : /*!
     180             :  * \brief Receive numeric initial data loaded by
     181             :  * GeneralizedHarmonic::Actions::ReadNumericInitialData.
     182             :  *
     183             :  * Place this action in the action list after
     184             :  * GeneralizedHarmonic::Actions::ReadNumericInitialData to wait until the data
     185             :  * for this element has arrived, and then transform the data to GH variables and
     186             :  * store it in the DataBox to be used as initial data.
     187             :  *
     188             :  * This action modifies the following tags in the DataBox:
     189             :  * - gr::Tags::SpacetimeMetric<3, Frame::Inertial, DataVector>
     190             :  * - GeneralizedHarmonic::Tags::Pi<3, Frame::Inertial>
     191             :  * - GeneralizedHarmonic::Tags::Phi<3, Frame::Inertial>
     192             :  *
     193             :  * \tparam ImporterOptionsGroup Option group in which options are placed.
     194             :  */
     195             : template <typename ImporterOptionsGroup>
     196           1 : struct SetNumericInitialData {
     197           0 :   static constexpr size_t Dim = 3;
     198           0 :   using inbox_tags =
     199             :       tmpl::list<importers::Tags::VolumeData<ImporterOptionsGroup,
     200             :                                              detail::all_numeric_vars>>;
     201             : 
     202             :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
     203             :             typename ActionList, typename ParallelComponent>
     204           0 :   static Parallel::iterable_action_return_t apply(
     205             :       db::DataBox<DbTagsList>& box, tuples::TaggedTuple<InboxTags...>& inboxes,
     206             :       const Parallel::GlobalCache<Metavariables>& /*cache*/,
     207             :       const ElementId<Dim>& /*element_id*/, const ActionList /*meta*/,
     208             :       const ParallelComponent* const /*meta*/) {
     209             :     auto& inbox = tuples::get<importers::Tags::VolumeData<
     210             :         ImporterOptionsGroup, detail::all_numeric_vars>>(inboxes);
     211             :     // Using 0 for the temporal ID since we only read the volume data once, so
     212             :     // there's no need to keep track of the temporal ID.
     213             :     if (inbox.find(0_st) == inbox.end()) {
     214             :       return {Parallel::AlgorithmExecution::Retry, std::nullopt};
     215             :     }
     216             :     auto numeric_initial_data = std::move(inbox.extract(0_st).mapped());
     217             : 
     218             :     const auto& selected_initial_data_vars =
     219             :         get<detail::Tags::NumericInitialDataVariables<ImporterOptionsGroup>>(
     220             :             box);
     221             :     if (std::holds_alternative<detail::GeneralizedHarmonic>(
     222             :             selected_initial_data_vars)) {
     223             :       // We have loaded the GH system variables from the file, so just move the
     224             :       // data into the DataBox directly. No conversion needed.
     225             :       db::mutate<gr::Tags::SpacetimeMetric<3, Frame::Inertial, DataVector>,
     226             :                  Tags::Pi<3, Frame::Inertial>, Tags::Phi<3, Frame::Inertial>>(
     227             :           make_not_null(&box),
     228             :           [&numeric_initial_data](
     229             :               const gsl::not_null<tnsr::aa<DataVector, 3>*> spacetime_metric,
     230             :               const gsl::not_null<tnsr::aa<DataVector, 3>*> pi,
     231             :               const gsl::not_null<tnsr::iaa<DataVector, 3>*> phi) {
     232             :             *spacetime_metric = std::move(
     233             :                 get<gr::Tags::SpacetimeMetric<3, Frame::Inertial, DataVector>>(
     234             :                     numeric_initial_data));
     235             :             *pi = std::move(
     236             :                 get<Tags::Pi<3, Frame::Inertial>>(numeric_initial_data));
     237             :             *phi = std::move(
     238             :                 get<Tags::Phi<3, Frame::Inertial>>(numeric_initial_data));
     239             :           });
     240             :     } else if (std::holds_alternative<detail::Adm>(
     241             :                    selected_initial_data_vars)) {
     242             :       // We have loaded ADM variables from the file. Convert to GH variables.
     243             :       const auto& spatial_metric =
     244             :           get<gr::Tags::SpatialMetric<3, Frame::Inertial, DataVector>>(
     245             :               numeric_initial_data);
     246             :       const auto& lapse =
     247             :           get<gr::Tags::Lapse<DataVector>>(numeric_initial_data);
     248             :       const auto& shift = get<gr::Tags::Shift<3, Frame::Inertial, DataVector>>(
     249             :           numeric_initial_data);
     250             :       const auto& extrinsic_curvature =
     251             :           get<gr::Tags::ExtrinsicCurvature<3, Frame::Inertial, DataVector>>(
     252             :               numeric_initial_data);
     253             : 
     254             :       // Take numerical derivatives
     255             :       const auto& mesh = db::get<domain::Tags::Mesh<Dim>>(box);
     256             :       const auto& inv_jacobian =
     257             :           db::get<domain::Tags::InverseJacobian<Dim, Frame::ElementLogical,
     258             :                                                 Frame::Inertial>>(box);
     259             :       const auto deriv_spatial_metric =
     260             :           partial_derivative(spatial_metric, mesh, inv_jacobian);
     261             :       const auto deriv_lapse = partial_derivative(lapse, mesh, inv_jacobian);
     262             :       const auto deriv_shift = partial_derivative(
     263             :           get<gr::Tags::Shift<3, Frame::Inertial, DataVector>>(
     264             :               numeric_initial_data),
     265             :           mesh, inv_jacobian);
     266             : 
     267             :       // Compute GH variables
     268             :       db::mutate<gr::Tags::SpacetimeMetric<3, Frame::Inertial, DataVector>,
     269             :                  Tags::Pi<3, Frame::Inertial>, Tags::Phi<3, Frame::Inertial>>(
     270             :           make_not_null(&box),
     271             :           [&spatial_metric, &deriv_spatial_metric, &lapse, &deriv_lapse, &shift,
     272             :            &deriv_shift, &extrinsic_curvature](
     273             :               const gsl::not_null<tnsr::aa<DataVector, 3>*> spacetime_metric,
     274             :               const gsl::not_null<tnsr::aa<DataVector, 3>*> pi,
     275             :               const gsl::not_null<tnsr::iaa<DataVector, 3>*> phi) {
     276             :             // Choose dt_lapse = 0 and dt_shift = 0 (for now)
     277             :             const auto dt_lapse =
     278             :                 make_with_value<Scalar<DataVector>>(lapse, 0.);
     279             :             const auto dt_shift =
     280             :                 make_with_value<tnsr::I<DataVector, 3>>(shift, 0.);
     281             :             const auto dt_spatial_metric =
     282             :                 gr::time_derivative_of_spatial_metric(
     283             :                     lapse, shift, deriv_shift, spatial_metric,
     284             :                     deriv_spatial_metric, extrinsic_curvature);
     285             :             gr::spacetime_metric(spacetime_metric, lapse, shift,
     286             :                                  spatial_metric);
     287             :             GeneralizedHarmonic::phi(phi, lapse, deriv_lapse, shift,
     288             :                                      deriv_shift, spatial_metric,
     289             :                                      deriv_spatial_metric);
     290             :             GeneralizedHarmonic::pi(pi, lapse, dt_lapse, shift, dt_shift,
     291             :                                     spatial_metric, dt_spatial_metric, *phi);
     292             :           });
     293             :     } else {
     294             :       ERROR(
     295             :           "These initial data variables are not implemented yet. Please add "
     296             :           "an implementation to "
     297             :           "GeneralizedHarmonic::Actions::SetNumericInitialData.");
     298             :     }
     299             :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     300             :   }
     301             : };
     302             : 
     303             : }  // namespace Actions
     304             : }  // namespace GeneralizedHarmonic

Generated by: LCOV version 1.14