Tags.hpp
Go to the documentation of this file.
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 /// \file
5 /// Defines DataBox tags for the linear solver
6 
7 #pragma once
8 
9 #include <cstddef>
10 #include <string>
11 
12 #include "DataStructures/DataBox/PrefixHelpers.hpp"
13 #include "DataStructures/DataBox/Tag.hpp"
14 #include "Options/Options.hpp"
15 #include "Utilities/Gsl.hpp"
16 
17 /// Functionality for solving nonlinear systems of equations
18 namespace NonlinearSolver {
19 
20 /// Options related to nonlinear solvers
21 namespace OptionTags {
22 
23 /*!
24  * \brief Sufficient decrease parameter of the line search globalization
25  *
26  * The sufficient decrease parameter is the acceptable decrease of the residual
27  * magnitude in each step of the nonlinear solver. It is measured as a fraction
28  * of the predicted decrease in residual magnitude if the problem was linear.
29  * For example, a sufficient decrease parameter of 1 means that a nonlinear
30  * solver step is expected to decrease the residual exactly as expected for a
31  * linear problem, i.e. immediately to zero. A sufficient decrease parameter of
32  * 0.5 means that decreasing the residual by half of that amount in each
33  * nonlinear solver step is acceptable.
34  *
35  * Nonlinear solver steps that fail the sufficient decrease condition (also
36  * known as _Armijo condition_) undergo a globalization procedure such as a line
37  * search.
38  *
39  * A typical value for the sufficient decrease parameter is \f$10^{-4}\f$. Set
40  * to values closer to unity when the nonlinear solver overshoots, e.g. when the
41  * initial guess is particularly bad. Larger values mean the nonlinear solver is
42  * stricter with accepting steps, preferring to apply the globalization
43  * strategy.
44  */
45 template <typename OptionsGroup>
47  using type = double;
48  static constexpr Options::String help = {
49  "Fraction of decrease predicted by linearization"};
50  static type lower_bound() noexcept { return 0.; }
51  static type upper_bound() noexcept { return 1.; }
52  static type suggested_value() noexcept { return 1.e-4; }
53  using group = OptionsGroup;
54 };
55 
56 /*!
57  * \brief Nonlinear solver steps are damped by this factor
58  *
59  * Instead of attempting to take full-length steps when correcting the solution
60  * in each nonlinear solver step (see `NonlinearSolver::Tags::Correction`),
61  * reduce the step length by this factor. This damping occurs before any
62  * globalization steps that may further reduce the step length.
63  */
64 template <typename OptionsGroup>
65 struct DampingFactor {
66  using type = double;
67  static constexpr Options::String help = {
68  "Multiply corrections by this factor"};
69  static type lower_bound() noexcept { return 0.; }
70  static type upper_bound() noexcept { return 1.; }
71  static type suggested_value() noexcept { return 1.; }
72  using group = OptionsGroup;
73 };
74 
75 /*!
76  * \brief The maximum number of allowed globalization steps
77  *
78  * Nonlinear solves of well-posed problems should never hit this limit because
79  * the step size shrinks and eventually triggers the sufficient-decrease
80  * condition (see `NonlinearSolver::OptionTags::SufficientDecrease`). So the
81  * suggested value just provides a safety-net to prevent the globalization
82  * from running forever when the problem is ill-posed.
83  */
84 template <typename OptionsGroup>
86  using type = size_t;
87  static constexpr Options::String help = {
88  "Maximum number of globalization steps"};
89  static type suggested_value() noexcept { return 40; }
90  using group = OptionsGroup;
91 };
92 
93 } // namespace OptionTags
94 
95 namespace Tags {
96 
97 /*!
98  * \brief The correction \f$\delta x\f$ to improve a solution \f$x_0\f$
99  *
100  * A linear problem \f$Ax=b\f$ can be equivalently formulated as the problem
101  * \f$A\delta x=b-A x_0\f$ for the correction \f$\delta x\f$ to an initial guess
102  * \f$x_0\f$. More importantly, we can use a correction scheme to solve a
103  * nonlinear problem \f$A_\mathrm{nonlinear}(x)=b\f$ by repeatedly solving a
104  * linearization of it. For instance, a Newton-Raphson scheme iteratively
105  * refines an initial guess \f$x_0\f$ by repeatedly solving the linearized
106  * problem
107  *
108  * \f{equation}
109  * \frac{\delta A_\mathrm{nonlinear}}{\delta x}(x_k)\delta x_k =
110  * b-A_\mathrm{nonlinear}(x_k)
111  * \f}
112  *
113  * for the correction \f$\delta x_k\f$ and then updating the solution as
114  * \f$x_{k+1}=x_k + \delta x_k\f$.
115  */
116 template <typename Tag>
118  using type = typename Tag::type;
119  using tag = Tag;
120 };
121 
122 /*!
123  * \brief The nonlinear operator \f$A_\mathrm{nonlinear}\f$ applied to the data
124  * in `Tag`
125  */
126 template <typename Tag>
128  static std::string name() noexcept {
129  // Add "Nonlinear" prefix to abbreviate the namespace for uniqueness
130  return "NonlinearOperatorAppliedTo(" + db::tag_name<Tag>() + ")";
131  }
132  using type = typename Tag::type;
133  using tag = Tag;
134 };
135 
136 /*!
137  * \brief The nonlinear residual
138  * \f$r_\mathrm{nonlinear} = b - A_\mathrm{nonlinear}(\delta x)\f$
139  */
140 template <typename Tag>
142  static std::string name() noexcept {
143  // Add "Nonlinear" prefix to abbreviate the namespace for uniqueness
144  return "NonlinearResidual(" + db::tag_name<Tag>() + ")";
145  }
146  using type = typename Tag::type;
147  using tag = Tag;
148 };
149 
150 /// Compute the residual \f$r=b - Ax\f$ from the `SourceTag` \f$b\f$ and the
151 /// `db::add_tag_prefix<NonlinearSolver::Tags::OperatorAppliedTo, FieldsTag>`
152 /// \f$Ax\f$.
153 template <typename FieldsTag, typename SourceTag>
154 struct ResidualCompute : db::add_tag_prefix<Residual, FieldsTag>,
157  using argument_tags =
158  tmpl::list<SourceTag, db::add_tag_prefix<OperatorAppliedTo, FieldsTag>>;
159  using return_type = typename base::type;
160  static void function(
161  const gsl::not_null<return_type*> residual,
162  const typename SourceTag::type& source,
164  operator_applied_to_fields) noexcept {
165  *residual = source - operator_applied_to_fields;
166  }
167 };
168 
169 /*!
170  * \brief The length of nonlinear solver steps
171  *
172  * Instead of taking full-length nonlinear solver steps when correcting the
173  * solution as detailed in `NonlinearSolver::Tags::Correction`, the correction
174  * is multiplied by this step length.
175  *
176  * The `NonlinearSolver::Tags::DampingFactor` multiplies the initial length of
177  * each step such that the nonlinear solver never takes full-length steps if the
178  * damping factor is below one. The step length can be further reduced by the
179  * globalization procedure. See `NonlinearSolver::NewtonRaphson` for details.
180  */
181 template <typename OptionsGroup>
183  static std::string name() noexcept {
184  return "StepLength(" + Options::name<OptionsGroup>() + ")";
185  }
186  using type = double;
187 };
188 
189 /*!
190  * \brief Sufficient decrease parameter of the line search globalization
191  *
192  * \see `NonlinearSolver::OptionTags::SufficientDecrease`
193  */
194 template <typename OptionsGroup>
196  static std::string name() noexcept {
197  return "SufficientDecrease(" + Options::name<OptionsGroup>() + ")";
198  }
199  using type = double;
200  static constexpr bool pass_metavariables = false;
201  using option_tags = tmpl::list<OptionTags::SufficientDecrease<OptionsGroup>>;
202  static type create_from_options(const type& option) { return option; }
203 };
204 
205 /*!
206  * \brief Nonlinear solver steps are damped by this factor
207  *
208  * \see `NonlinearSolver::OptionTags::DampingFactor`
209  */
210 template <typename OptionsGroup>
212  static std::string name() noexcept {
213  return "DampingFactor(" + Options::name<OptionsGroup>() + ")";
214  }
215  using type = double;
216  static constexpr bool pass_metavariables = false;
217  using option_tags = tmpl::list<OptionTags::DampingFactor<OptionsGroup>>;
218  static type create_from_options(const type& option) { return option; }
219 };
220 
221 /*!
222  * \brief The maximum number of allowed globalization steps
223  *
224  * \see `NonlinearSolver::OptionTags::MinStepLength`
225  */
226 template <typename OptionsGroup>
228  static std::string name() noexcept {
229  return "MaxGlobalizationSteps(" + Options::name<OptionsGroup>() + ")";
230  }
231  using type = size_t;
232  static constexpr bool pass_metavariables = false;
233  using option_tags =
234  tmpl::list<OptionTags::MaxGlobalizationSteps<OptionsGroup>>;
235  static type create_from_options(const type& option) { return option; }
236 };
237 
238 /// Prefix indicating the `Tag` is related to the globalization procedure
239 template <typename Tag>
241  using type = typename Tag::type;
242  using tag = Tag;
243 };
244 
245 } // namespace Tags
246 } // namespace NonlinearSolver
db::ComputeTag
Mark a struct as a compute tag by inheriting from this.
Definition: Tag.hpp:157
NonlinearSolver::OptionTags::MaxGlobalizationSteps
The maximum number of allowed globalization steps.
Definition: Tags.hpp:85
NonlinearSolver::Tags::Residual
The nonlinear residual .
Definition: Tags.hpp:141
std::string
db::PrefixTag
Mark a struct as a prefix tag by inheriting from this.
Definition: Tag.hpp:103
Options.hpp
db::add_tag_prefix
typename detail::add_tag_prefix_impl< Prefix, Tag, Args... >::type add_tag_prefix
Definition: PrefixHelpers.hpp:51
NonlinearSolver::Tags::SufficientDecrease
Sufficient decrease parameter of the line search globalization.
Definition: Tags.hpp:195
db::SimpleTag
Mark a struct as a simple tag by inheriting from this.
Definition: Tag.hpp:36
NonlinearSolver::OptionTags::DampingFactor
Nonlinear solver steps are damped by this factor.
Definition: Tags.hpp:65
NonlinearSolver::Tags::StepLength
The length of nonlinear solver steps.
Definition: Tags.hpp:182
NonlinearSolver::Tags::ResidualCompute
Compute the residual from the SourceTag and the db::add_tag_prefix<NonlinearSolver::Tags::OperatorA...
Definition: Tags.hpp:154
cstddef
NonlinearSolver
Functionality for solving nonlinear systems of equations.
Definition: ElementActions.hpp:49
NonlinearSolver::Tags::OperatorAppliedTo
The nonlinear operator applied to the data in Tag
Definition: Tags.hpp:127
NonlinearSolver::Tags::MaxGlobalizationSteps
The maximum number of allowed globalization steps.
Definition: Tags.hpp:227
NonlinearSolver::OptionTags::SufficientDecrease
Sufficient decrease parameter of the line search globalization.
Definition: Tags.hpp:46
Gsl.hpp
Options::String
const char *const String
The string used in option structs.
Definition: Options.hpp:32
NonlinearSolver::Tags::DampingFactor
Nonlinear solver steps are damped by this factor.
Definition: Tags.hpp:211
NonlinearSolver::Tags::Globalization
Prefix indicating the Tag is related to the globalization procedure.
Definition: Tags.hpp:240
NonlinearSolver::Tags::Correction
The correction to improve a solution .
Definition: Tags.hpp:117
gsl::not_null
Require a pointer to not be a nullptr
Definition: ReadSpecThirdOrderPiecewisePolynomial.hpp:13
string