Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <cstddef>
8 : #include <optional>
9 : #include <pup.h>
10 : #include <string>
11 : #include <vector>
12 :
13 : #include "DataStructures/DataBox/DataBox.hpp"
14 : #include "DataStructures/DataBox/DataBoxTag.hpp"
15 : #include "DataStructures/DataBox/ValidateSelection.hpp"
16 : #include "DataStructures/DataVector.hpp"
17 : #include "DataStructures/Tensor/Tensor.hpp"
18 : #include "Domain/Amr/Flag.hpp"
19 : #include "Domain/Tags.hpp"
20 : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
21 : #include "Options/Context.hpp"
22 : #include "Options/ParseError.hpp"
23 : #include "Options/String.hpp"
24 : #include "ParallelAlgorithms/Amr/Criteria/Criterion.hpp"
25 : #include "Utilities/Algorithm.hpp"
26 : #include "Utilities/TMPL.hpp"
27 :
28 : /// \cond
29 : template <size_t>
30 : class ElementId;
31 : /// \endcond
32 :
33 : namespace amr::Criteria {
34 :
35 : namespace TruncationError_detail {
36 : /*!
37 : * \brief Apply the truncation error criterion to a single tensor component
38 : *
39 : * The `result` is the current decision in each dimension based on the previous
40 : * tensor components. This function will update the flags if necessary. It takes
41 : * the "max" of the current and new flags, where the "highest" flag is
42 : * `Flag::IncreaseResolution`, followed by `Flag::DoNothing`, and then
43 : * `Flag::DecreaseResolution`.
44 : */
45 : template <size_t Dim>
46 : void max_over_components(
47 : gsl::not_null<std::array<Flag, Dim>*> result,
48 : const gsl::not_null<std::array<DataVector, Dim>*> power_monitors_buffer,
49 : const DataVector& tensor_component, const Mesh<Dim>& mesh,
50 : std::optional<double> target_abs_truncation_error,
51 : std::optional<double> target_rel_truncation_error);
52 : } // namespace TruncationError_detail
53 :
54 : /*!
55 : * \brief Refine the grid towards the target truncation error
56 : *
57 : * - If any tensor component has a truncation error above the target value, the
58 : * element will be p-refined.
59 : * - If all tensor components still satisfy the target even with one mode
60 : * removed, the element will be p-coarsened.
61 : *
62 : * For details on how the truncation error is computed see
63 : * `PowerMonitors::truncation_error`.
64 : *
65 : * \tparam Dim Spatial dimension of the grid
66 : * \tparam TensorTags List of tags of the tensors to be monitored
67 : */
68 : template <size_t Dim, typename TensorTags>
69 1 : class TruncationError : public Criterion {
70 : public:
71 0 : struct VariablesToMonitor {
72 0 : using type = std::vector<std::string>;
73 0 : static constexpr Options::String help = {
74 : "The tensors to monitor the truncation error of."};
75 0 : static size_t lower_bound_on_size() { return 1; }
76 : };
77 0 : struct AbsoluteTargetTruncationError {
78 0 : static std::string name() { return "AbsoluteTarget"; }
79 0 : using type = Options::Auto<double, Options::AutoLabel::None>;
80 0 : static constexpr Options::String help = {
81 : "The absolute target truncation error. If any tensor component "
82 : "has a truncation error above this value, the element will be "
83 : "p-refined."};
84 : };
85 0 : struct RelativeTargetTruncationError {
86 0 : static std::string name() { return "RelativeTarget"; }
87 0 : using type = Options::Auto<double, Options::AutoLabel::None>;
88 0 : static constexpr Options::String help = {
89 : "The relative target truncation error. If any tensor component "
90 : "has a truncation error above this value, the element will be "
91 : "p-refined."};
92 : };
93 :
94 0 : using options = tmpl::list<VariablesToMonitor, AbsoluteTargetTruncationError,
95 : RelativeTargetTruncationError>;
96 :
97 0 : static constexpr Options::String help = {
98 : "Refine the grid towards the target truncation error"};
99 :
100 0 : TruncationError() = default;
101 :
102 0 : TruncationError(std::vector<std::string> vars_to_monitor,
103 : const std::optional<double> target_abs_truncation_error,
104 : const std::optional<double> target_rel_truncation_error,
105 : const Options::Context& context = {});
106 :
107 : /// \cond
108 : explicit TruncationError(CkMigrateMessage* msg);
109 : using PUP::able::register_constructor;
110 : WRAPPED_PUPable_decl_template(TruncationError); // NOLINT
111 : /// \endcond
112 :
113 0 : std::string observation_name() override { return "TruncationError"; }
114 :
115 0 : using compute_tags_for_observation_box = tmpl::list<>;
116 :
117 0 : using argument_tags = tmpl::list<::Tags::DataBox>;
118 :
119 : template <typename DbTagsList, typename Metavariables>
120 0 : std::array<Flag, Dim> operator()(const db::DataBox<DbTagsList>& box,
121 : Parallel::GlobalCache<Metavariables>& cache,
122 : const ElementId<Dim>& element_id) const;
123 :
124 0 : void pup(PUP::er& p) override;
125 :
126 : private:
127 0 : std::vector<std::string> vars_to_monitor_{};
128 0 : std::optional<double> target_abs_truncation_error_{};
129 0 : std::optional<double> target_rel_truncation_error_{};
130 : };
131 :
132 : // Out-of-line definitions
133 : /// \cond
134 :
135 : template <size_t Dim, typename TensorTags>
136 : TruncationError<Dim, TensorTags>::TruncationError(
137 : std::vector<std::string> vars_to_monitor,
138 : const std::optional<double> target_abs_truncation_error,
139 : const std::optional<double> target_rel_truncation_error,
140 : const Options::Context& context)
141 : : vars_to_monitor_(std::move(vars_to_monitor)),
142 : target_abs_truncation_error_(target_abs_truncation_error),
143 : target_rel_truncation_error_(target_rel_truncation_error) {
144 : db::validate_selection<TensorTags>(vars_to_monitor_, context);
145 : if (not target_abs_truncation_error.has_value() and
146 : not target_rel_truncation_error.has_value()) {
147 : PARSE_ERROR(context,
148 : "Must specify AbsoluteTarget, RelativeTarget, or both");
149 : }
150 : }
151 :
152 : template <size_t Dim, typename TensorTags>
153 : TruncationError<Dim, TensorTags>::TruncationError(CkMigrateMessage* msg)
154 : : Criterion(msg) {}
155 :
156 : template <size_t Dim, typename TensorTags>
157 : template <typename DbTagsList, typename Metavariables>
158 : std::array<Flag, Dim> TruncationError<Dim, TensorTags>::operator()(
159 : const db::DataBox<DbTagsList>& box,
160 : Parallel::GlobalCache<Metavariables>& /*cache*/,
161 : const ElementId<Dim>& /*element_id*/) const {
162 : auto result = make_array<Dim>(Flag::Undefined);
163 : const auto& mesh = db::get<domain::Tags::Mesh<Dim>>(box);
164 : std::array<DataVector, Dim> power_monitors_buffer{};
165 : // Check all tensors and all tensor components in turn
166 : tmpl::for_each<TensorTags>(
167 : [&result, &box, &mesh, &power_monitors_buffer, this](const auto tag_v) {
168 : // Stop if we have already decided to refine every dimension
169 : if (result == make_array<Dim>(Flag::IncreaseResolution)) {
170 : return;
171 : }
172 : using tag = tmpl::type_from<std::decay_t<decltype(tag_v)>>;
173 : const std::string tag_name = db::tag_name<tag>();
174 : // Skip if this tensor is not being monitored
175 : if (not alg::found(vars_to_monitor_, tag_name)) {
176 : return;
177 : }
178 : const auto& tensor = db::get<tag>(box);
179 : for (const DataVector& tensor_component : tensor) {
180 : TruncationError_detail::max_over_components(
181 : make_not_null(&result), make_not_null(&power_monitors_buffer),
182 : tensor_component, mesh, target_abs_truncation_error_,
183 : target_rel_truncation_error_);
184 : }
185 : });
186 : return result;
187 : }
188 :
189 : template <size_t Dim, typename TensorTags>
190 : void TruncationError<Dim, TensorTags>::pup(PUP::er& p) {
191 : p | vars_to_monitor_;
192 : p | target_abs_truncation_error_;
193 : p | target_rel_truncation_error_;
194 : }
195 :
196 : template <size_t Dim, typename TensorTags>
197 : PUP::able::PUP_ID TruncationError<Dim, TensorTags>::my_PUP_ID = 0; // NOLINT
198 : /// \endcond
199 :
200 : } // namespace amr::Criteria
|