14 #include "DataStructures/DataBox/PrefixHelpers.hpp"
15 #include "IO/Observer/Actions/RegisterWithObservers.hpp"
16 #include "IO/Observer/ArrayComponentId.hpp"
17 #include "IO/Observer/Helpers.hpp"
18 #include "IO/Observer/ObservationId.hpp"
19 #include "IO/Observer/ObserverComponent.hpp"
20 #include "IO/Observer/ReductionActions.hpp"
21 #include "IO/Observer/TypeOfObservation.hpp"
22 #include "Informer/Tags.hpp"
23 #include "Informer/Verbosity.hpp"
24 #include "NumericalAlgorithms/Convergence/HasConverged.hpp"
25 #include "NumericalAlgorithms/Convergence/Tags.hpp"
26 #include "NumericalAlgorithms/LinearSolver/Gmres.hpp"
29 #include "Parallel/Invoke.hpp"
31 #include "Parallel/Reduction.hpp"
32 #include "ParallelAlgorithms/Initialization/MutateAssign.hpp"
34 #include "Utilities/Functional.hpp"
35 #include "Utilities/GetOutput.hpp"
43 template <
typename...>
47 template <
typename FieldsTag,
typename OptionsGroup,
typename SourceTag,
57 using reduction_data = Parallel::ReductionData<
63 template <
typename OptionsGroup,
typename ParallelComponent,
64 typename Metavariables,
typename ArrayIndex>
65 void contribute_to_residual_observation(
66 const size_t iteration_id,
const double residual_magnitude_square,
68 const ArrayIndex& array_index) noexcept {
69 auto& local_observer =
70 *Parallel::get_parallel_component<observers::Observer<Metavariables>>(
73 Parallel::simple_action<observers::Actions::ContributeReductionData>(
76 pretty_type::get_name<OptionsGroup>()),
80 std::string{
"/" + Options::name<OptionsGroup>() +
"Residuals"},
82 reduction_data{iteration_id, residual_magnitude_square});
84 ::Verbosity::Verbose)) {
85 if (iteration_id == 0) {
87 "Linear solver '" + Options::name<OptionsGroup>() +
88 "' initialized on element %s. Remaining local residual: %e\n",
89 get_output(array_index), sqrt(residual_magnitude_square));
92 Options::name<OptionsGroup>() +
93 "' iteration %zu done on element %s. Remaining "
94 "local residual: %e\n",
96 sqrt(residual_magnitude_square));
101 template <
typename FieldsTag,
typename OptionsGroup,
typename SourceTag>
104 using fields_tag = FieldsTag;
105 using operator_applied_to_fields_tag =
107 using source_tag = SourceTag;
114 using const_global_cache_tags =
115 tmpl::list<Convergence::Tags::Iterations<OptionsGroup>>;
117 using simple_tags = tmpl::list<Convergence::Tags::IterationId<OptionsGroup>,
119 operator_applied_to_fields_tag>;
121 tmpl::list<LinearSolver::Tags::ResidualCompute<fields_tag, source_tag>>;
123 template <
typename DbTagsList,
typename... InboxTags,
typename Metavariables,
124 typename ArrayIndex,
typename ActionList,
125 typename ParallelComponent>
126 static auto apply(db::DataBox<DbTagsList>& box,
131 const ParallelComponent*
const ) noexcept {
136 tmpl::list<Convergence::Tags::IterationId<OptionsGroup>>>(
138 return std::make_tuple(std::move(box));
142 template <
typename OptionsGroup>
144 template <
typename ParallelComponent,
typename DbTagsList,
147 register_info(
const db::DataBox<DbTagsList>& ,
148 const ArrayIndex& ) noexcept {
154 template <
typename FieldsTag,
typename OptionsGroup,
typename SourceTag>
158 template <
typename FieldsTag,
typename OptionsGroup,
typename SourceTag,
162 using fields_tag = FieldsTag;
167 using const_global_cache_tags =
168 tmpl::list<logging::Tags::Verbosity<OptionsGroup>>;
170 template <
typename DbTagsList,
typename... InboxTags,
typename Metavariables,
171 typename ArrayIndex,
typename ActionList,
172 typename ParallelComponent>
174 db::DataBox<DbTagsList>& box,
177 const ArrayIndex& array_index,
const ActionList ,
178 const ParallelComponent*
const ) noexcept {
179 constexpr
size_t iteration_id = 0;
181 db::mutate<Convergence::Tags::IterationId<OptionsGroup>,
186 const size_t num_iterations) noexcept {
187 *local_iteration_id = iteration_id;
191 get<Convergence::Tags::Iterations<OptionsGroup>>(box));
194 const auto& residual = get<residual_tag>(box);
195 const double residual_magnitude_square =
inner_product(residual, residual);
196 contribute_to_residual_observation<OptionsGroup, ParallelComponent>(
197 iteration_id, residual_magnitude_square, cache, array_index);
200 constexpr
size_t step_end_index =
201 tmpl::index_of<ActionList,
CompleteStep<FieldsTag, OptionsGroup,
202 SourceTag, Label>>::value;
203 constexpr
size_t this_action_index =
204 tmpl::index_of<ActionList, PrepareSolve>::value;
205 return {std::move(box),
false,
206 get<Convergence::Tags::HasConverged<OptionsGroup>>(box)
207 ? (step_end_index + 1)
208 : (this_action_index + 1)};
212 template <
typename FieldsTag,
typename OptionsGroup,
typename SourceTag,
216 using fields_tag = FieldsTag;
221 using const_global_cache_tags =
222 tmpl::list<logging::Tags::Verbosity<OptionsGroup>>;
224 template <
typename DbTagsList,
typename... InboxTags,
typename Metavariables,
225 typename ArrayIndex,
typename ActionList,
226 typename ParallelComponent>
228 db::DataBox<DbTagsList>& box,
231 const ArrayIndex& array_index,
const ActionList ,
232 const ParallelComponent*
const ) noexcept {
234 db::mutate<Convergence::Tags::IterationId<OptionsGroup>,
239 const size_t num_iterations) noexcept {
244 get<Convergence::Tags::Iterations<OptionsGroup>>(box));
247 const size_t completed_iterations =
248 get<Convergence::Tags::IterationId<OptionsGroup>>(box);
249 const auto& residual = get<residual_tag>(box);
250 const double residual_magnitude_square =
inner_product(residual, residual);
251 contribute_to_residual_observation<OptionsGroup, ParallelComponent>(
252 completed_iterations, residual_magnitude_square, cache, array_index);
255 constexpr
size_t step_begin_index =
256 tmpl::index_of<ActionList,
PrepareSolve<FieldsTag, OptionsGroup,
257 SourceTag, Label>>::value +
259 constexpr
size_t this_action_index =
260 tmpl::index_of<ActionList, CompleteStep>::value;
261 return {std::move(box),
false,
262 get<Convergence::Tags::HasConverged<OptionsGroup>>(box)
263 ? (this_action_index + 1)