Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <optional> 7 : #include <tuple> 8 : 9 : #include "DataStructures/DataBox/DataBox.hpp" 10 : #include "DataStructures/DataBox/ObservationBox.hpp" 11 : #include "DataStructures/DataBox/TagName.hpp" 12 : #include "Parallel/AlgorithmExecution.hpp" 13 : #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp" 14 : #include "ParallelAlgorithms/EventsAndTriggers/Tags.hpp" 15 : #include "Utilities/CloneUniquePtrs.hpp" 16 : #include "Utilities/ErrorHandling/FloatingPointExceptions.hpp" 17 : #include "Utilities/Gsl.hpp" 18 : #include "Utilities/TMPL.hpp" 19 : #include "Utilities/TaggedTuple.hpp" 20 : 21 : /// \cond 22 : namespace Parallel { 23 : template <typename Metavariables> 24 : class GlobalCache; 25 : } // namespace Parallel 26 : /// \endcond 27 : 28 : namespace Actions { 29 : /*! 30 : * \brief Invokes all events specified in `Tags::EventsRunAtCleanup`. 31 : * 32 : * Before running the events, floating point exceptions are disabled. This is 33 : * to allow manipulating data even if there are `NaN` or other problematic 34 : * values. We ultimately just want to be able to see the state of the 35 : * simulation at failure. 36 : * 37 : * This action is intended to be executed in the 38 : * `Parallel::Phase::PostFailureCleanup` phase. 39 : * 40 : * \note The simulation will almost certainly fail with different 41 : * elements at different times. 42 : */ 43 : template <typename ObservationId> 44 1 : struct RunEventsOnFailure { 45 : private: 46 : template <typename Event> 47 0 : struct get_tags { 48 0 : using type = typename Event::compute_tags_for_observation_box; 49 : }; 50 : 51 : public: 52 0 : using const_global_cache_tags = 53 : tmpl::list<::Tags::EventsRunAtCleanup, 54 : ::Tags::EventsRunAtCleanupObservationValue>; 55 : 56 : template <typename DbTags, typename... InboxTags, typename Metavariables, 57 : typename ArrayIndex, typename ActionList, 58 : typename ParallelComponent> 59 0 : static Parallel::iterable_action_return_t apply( 60 : db::DataBox<DbTags>& box, tuples::TaggedTuple<InboxTags...>& /*inboxes*/, 61 : Parallel::GlobalCache<Metavariables>& cache, 62 : const ArrayIndex& array_index, const ActionList /*meta*/, 63 : const ParallelComponent* const component) { 64 : // We explicitly disable FPEs because we are dumping during a failure and 65 : // so can't rely on the data being safe. 66 : disable_floating_point_exceptions(); 67 : 68 : const Event::ObservationValue observation_value{ 69 : db::tag_name<ObservationId>(), 70 : db::get<Tags::EventsRunAtCleanupObservationValue>(box)}; 71 : 72 : using compute_tags = tmpl::remove_duplicates<tmpl::filter< 73 : tmpl::flatten<tmpl::transform< 74 : tmpl::at<typename Metavariables::factory_creation::factory_classes, 75 : Event>, 76 : get_tags<tmpl::_1>>>, 77 : db::is_compute_tag<tmpl::_1>>>; 78 : std::optional observation_box{ 79 : make_observation_box<compute_tags>(make_not_null(&box))}; 80 : 81 : for (const auto& event : db::get<::Tags::EventsRunAtCleanup>(box)) { 82 : event->run(make_not_null(&observation_box.value()), cache, array_index, 83 : component, observation_value); 84 : } 85 : 86 : // Do not re-enable FPEs because other parts of the pipeline might rely on 87 : // them being disabled. We generally have them disabled during cleanup. 88 : return {Parallel::AlgorithmExecution::Continue, std::nullopt}; 89 : } 90 : }; 91 : } // namespace Actions