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