Grid 0.7.0
MinimalResidual.h
Go to the documentation of this file.
1/*************************************************************************************
2
3Grid physics library, www.github.com/paboyle/Grid
4
5Source file: ./lib/algorithms/iterative/MinimalResidual.h
6
7Copyright (C) 2015
8
9Author: Daniel Richtmann <daniel.richtmann@ur.de>
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License along
22with this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25See the full license in the file "LICENSE" in the top level distribution
26directory
27*************************************************************************************/
28/* END LEGAL */
29#ifndef GRID_MINIMAL_RESIDUAL_H
30#define GRID_MINIMAL_RESIDUAL_H
31
32namespace Grid {
33
34template<class Field> class MinimalResidual : public OperatorFunction<Field> {
35 public:
36 using OperatorFunction<Field>::operator();
37
38 bool ErrorOnNoConverge; // throw an assert when the MR fails to converge.
39 // Defaults true.
43 Integer IterationsToComplete; // Number of iterations the MR took to finish.
44 // Filled in upon completion
45
46 MinimalResidual(RealD tol, Integer maxit, Real ovrelparam = 1.0, bool err_on_no_conv = true)
47 : Tolerance(tol), MaxIterations(maxit), overRelaxParam(ovrelparam), ErrorOnNoConverge(err_on_no_conv){};
48
49 void operator()(LinearOperatorBase<Field> &Linop, const Field &src, Field &psi) {
50
51 psi.Checkerboard() = src.Checkerboard();
52 conformable(psi, src);
53
54 ComplexD a, c;
55 RealD d;
56
57 Field Mr(src);
58 Field r(src);
59
60 // Initial residual computation & set up
61 RealD guess = norm2(psi);
62 assert(std::isnan(guess) == 0);
63
64 RealD ssq = norm2(src);
65 RealD rsq = Tolerance * Tolerance * ssq;
66
67 Linop.Op(psi, Mr);
68
69 r = src - Mr;
70
71 RealD cp = norm2(r);
72
73 std::cout << std::setprecision(4) << std::scientific;
74 std::cout << GridLogIterative << "MinimalResidual: guess " << guess << std::endl;
75 std::cout << GridLogIterative << "MinimalResidual: src " << ssq << std::endl;
76 std::cout << GridLogIterative << "MinimalResidual: cp,r " << cp << std::endl;
77
78 if (cp <= rsq) {
79 return;
80 }
81
82 std::cout << GridLogIterative << "MinimalResidual: k=0 residual " << cp << " target " << rsq << std::endl;
83
84 GridStopWatch LinalgTimer;
85 GridStopWatch MatrixTimer;
86 GridStopWatch SolverTimer;
87
88 SolverTimer.Start();
89 int k;
90 for (k = 1; k <= MaxIterations; k++) {
91
92 MatrixTimer.Start();
93 Linop.Op(r, Mr);
94 MatrixTimer.Stop();
95
96 LinalgTimer.Start();
97
98 c = innerProduct(Mr, r);
99
100 d = norm2(Mr);
101
102 a = c / d;
103
104 a = a * overRelaxParam;
105
106 psi = psi + r * a;
107
108 r = r - Mr * a;
109
110 cp = norm2(r);
111
112 LinalgTimer.Stop();
113
114 std::cout << GridLogIterative << "MinimalResidual: Iteration " << k
115 << " residual " << cp << " target " << rsq << std::endl;
116 std::cout << GridLogDebug << "a = " << a << " c = " << c << " d = " << d << std::endl;
117
118 // Stopping condition
119 if (cp <= rsq) {
120 SolverTimer.Stop();
121
122 Linop.Op(psi, Mr);
123 r = src - Mr;
124
125 RealD srcnorm = sqrt(ssq);
126 RealD resnorm = sqrt(norm2(r));
127 RealD true_residual = resnorm / srcnorm;
128
129 std::cout << GridLogMessage << "MinimalResidual Converged on iteration " << k
130 << " computed residual " << sqrt(cp / ssq)
131 << " true residual " << true_residual
132 << " target " << Tolerance << std::endl;
133
134 std::cout << GridLogMessage << "MR Time elapsed: Total " << SolverTimer.Elapsed() << std::endl;
135 std::cout << GridLogMessage << "MR Time elapsed: Matrix " << MatrixTimer.Elapsed() << std::endl;
136 std::cout << GridLogMessage << "MR Time elapsed: Linalg " << LinalgTimer.Elapsed() << std::endl;
137
139 assert(true_residual / Tolerance < 10000.0);
140
142
143 return;
144 }
145 }
146
147 std::cout << GridLogMessage << "MinimalResidual did NOT converge"
148 << std::endl;
149
151 assert(0);
152
154 }
155};
156} // namespace Grid
157#endif
accelerator_inline Grid_simd< S, V > sqrt(const Grid_simd< S, V > &r)
void conformable(const Lattice< obj1 > &lhs, const Lattice< obj2 > &rhs)
ComplexD innerProduct(const Lattice< vobj > &left, const Lattice< vobj > &right)
RealD norm2(const Lattice< vobj > &arg)
GridLogger GridLogIterative(1, "Iterative", GridLogColours, "BLUE")
GridLogger GridLogDebug(1, "Debug", GridLogColours, "PURPLE")
GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL")
uint32_t Integer
Definition Simd.h:58
RealF Real
Definition Simd.h:65
std::complex< RealD > ComplexD
Definition Simd.h:79
double RealD
Definition Simd.h:61
void Start(void)
Definition Timer.h:92
GridTime Elapsed(void) const
Definition Timer.h:113
void Stop(void)
Definition Timer.h:99
void operator()(LinearOperatorBase< Field > &Linop, const Field &src, Field &psi)
MinimalResidual(RealD tol, Integer maxit, Real ovrelparam=1.0, bool err_on_no_conv=true)
virtual void Op(const Field &in, Field &out)=0