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 : ¶llel_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, ¶llel_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
|