Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include "DataStructures/DataBox/PrefixHelpers.hpp"
7 : #include "DataStructures/DataBox/Prefixes.hpp"
8 : #include "ParallelAlgorithms/LinearSolver/ConjugateGradient/ElementActions.hpp"
9 : #include "ParallelAlgorithms/LinearSolver/ConjugateGradient/InitializeElement.hpp"
10 : #include "ParallelAlgorithms/LinearSolver/ConjugateGradient/ResidualMonitor.hpp"
11 : #include "Utilities/TMPL.hpp"
12 :
13 : /// Items related to the conjugate gradient linear solver
14 : ///
15 : /// \see `LinearSolver::cg::ConjugateGradient`
16 1 : namespace LinearSolver::cg {
17 :
18 : /*!
19 : * \ingroup LinearSolverGroup
20 : * \brief A conjugate gradient solver for linear systems of equations \f$Ax=b\f$
21 : * where the operator \f$A\f$ is symmetric.
22 : *
23 : * \details The only operation we need to supply to the algorithm is the
24 : * result of the operation \f$A(p)\f$ (see \ref LinearSolverGroup) that in the
25 : * case of the conjugate gradient algorithm must be symmetric. Each step of the
26 : * algorithm expects that \f$A(p)\f$ is computed and stored in the DataBox as
27 : * %db::add_tag_prefix<LinearSolver::Tags::OperatorAppliedTo,
28 : * db::add_tag_prefix<LinearSolver::Tags::Operand, FieldsTag>>. To perform a
29 : * solve, add the `solve` action list to an array parallel component. Pass the
30 : * actions that compute \f$A(q)\f$, as well as any further actions you wish to
31 : * run in each step of the algorithm, as the first template parameter to
32 : * `solve`. If you add the `solve` action list multiple times, use the second
33 : * template parameter to label each solve with a different type.
34 : *
35 : * Note that the operand \f$p\f$ for which \f$A(p)\f$ needs to be computed is
36 : * not the field \f$x\f$ we are solving for but
37 : * `db::add_tag_prefix<LinearSolver::Tags::Operand, FieldsTag>`. This field is
38 : * initially set to the residual \f$r = b - A(x_0)\f$ where \f$x_0\f$ is the
39 : * initial value of the `FieldsTag`.
40 : *
41 : * When the algorithm step is performed after the operator action \f$A(p)\f$ has
42 : * been computed and stored in the DataBox, the conjugate gradient algorithm
43 : * implemented here will converge the field \f$x\f$ towards the solution and
44 : * update the operand \f$p\f$ in the process. This requires two reductions over
45 : * all elements that are received by a `ResidualMonitor` singleton parallel
46 : * component, processed, and then broadcast back to all elements. The actions
47 : * are implemented in the `cg::detail` namespace and constitute the full
48 : * algorithm in the following order:
49 : * 1. `PerformStep` (on elements): Compute the inner product \f$\langle p,
50 : * A(p)\rangle\f$ and reduce.
51 : * 2. `ComputeAlpha` (on `ResidualMonitor`): Compute
52 : * \f$\alpha=\frac{r^2}{\langle p, A(p)\rangle}\f$ and broadcast.
53 : * 3. `UpdateFieldValues` (on elements): Update \f$x\f$ and \f$r\f$, then
54 : * compute the inner product \f$\langle r, r\rangle\f$ and reduce to find the
55 : * new \f$r^2\f$.
56 : * 4. `UpdateResidual` (on `ResidualMonitor`): Store the new \f$r^2\f$ and
57 : * broadcast the ratio of the new and old \f$r^2\f$, as well as a termination
58 : * flag if the `Convergence::Tags::Criteria` are met.
59 : * 5. `UpdateOperand` (on elements): Update \f$p\f$.
60 : *
61 : * \see Gmres for a linear solver that can invert nonsymmetric operators
62 : * \f$A\f$.
63 : */
64 : template <typename Metavariables, typename FieldsTag, typename OptionsGroup,
65 : typename SourceTag =
66 : db::add_tag_prefix<::Tags::FixedSource, FieldsTag>>
67 1 : struct ConjugateGradient {
68 0 : using fields_tag = FieldsTag;
69 0 : using options_group = OptionsGroup;
70 0 : using source_tag = SourceTag;
71 :
72 : /// Apply the linear operator to this tag in each iteration
73 1 : using operand_tag =
74 : db::add_tag_prefix<LinearSolver::Tags::Operand, fields_tag>;
75 :
76 : /*!
77 : * \brief The parallel components used by the conjugate gradient linear solver
78 : */
79 1 : using component_list = tmpl::list<
80 : detail::ResidualMonitor<Metavariables, FieldsTag, OptionsGroup>>;
81 :
82 0 : using initialize_element = detail::InitializeElement<FieldsTag, OptionsGroup>;
83 :
84 0 : using register_element = tmpl::list<>;
85 :
86 : template <typename ApplyOperatorActions, typename Label = OptionsGroup>
87 0 : using solve = tmpl::list<
88 : detail::PrepareSolve<FieldsTag, OptionsGroup, Label, SourceTag>,
89 : detail::InitializeHasConverged<FieldsTag, OptionsGroup, Label>,
90 : ApplyOperatorActions, detail::PerformStep<FieldsTag, OptionsGroup, Label>,
91 : detail::UpdateFieldValues<FieldsTag, OptionsGroup, Label>,
92 : detail::UpdateOperand<FieldsTag, OptionsGroup, Label>>;
93 : };
94 :
95 : } // namespace LinearSolver::cg
|