12 #include "Informer/Tags.hpp"
13 #include "Informer/Verbosity.hpp"
15 #include "Parallel/Invoke.hpp"
17 #include "ParallelAlgorithms/NonlinearSolver/NewtonRaphson/LineSearch.hpp"
18 #include "ParallelAlgorithms/NonlinearSolver/NewtonRaphson/Tags/InboxTags.hpp"
19 #include "ParallelAlgorithms/NonlinearSolver/Observe.hpp"
21 #include "Utilities/EqualWithinRoundoff.hpp"
22 #include "Utilities/Functional.hpp"
26 template <
typename...>
31 namespace NonlinearSolver::newton_raphson::detail {
33 template <
typename FieldsTag,
typename OptionsGroup,
typename BroadcastTarget>
34 struct CheckResidualMagnitude {
35 using fields_tag = FieldsTag;
38 using residual_magnitude_square_tag =
40 using initial_residual_magnitude_tag =
42 using prev_residual_magnitude_square_tag =
45 template <
typename ParallelComponent,
typename DataBox,
46 typename Metavariables,
typename ArrayIndex,
typename... Args>
49 Args&&... args) noexcept {
50 if constexpr (db::tag_is_retrievable_v<residual_magnitude_square_tag,
52 apply_impl<ParallelComponent>(box,
cache, std::forward<Args>(args)...);
55 "The residual monitor is not yet initialized. This is a bug, so "
56 "please file an issue.");
61 template <
typename ParallelComponent,
typename DbTagsList,
62 typename Metavariables>
63 static void apply_impl(db::DataBox<DbTagsList>& box,
65 const size_t iteration_id,
66 const size_t globalization_iteration_id,
67 const double next_residual_magnitude_square,
68 const double step_length) noexcept {
69 const double residual_magnitude =
sqrt(next_residual_magnitude_square);
71 NonlinearSolver::observe_detail::contribute_to_reduction_observer<
72 OptionsGroup, ParallelComponent>(
73 iteration_id, globalization_iteration_id, residual_magnitude,
77 db::mutate<initial_residual_magnitude_tag>(
80 initial_residual_magnitude) noexcept {
81 *initial_residual_magnitude =
sqrt(residual_magnitude);
89 const double sufficient_decrease =
90 get<NonlinearSolver::Tags::SufficientDecrease<OptionsGroup>>(box);
91 const double residual_magnitude_square =
92 get<residual_magnitude_square_tag>(box);
93 const double initial_residual_magnitude =
94 get<initial_residual_magnitude_tag>(box);
95 const double abs_tolerance =
96 get<Convergence::Tags::Criteria<OptionsGroup>>(box).absolute_residual;
97 const double rel_tolerance =
98 get<Convergence::Tags::Criteria<OptionsGroup>>(box).relative_residual;
101 const double residual_magnitude_square_slope =
102 -2. * residual_magnitude_square;
105 if (residual_magnitude > abs_tolerance and
106 residual_magnitude / initial_residual_magnitude > rel_tolerance and
107 next_residual_magnitude_square >
108 residual_magnitude_square + sufficient_decrease * step_length *
109 residual_magnitude_square_slope) {
112 if (globalization_iteration_id <
117 globalization_iteration_id, step_length,
119 residual_magnitude_square, residual_magnitude_square_slope,
120 next_residual_magnitude_square,
121 get<prev_residual_magnitude_square_tag>(box)),
122 0.1 * step_length, 0.5 * step_length);
123 db::mutate<NonlinearSolver::Tags::StepLength<OptionsGroup>,
124 prev_residual_magnitude_square_tag>(
126 [step_length, next_residual_magnitude_square](
129 prev_residual_magnitude_square) noexcept {
130 *prev_step_length = step_length;
131 *prev_residual_magnitude_square =
132 next_residual_magnitude_square;
136 ::Verbosity::Verbose)) {
138 "%s(%zu): Step with length %g didn't sufficiently decrease the "
139 "residual (possible overshoot). Residual: %e. Next step "
141 Options::name<OptionsGroup>(), iteration_id, step_length,
142 residual_magnitude, next_step_length);
144 ::Verbosity::Debug)) {
146 residual_magnitude_square_slope);
151 Parallel::receive_data<Tags::GlobalizationResult<OptionsGroup>>(
152 Parallel::get_parallel_component<BroadcastTarget>(
cache),
158 ::Verbosity::Quiet)) {
160 "%s(%zu): WARNING: Failed to sufficiently decrease the residual "
161 "in %zu globalization steps. This is usually indicative of an "
162 "ill-posed problem, for example when the linearization of the "
163 "nonlinear operator is not computed correctly.",
164 Options::name<OptionsGroup>(), iteration_id,
165 globalization_iteration_id);
170 db::mutate<residual_magnitude_square_tag>(
173 local_residual_magnitude_square) noexcept {
174 *local_residual_magnitude_square = next_residual_magnitude_square;
182 get<Convergence::Tags::Criteria<OptionsGroup>>(box), iteration_id,
183 residual_magnitude, get<initial_residual_magnitude_tag>(box)};
187 ::Verbosity::Quiet)) {
190 Options::name<OptionsGroup>(), residual_magnitude);
193 "%s(%zu) iteration complete (%zu globalization steps, step length "
194 "%g). Remaining residual: %e\n",
195 Options::name<OptionsGroup>(), iteration_id,
196 globalization_iteration_id, step_length, residual_magnitude);
200 box) >= ::Verbosity::Quiet)) {
203 Options::name<OptionsGroup>(), has_converged);
206 Options::name<OptionsGroup>(), iteration_id,
211 Parallel::receive_data<Tags::GlobalizationResult<OptionsGroup>>(
212 Parallel::get_parallel_component<BroadcastTarget>(
cache), iteration_id,
215 std::move(has_converged)));