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 <optional> 8 : #include <tuple> 9 : #include <utility> 10 : 11 : #include "DataStructures/DataBox/DataBox.hpp" 12 : #include "DataStructures/DataBox/PrefixHelpers.hpp" 13 : #include "DataStructures/DataBox/Prefixes.hpp" 14 : #include "DataStructures/Tensor/Tensor.hpp" 15 : #include "DataStructures/Variables.hpp" 16 : #include "Domain/Structure/ElementId.hpp" 17 : #include "Domain/Tags.hpp" 18 : #include "Parallel/AlgorithmExecution.hpp" 19 : #include "Parallel/GlobalCache.hpp" 20 : #include "Parallel/Tags/Metavariables.hpp" 21 : #include "ParallelAlgorithms/Amr/Protocols/Projector.hpp" 22 : #include "ParallelAlgorithms/Initialization/MutateAssign.hpp" 23 : #include "PointwiseFunctions/AnalyticSolutions/Tags.hpp" 24 : #include "Utilities/CallWithDynamicType.hpp" 25 : #include "Utilities/TMPL.hpp" 26 : #include "Utilities/TaggedTuple.hpp" 27 : 28 : /// \cond 29 : namespace Frame { 30 : struct Inertial; 31 : } // namespace Frame 32 : /// \endcond 33 : 34 0 : namespace elliptic::Actions { 35 : 36 : /// @{ 37 : /*! 38 : * \brief Place the analytic solution of the system fields in the DataBox. 39 : * 40 : * The `::Tags::AnalyticSolutionsBase` tag retrieved from the DataBox will hold 41 : * a `std::optional`. The analytic solution is only evaluated and stored in the 42 : * DataBox if the `BackgroundTag` holds a type that inherits from the 43 : * `AnalyticSolutionType`. 44 : * 45 : * Uses: 46 : * - DataBox: 47 : * - `AnalyticSolutionTag` or `BackgroundTag` 48 : * - `Tags::Coordinates<Dim, Frame::Inertial>` 49 : * 50 : * DataBox: 51 : * - Adds: 52 : * - `::Tags::AnalyticSolutionsBase` 53 : */ 54 : template <size_t Dim, typename BackgroundTag, typename AnalyticSolutionFields, 55 : typename AnalyticSolutionType> 56 1 : struct InitializeOptionalAnalyticSolution 57 : : tt::ConformsTo<::amr::protocols::Projector> { 58 : private: 59 0 : using analytic_fields_tag = ::Tags::AnalyticSolutions<AnalyticSolutionFields>; 60 : 61 : public: // Iterable action 62 0 : using simple_tags = tmpl::list<analytic_fields_tag>; 63 0 : using compute_tags = tmpl::list<>; 64 0 : using const_global_cache_tags = tmpl::list<BackgroundTag>; 65 : 66 : template <typename DbTagsList, typename... InboxTags, typename Metavariables, 67 : typename ActionList, typename ParallelComponent> 68 0 : static Parallel::iterable_action_return_t apply( 69 : db::DataBox<DbTagsList>& box, 70 : const tuples::TaggedTuple<InboxTags...>& /*inboxes*/, 71 : const Parallel::GlobalCache<Metavariables>& /*cache*/, 72 : const ElementId<Dim>& /*array_index*/, const ActionList /*meta*/, 73 : const ParallelComponent* const /*meta*/) { 74 : db::mutate_apply<InitializeOptionalAnalyticSolution>(make_not_null(&box)); 75 : return {Parallel::AlgorithmExecution::Continue, std::nullopt}; 76 : } 77 : 78 : public: // DataBox mutator, amr::protocols::Projector 79 0 : using return_tags = tmpl::list<analytic_fields_tag>; 80 0 : using argument_tags = 81 : tmpl::list<domain::Tags::Mesh<Dim>, 82 : domain::Tags::Coordinates<Dim, Frame::Inertial>, BackgroundTag, 83 : Parallel::Tags::Metavariables>; 84 : 85 : template <typename Background, typename Metavariables, typename... AmrData> 86 0 : static void apply(const gsl::not_null<typename analytic_fields_tag::type*> 87 : analytic_solution_fields, 88 : const Mesh<Dim>& mesh, 89 : const tnsr::I<DataVector, Dim> inertial_coords, 90 : const Background& background, const Metavariables& /*meta*/, 91 : const AmrData&... amr_data) { 92 : if constexpr (sizeof...(AmrData) == 1) { 93 : if constexpr (std::is_same_v<AmrData..., 94 : std::pair<Mesh<Dim>, Element<Dim>>>) { 95 : if (((mesh == amr_data.first) and ...)) { 96 : // This element hasn't changed during AMR. Nothing to do. 97 : return; 98 : } 99 : } 100 : } 101 : 102 : const auto analytic_solution = 103 : dynamic_cast<const AnalyticSolutionType*>(&background); 104 : if (analytic_solution != nullptr) { 105 : using factory_classes = typename std::decay_t< 106 : Metavariables>::factory_creation::factory_classes; 107 : *analytic_solution_fields = call_with_dynamic_type< 108 : Variables<AnalyticSolutionFields>, 109 : tmpl::at<factory_classes, AnalyticSolutionType>>( 110 : analytic_solution, [&inertial_coords](const auto* const derived) { 111 : return variables_from_tagged_tuple( 112 : derived->variables(inertial_coords, AnalyticSolutionFields{})); 113 : }); 114 : } else { 115 : *analytic_solution_fields = std::nullopt; 116 : } 117 : } 118 : }; 119 : /// @} 120 : } // namespace elliptic::Actions