Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <string>
7 : #include <tuple>
8 :
9 : #include "DataStructures/DataBox/DataBox.hpp"
10 : #include "DataStructures/VariablesTag.hpp"
11 : #include "Evolution/Systems/Cce/Actions/ReceiveWorldtubeData.hpp"
12 : #include "Evolution/Systems/Cce/Components/WorldtubeBoundary.hpp"
13 : #include "Evolution/Systems/Cce/InterfaceManagers/GhInterfaceManager.hpp"
14 : #include "Evolution/Systems/Cce/OptionTags.hpp"
15 : #include "Evolution/Systems/Cce/ReceiveTags.hpp"
16 : #include "Evolution/Systems/Cce/Tags.hpp"
17 : #include "Evolution/Systems/Cce/WorldtubeDataManager.hpp"
18 : #include "IO/Observer/Actions/GetLockPointer.hpp"
19 : #include "IO/Observer/ObserverComponent.hpp"
20 : #include "Parallel/GlobalCache.hpp"
21 : #include "Parallel/Invoke.hpp"
22 : #include "Parallel/Local.hpp"
23 : #include "Parallel/Printf.hpp"
24 : #include "Time/SelfStart.hpp"
25 : #include "Time/TimeStepId.hpp"
26 : #include "Utilities/ErrorHandling/Error.hpp"
27 : #include "Utilities/Gsl.hpp"
28 : #include "Utilities/TMPL.hpp"
29 : #include "Utilities/TypeTraits.hpp"
30 :
31 1 : namespace Cce {
32 1 : namespace Actions {
33 :
34 : /*!
35 : * \ingroup ActionsGroup
36 : * \brief Obtains the CCE boundary data at the specified `time`, and reports it
37 : * to the `EvolutionComponent` via `Actions::ReceiveWorldtubeData`.
38 : *
39 : * \details See the template partial specializations of this class for details
40 : * on the different strategies for each component type.
41 : */
42 : template <typename BoundaryComponent, typename EvolutionComponent>
43 1 : struct BoundaryComputeAndSendToEvolution;
44 :
45 : /*!
46 : * \ingroup ActionsGroup
47 : * \brief Computes Bondi boundary data from GH evolution variables and sends the
48 : * result to the `EvolutionComponent` (template argument).
49 : *
50 : * \details After the computation, this action will call
51 : * `Cce::Actions::ReceiveWorldtubeData` on the `EvolutionComponent` with each of
52 : * the types from `typename Metavariables::cce_boundary_communication_tags` sent
53 : * as arguments
54 : *
55 : * \ref DataBoxGroup changes:
56 : * - Adds: nothing
57 : * - Removes: nothing
58 : * - Modifies:
59 : * - `Tags::Variables<typename
60 : * Metavariables::cce_boundary_communication_tags>` (every tensor)
61 : */
62 : template <typename BoundaryComponent, typename EvolutionComponent>
63 1 : struct SendToEvolution;
64 :
65 : /*!
66 : * \ingroup ActionsGroup
67 : * \brief Obtains the CCE boundary data at the specified `time`, and reports it
68 : * to the `EvolutionComponent` via `Actions::ReceiveWorldtubeData`.
69 : *
70 : * \details This uses the `WorldtubeDataManager` to perform all of the work of
71 : * managing the file buffer, interpolating to the desired time point, and
72 : * compute the Bondi quantities on the boundary. Once readied, it sends each
73 : * tensor from the the full `Variables<typename
74 : * Metavariables::cce_boundary_communication_tags>` back to the
75 : * `EvolutionComponent`
76 : *
77 : * Uses:
78 : * - DataBox:
79 : * - `Tags::H5WorldtubeBoundaryDataManager`
80 : *
81 : * \ref DataBoxGroup changes:
82 : * - Adds: nothing
83 : * - Removes: nothing
84 : * - Modifies:
85 : * - `Tags::Variables<typename
86 : * Metavariables::cce_boundary_communication_tags>` (every tensor)
87 : */
88 : template <typename Metavariables, typename EvolutionComponent>
89 1 : struct BoundaryComputeAndSendToEvolution<H5WorldtubeBoundary<Metavariables>,
90 : EvolutionComponent> {
91 : template <typename ParallelComponent, typename... DbTags, typename ArrayIndex>
92 0 : static void apply(db::DataBox<tmpl::list<DbTags...>>& box,
93 : Parallel::GlobalCache<Metavariables>& cache,
94 : const ArrayIndex& /*array_index*/, const TimeStepId& time) {
95 : auto hdf5_lock = Parallel::local_branch(
96 : Parallel::get_parallel_component<
97 : observers::ObserverWriter<Metavariables>>(cache))
98 : ->template local_synchronous_action<
99 : observers::Actions::GetLockPointer<
100 : observers::Tags::H5FileLock>>();
101 : bool successfully_populated = false;
102 : db::mutate<Tags::H5WorldtubeBoundaryDataManager,
103 : ::Tags::Variables<
104 : typename Metavariables::cce_boundary_communication_tags>>(
105 : [&successfully_populated, &time, &hdf5_lock](
106 : const gsl::not_null<std::unique_ptr<Cce::WorldtubeDataManager<
107 : Tags::characteristic_worldtube_boundary_tags<
108 : Tags::BoundaryValue>>>*>
109 : worldtube_data_manager,
110 : const gsl::not_null<Variables<
111 : typename Metavariables::cce_boundary_communication_tags>*>
112 : boundary_variables) {
113 : successfully_populated =
114 : (*worldtube_data_manager)
115 : ->populate_hypersurface_boundary_data(boundary_variables,
116 : time.substep_time(),
117 : hdf5_lock);
118 : },
119 : make_not_null(&box));
120 : if (not successfully_populated) {
121 : ERROR("Insufficient boundary data to proceed, exiting early at time " +
122 : std::to_string(time.substep_time()));
123 : }
124 : Parallel::receive_data<Cce::ReceiveTags::BoundaryData<
125 : typename Metavariables::cce_boundary_communication_tags>>(
126 : Parallel::get_parallel_component<EvolutionComponent>(cache), time,
127 : db::get<::Tags::Variables<
128 : typename Metavariables::cce_boundary_communication_tags>>(box),
129 : true);
130 : }
131 : };
132 :
133 : /*!
134 : * \ingroup ActionsGroup
135 : * \brief Obtains the Klein-Gordon CCE boundary data at the specified `time`,
136 : * and reports it to the `EvolutionComponent` via
137 : * `Actions::ReceiveWorldtubeData`.
138 : *
139 : * \details This uses the `WorldtubeDataManager` to perform all of the work of
140 : * managing the file buffer, interpolating to the desired time point, and
141 : * compute the Bondi and Klein-Gordon quantities on the boundary. Once readied,
142 : * it sends each tensor or scalar from the the full `Variables<typename
143 : * Metavariables::cce_boundary_communication_tags>` or `Variables<typename
144 : * Metavariables::klein_gordon_boundary_communication_tags>` back to the
145 : * `EvolutionComponent`
146 : *
147 : * Uses:
148 : * - DataBox:
149 : * - `Tags::H5WorldtubeBoundaryDataManager`
150 : * - `Tags::KleinGordonH5WorldtubeBoundaryDataManager`
151 : *
152 : * \ref DataBoxGroup changes:
153 : * - Adds: nothing
154 : * - Removes: nothing
155 : * - Modifies:
156 : * - `Tags::Variables<typename
157 : * Metavariables::cce_boundary_communication_tags>` (every tensor)
158 : * - `Tags::Variables<typename
159 : * Metavariables::klein_gordon_boundary_communication_tags>` (every scalar)
160 : */
161 : template <typename Metavariables, typename EvolutionComponent>
162 1 : struct BoundaryComputeAndSendToEvolution<
163 : KleinGordonH5WorldtubeBoundary<Metavariables>, EvolutionComponent> {
164 : template <typename ParallelComponent, typename... DbTags, typename ArrayIndex>
165 0 : static void apply(db::DataBox<tmpl::list<DbTags...>>& box,
166 : Parallel::GlobalCache<Metavariables>& cache,
167 : const ArrayIndex& /*array_index*/, const TimeStepId& time) {
168 : auto hdf5_lock = Parallel::local_branch(
169 : Parallel::get_parallel_component<
170 : observers::ObserverWriter<Metavariables>>(cache))
171 : ->template local_synchronous_action<
172 : observers::Actions::GetLockPointer<
173 : observers::Tags::H5FileLock>>();
174 : bool tensor_successfully_populated = false;
175 : bool klein_gordon_successfully_populated = false;
176 : db::mutate<
177 : Tags::H5WorldtubeBoundaryDataManager,
178 : Tags::KleinGordonH5WorldtubeBoundaryDataManager,
179 : ::Tags::Variables<
180 : typename Metavariables::cce_boundary_communication_tags>,
181 : ::Tags::Variables<
182 : typename Metavariables::klein_gordon_boundary_communication_tags>>(
183 : [&tensor_successfully_populated, &klein_gordon_successfully_populated,
184 : &time, &hdf5_lock](
185 : const gsl::not_null<std::unique_ptr<Cce::WorldtubeDataManager<
186 : Tags::characteristic_worldtube_boundary_tags<
187 : Tags::BoundaryValue>>>*>
188 : tensor_worldtube_data_manager,
189 : const gsl::not_null<std::unique_ptr<Cce::WorldtubeDataManager<
190 : Tags::klein_gordon_worldtube_boundary_tags>>*>
191 : klein_gordon_worldtube_data_manager,
192 : const gsl::not_null<Variables<
193 : typename Metavariables::cce_boundary_communication_tags>*>
194 : tensor_boundary_variables,
195 : const gsl::not_null<
196 : Variables<typename Metavariables::
197 : klein_gordon_boundary_communication_tags>*>
198 : klein_gordon_boundary_variables) {
199 : tensor_successfully_populated =
200 : (*tensor_worldtube_data_manager)
201 : ->populate_hypersurface_boundary_data(
202 : tensor_boundary_variables, time.substep_time(),
203 : hdf5_lock);
204 :
205 : klein_gordon_successfully_populated =
206 : (*klein_gordon_worldtube_data_manager)
207 : ->populate_hypersurface_boundary_data(
208 : klein_gordon_boundary_variables, time.substep_time(),
209 : hdf5_lock);
210 : },
211 : make_not_null(&box));
212 : if (not tensor_successfully_populated) {
213 : ERROR(
214 : "Insufficient tensor boundary data to proceed, exiting early at "
215 : "time " +
216 : std::to_string(time.substep_time()));
217 : }
218 :
219 : if (not klein_gordon_successfully_populated) {
220 : ERROR(
221 : "Insufficient scalar boundary data to proceed, exiting early at "
222 : "time " +
223 : std::to_string(time.substep_time()));
224 : }
225 : Parallel::receive_data<Cce::ReceiveTags::BoundaryData<
226 : typename Metavariables::cce_boundary_communication_tags>>(
227 : Parallel::get_parallel_component<EvolutionComponent>(cache), time,
228 : db::get<::Tags::Variables<
229 : typename Metavariables::cce_boundary_communication_tags>>(box),
230 : true);
231 :
232 : Parallel::receive_data<Cce::ReceiveTags::BoundaryData<
233 : typename Metavariables::klein_gordon_boundary_communication_tags>>(
234 : Parallel::get_parallel_component<EvolutionComponent>(cache), time,
235 : db::get<::Tags::Variables<
236 : typename Metavariables::klein_gordon_boundary_communication_tags>>(
237 : box),
238 : true);
239 : }
240 : };
241 :
242 : /*!
243 : * \ingroup ActionsGroup
244 : * \brief Calculates the analytic boundary data at the specified `time`, and
245 : * sends the resulting Bondi-Sachs boundary data to the `EvolutionComponent`
246 : *
247 : * \details This uses the `Cce::AnalyticBoundaryDataManager` to
248 : * perform all of the work of calculating the analytic boundary solution, which
249 : * in turn uses derived classes of `Cce::Solutions::WorldtubeData` to calculate
250 : * the metric data before it is transformed to Bondi-Sachs variables.
251 : *
252 : * \ref DataBoxGroup changes:
253 : * - Adds: nothing
254 : * - Removes: nothing
255 : * - Modifies:
256 : * - `Tags::AnalyticWordltubeBoundaryDataManager`
257 : */
258 : template <typename Metavariables, typename EvolutionComponent>
259 1 : struct BoundaryComputeAndSendToEvolution<
260 : AnalyticWorldtubeBoundary<Metavariables>, EvolutionComponent> {
261 : template <typename ParallelComponent, typename DbTagList, typename ArrayIndex>
262 0 : static void apply(db::DataBox<DbTagList>& box,
263 : Parallel::GlobalCache<Metavariables>& cache,
264 : const ArrayIndex& /*array_index*/, const TimeStepId& time) {
265 : bool successfully_populated = false;
266 : db::mutate<Tags::AnalyticBoundaryDataManager,
267 : ::Tags::Variables<
268 : typename Metavariables::cce_boundary_communication_tags>>(
269 : [&successfully_populated, &time](
270 : const gsl::not_null<Cce::AnalyticBoundaryDataManager*>
271 : worldtube_data_manager,
272 : const gsl::not_null<Variables<
273 : typename Metavariables::cce_boundary_communication_tags>*>
274 : boundary_variables) {
275 : successfully_populated =
276 : (*worldtube_data_manager)
277 : .populate_hypersurface_boundary_data(boundary_variables,
278 : time.substep_time());
279 : },
280 : make_not_null(&box));
281 :
282 : if (not successfully_populated) {
283 : ERROR("Insufficient boundary data to proceed, exiting early at time "
284 : << time.substep_time());
285 : }
286 : Parallel::receive_data<Cce::ReceiveTags::BoundaryData<
287 : typename Metavariables::cce_boundary_communication_tags>>(
288 : Parallel::get_parallel_component<EvolutionComponent>(cache), time,
289 : db::get<::Tags::Variables<
290 : typename Metavariables::cce_boundary_communication_tags>>(box),
291 : true);
292 : }
293 : };
294 :
295 : /*!
296 : * \ingroup ActionsGroup
297 : * \brief Submits a request for CCE boundary data at the specified `time` to the
298 : * `Cce::InterfaceManagers::GhInterfaceManager`, and sends the data to the
299 : * `EvolutionComponent` (template argument) if it is ready.
300 : *
301 : * \details This uses the `Cce::InterfaceManagers::GhInterfaceManager` to
302 : * perform all of the work of managing the buffer of data sent from the GH
303 : * system and interpolating if necessary and supported. This dispatches then to
304 : * `Cce::Actions::SendToEvolution<GhWorldtubeBoundary<Metavariables>,
305 : * EvolutionComponent>` if the boundary data is ready, otherwise
306 : * simply submits the request and waits for data to become available via
307 : * `Cce::Actions::ReceiveGhWorldtubeData`, which will call
308 : * `Cce::Actions::SendToEvolution<GhWorldtubeBoundary<Metavariables>,
309 : * EvolutionComponent>` as soon as the data becomes available.
310 : *
311 : * \ref DataBoxGroup changes:
312 : * - Adds: nothing
313 : * - Removes: nothing
314 : * - Modifies:
315 : * - `Tags::GhInterfaceManager`
316 : */
317 : template <typename Metavariables, typename EvolutionComponent>
318 1 : struct BoundaryComputeAndSendToEvolution<GhWorldtubeBoundary<Metavariables>,
319 : EvolutionComponent> {
320 : template <typename ParallelComponent, typename... DbTags, typename ArrayIndex>
321 0 : static void apply(db::DataBox<tmpl::list<DbTags...>>& box,
322 : Parallel::GlobalCache<Metavariables>& cache,
323 : const ArrayIndex& /*array_index*/, const TimeStepId& time) {
324 : auto retrieve_data_and_send_to_evolution =
325 : [&time,
326 : &cache](const gsl::not_null<InterfaceManagers::GhInterfaceManager*>
327 : interface_manager) {
328 : interface_manager->request_gh_data(time);
329 : const auto gh_data =
330 : interface_manager->retrieve_and_remove_first_ready_gh_data();
331 : if (static_cast<bool>(gh_data)) {
332 : Parallel::simple_action<Actions::SendToEvolution<
333 : GhWorldtubeBoundary<Metavariables>, EvolutionComponent>>(
334 : Parallel::get_parallel_component<
335 : GhWorldtubeBoundary<Metavariables>>(cache),
336 : get<0>(*gh_data), get<1>(*gh_data));
337 : }
338 : };
339 : if (SelfStart::is_self_starting(time)) {
340 : db::mutate<Tags::SelfStartGhInterfaceManager>(
341 : retrieve_data_and_send_to_evolution, make_not_null(&box));
342 : } else {
343 : db::mutate<Tags::GhInterfaceManager>(retrieve_data_and_send_to_evolution,
344 : make_not_null(&box));
345 : }
346 : }
347 : };
348 :
349 : /// \cond
350 : template <typename Metavariables, typename EvolutionComponent>
351 : struct SendToEvolution<GhWorldtubeBoundary<Metavariables>, EvolutionComponent> {
352 : template <typename ParallelComponent, typename... DbTags, typename ArrayIndex>
353 : static void apply(
354 : db::DataBox<tmpl::list<DbTags...>>& box,
355 : Parallel::GlobalCache<Metavariables>& cache,
356 : const ArrayIndex& array_index, const TimeStepId& time,
357 : const InterfaceManagers::GhInterfaceManager::gh_variables& gh_variables) {
358 : apply<ParallelComponent>(
359 : box, cache, array_index, time,
360 : get<gr::Tags::SpacetimeMetric<DataVector, 3>>(gh_variables),
361 : get<gh::Tags::Phi<DataVector, 3>>(gh_variables),
362 : get<gh::Tags::Pi<DataVector, 3>>(gh_variables));
363 : }
364 :
365 : template <typename ParallelComponent, typename... DbTags, typename ArrayIndex>
366 : static void apply(
367 : db::DataBox<tmpl::list<DbTags...>>& box,
368 : Parallel::GlobalCache<Metavariables>& cache,
369 : const ArrayIndex& /*array_index*/, const TimeStepId& time,
370 : const tnsr::aa<DataVector, 3, ::Frame::Inertial>& spacetime_metric,
371 : const tnsr::iaa<DataVector, 3, ::Frame::Inertial>& phi,
372 : const tnsr::aa<DataVector, 3, ::Frame::Inertial>& pi) {
373 : db::mutate<::Tags::Variables<
374 : typename Metavariables::cce_boundary_communication_tags>>(
375 : [&spacetime_metric, &phi, &pi](
376 : const gsl::not_null<Variables<
377 : typename Metavariables::cce_boundary_communication_tags>*>
378 : boundary_variables,
379 : const double extraction_radius, const double l_max) {
380 : create_bondi_boundary_data(boundary_variables, phi, pi,
381 : spacetime_metric, extraction_radius,
382 : l_max);
383 : },
384 : make_not_null(&box), db::get<InitializationTags::ExtractionRadius>(box),
385 : db::get<Tags::LMax>(box));
386 : Parallel::receive_data<Cce::ReceiveTags::BoundaryData<
387 : typename Metavariables::cce_boundary_communication_tags>>(
388 : Parallel::get_parallel_component<EvolutionComponent>(cache), time,
389 : db::get<::Tags::Variables<
390 : typename Metavariables::cce_boundary_communication_tags>>(box),
391 : true);
392 : }
393 : };
394 : /// \endcond
395 :
396 : } // namespace Actions
397 : } // namespace Cce
|