11 #include "DataStructures/DataBox/PrefixHelpers.hpp"
12 #include "Informer/Tags.hpp"
13 #include "Informer/Verbosity.hpp"
14 #include "NumericalAlgorithms/Convergence/HasConverged.hpp"
15 #include "NumericalAlgorithms/Convergence/Tags.hpp"
18 #include "Parallel/Invoke.hpp"
20 #include "ParallelAlgorithms/LinearSolver/ConjugateGradient/Tags/InboxTags.hpp"
21 #include "ParallelAlgorithms/LinearSolver/Observe.hpp"
23 #include "Utilities/EqualWithinRoundoff.hpp"
24 #include "Utilities/Functional.hpp"
30 template <
typename...>
35 namespace LinearSolver::cg::detail {
37 template <
typename FieldsTag,
typename OptionsGroup,
typename BroadcastTarget>
38 struct InitializeResidual {
40 using fields_tag = FieldsTag;
43 using initial_residual_magnitude_tag =
48 template <
typename ParallelComponent,
typename DbTagsList,
49 typename Metavariables,
typename ArrayIndex,
50 typename DataBox = db::DataBox<DbTagsList>,
53 static void apply(db::DataBox<DbTagsList>& box,
56 const double residual_square) noexcept {
57 constexpr
size_t iteration_id = 0;
58 const double residual_magnitude =
sqrt(residual_square);
60 db::mutate<residual_square_tag, initial_residual_magnitude_tag>(
62 [residual_square, residual_magnitude](
65 *local_residual_square = residual_square;
66 *initial_residual_magnitude = residual_magnitude;
69 LinearSolver::observe_detail::contribute_to_reduction_observer<
70 OptionsGroup, ParallelComponent>(iteration_id, residual_magnitude,
75 get<Convergence::Tags::Criteria<OptionsGroup>>(box), iteration_id,
76 residual_magnitude, residual_magnitude};
80 ::Verbosity::Quiet)) {
82 Options::name<OptionsGroup>(), residual_magnitude);
85 cache) >= ::Verbosity::Quiet)) {
87 "%s has converged without any iterations: %s\n",
88 Options::name<OptionsGroup>(), has_converged);
91 Parallel::receive_data<Tags::InitialHasConverged<OptionsGroup>>(
92 Parallel::get_parallel_component<BroadcastTarget>(
cache), iteration_id,
94 std::move(has_converged));
98 template <
typename FieldsTag,
typename OptionsGroup,
typename BroadcastTarget>
101 using fields_tag = FieldsTag;
106 template <
typename ParallelComponent,
typename DbTagsList,
107 typename Metavariables,
typename ArrayIndex,
108 typename DataBox = db::DataBox<DbTagsList>,
111 static void apply(db::DataBox<DbTagsList>& box,
114 const size_t iteration_id,
115 const double conj_grad_inner_product) noexcept {
116 Parallel::receive_data<Tags::Alpha<OptionsGroup>>(
117 Parallel::get_parallel_component<BroadcastTarget>(
cache), iteration_id,
118 get<residual_square_tag>(box) / conj_grad_inner_product);
122 template <
typename FieldsTag,
typename OptionsGroup,
typename BroadcastTarget>
123 struct UpdateResidual {
125 using fields_tag = FieldsTag;
128 using initial_residual_magnitude_tag =
133 template <
typename ParallelComponent,
typename DbTagsList,
134 typename Metavariables,
typename ArrayIndex,
135 typename DataBox = db::DataBox<DbTagsList>,
138 static void apply(db::DataBox<DbTagsList>& box,
141 const size_t iteration_id,
142 const double residual_square) noexcept {
144 const double res_ratio = residual_square / get<residual_square_tag>(box);
146 db::mutate<residual_square_tag>(
150 *local_residual_square = residual_square;
157 const size_t completed_iterations = iteration_id + 1;
158 const double residual_magnitude =
sqrt(residual_square);
159 LinearSolver::observe_detail::contribute_to_reduction_observer<
160 OptionsGroup, ParallelComponent>(completed_iterations,
161 residual_magnitude,
cache);
165 get<Convergence::Tags::Criteria<OptionsGroup>>(box),
166 completed_iterations, residual_magnitude,
167 get<initial_residual_magnitude_tag>(box)};
171 ::Verbosity::Quiet)) {
173 "%s(%zu) iteration complete. Remaining residual: %e\n",
174 Options::name<OptionsGroup>(), completed_iterations,
178 cache) >= ::Verbosity::Quiet)) {
180 "%s has converged in %zu iterations: %s\n",
181 Options::name<OptionsGroup>(), completed_iterations, has_converged);
184 Parallel::receive_data<Tags::ResidualRatioAndHasConverged<OptionsGroup>>(
185 Parallel::get_parallel_component<BroadcastTarget>(
cache), iteration_id,
187 std::make_tuple(res_ratio, std::move(has_converged)));