DNDSR 0.2.1
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
Linear.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
4
5#include "DNDS/HardEigen.hpp"
6#include "DNDS/Defines.hpp"
7
8namespace DNDS::Linear
9{
10
11 template <class TDATA>
13 {
14 uint32_t kSubspace;
15
16 std::vector<TDATA> Vs;
17 TDATA V_temp;
18 TDATA MLb;
19
20 public:
21 template <class Finit>
23 uint32_t NkSubspace,
24 Finit &&finit = [](TDATA &) {}) : kSubspace(NkSubspace)
25 {
26 Vs.resize(kSubspace + 1);
27 for (auto &i : Vs)
28 finit(i);
29 finit(V_temp);
30 finit(MLb);
31 }
32
33 /**
34 * @brief
35 *
36 * @tparam TFA
37 * @tparam TFML
38 * @tparam TFstop
39 * @param FA void FA(TDATA &x, TDATA &Ax)
40 * @param FML void FML(TDATA &x, TDATA &MLx)
41 * @param b rhs
42 * @param x input and output
43 * @param nRestart
44 * @param FStop bool FStop(iRestart, res, resB)
45 */
46 template <class TFA, class TFML, class TFDot, class TFstop>
47 bool solve(TFA &&FA, TFML &&FML, TFDot &&fDot, TDATA &b, TDATA &x, uint32_t nRestart, TFstop &&FStop)
48 {
49 FML(b, MLb); // MLb = ML * b
50 real scale_MLb = std::sqrt(fDot(MLb, MLb));
51 MatrixXR h;
52 h.setZero(kSubspace + 1, kSubspace);
53 uint32_t iRestart = 0;
54 for (iRestart = 0; iRestart <= nRestart; iRestart++)
55 {
56 FA(x, V_temp); // V_temp = A * x
57 FML(V_temp, Vs[0]); // Vs[0] = ML * A * x
58 Vs[0].addTo(MLb, -1.0); // Vs[0] = ML * A * x - ML * b = -r
59 real beta = UnInitReal;
60 beta = std::sqrt(fDot(Vs[0], Vs[0])); // beta = norm2(r)
61 if (FStop(iRestart, beta, scale_MLb)) // see if converge
62 break;
63 if (std::abs(beta) < verySmallReal || // beta is floating-point negligible
64 (iRestart == nRestart))
65 break;
66 Vs[0] *= -1.0 / beta; // Vs[0] = r/norm2(r)
67
68 uint32_t j = 0;
69 for (; j < kSubspace; j++) // Arnoldi
70 {
71 FA(Vs[j], V_temp); // V_temp = A * Vs[j]
72 FML(V_temp, Vs[j + 1]); // Vs[j + 1] = ML * A * Vs[j]
73 for (uint32_t i = 0; i <= j; i++)
74 {
75 // Gram-Schmidt, calculate projected lengths
76 h(i, j) = fDot(Vs[j + 1], (Vs[i])); // h(i, j) = dot(ML * A * Vs[j],Vs[i])
77 }
78 for (uint32_t i = 0; i <= j; i++)
79 {
80 // Gram-Schmidt, subtract projections
81 Vs[j + 1].addTo(Vs[i], -h(i, j)); // Vs[j + 1] = ML * A * Vs[j] - sum_{i=0,1,...j}(h(i,j) * Vs[i])
82 }
83 h(j + 1, j) = std::sqrt(fDot(Vs[j + 1], Vs[j + 1])); //
84 if (h(j + 1, j) < scale_MLb * 1e-32)
85 {
86 std::cout << "early stop" << std::endl;
87 break;
88 }
89 Vs[j + 1] *= 1.0 / h(j + 1, j); // normalize
90 }
91 // std::cout << beta << std::endl;
92
93 VectorXR eBeta;
94 eBeta.resize(j + 1);
95 eBeta.setZero();
96 eBeta(0) = beta; // eBeta = e_1 * beta
97 if (j < 1)
98 break;
99
100 { // the QR method
101 // auto QR = h.colPivHouseholderQr();
102 // QR.setThreshold(std::sqrt(scale_MLb) * 1e-32);
103 // if (QR.rank() != h.rows())
104 // DNDS_assert_info(false, "GMRES not good");
105 // Eigen::VectorXd y = QR.solve(eBeta);
106 }
107
108 // auto sol = h(Eigen::seq(0, j + 1 - 1), Eigen::seq(0, j - 1)).bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV);
109 // Eigen::VectorXd y = sol.solve(eBeta); //! warning: this gmres is dumb and do not lucky stop
110 MatrixXR y;
111 MatrixXR hPart = h(Eigen::seq(0, j + 1 - 1), Eigen::seq(0, j - 1));
112 DNDS_assert_info(hPart.allFinite(), "GMRES_LeftPreconditioned acquired inf or nan coefficient");
113 auto rank = HardEigen::EigenLeastSquareSolve(hPart, eBeta, y);
114
115 // int rank;
116 // MPI_Comm_rank(MPI_COMM_WORLD, &rank);
117 // if (rank == 0)
118 // std::cout << h << std::endl;
119
120 for (uint32_t jj = 0; jj < j; jj++) // x = V(:, 0,1,2,...kSubspace-1) * y
121 {
122 x.addTo(Vs[jj], y(jj));
123 // std::cout << iRestart << "::" << Vs[j].transpose() << "::" << y(j) << std::endl;
124 }
125 if (rank < h.cols())
126 {
127
128 break; // do not restart
129 }
130 }
131 return iRestart < nRestart;
132 }
133 };
134
135 template <class TDATA, class TScalar>
137 {
138 bool initialized = false;
139 TDATA r, z, p, Ap;
140 TDATA V_temp;
141
142 TScalar zrDot;
143
144 index pHistorySize{0};
145
146 public:
147 template <class Finit>
149 Finit &&finit = [](TDATA &) {})
150 {
151 finit(r);
152 finit(z);
153 finit(p);
154 finit(Ap);
155 finit(V_temp);
156 }
157
158 void reset() { initialized = false, pHistorySize = 0; }
159
160 [[nodiscard]] index getPHistorySize() const { return pHistorySize; }
161
162 template <class TFA, class TFM, class TFResPrec, class TFDot, class TFstop>
163 bool solve(TFA &&FA, TFM &&FM, TFResPrec &&FResPrec, TFDot &&fDot, TDATA &x, uint32_t niter, TFstop &&FStop)
164 {
165 if (!initialized)
166 {
167 FResPrec(x, z);
168 FM(z, r);
169 p = z;
170 pHistorySize++;
171 FA(p, Ap);
172 }
173 for (int iter = 1; iter <= niter; iter++)
174 {
175 if (initialized)
176 {
177 FResPrec(x, z);
178 FM(z, r);
179 }
180 TScalar zrDotNew = fDot(z, r);
181 TScalar zDotz = fDot(z, z);
182 if (FStop(iter, zrDotNew, zDotz))
183 return true;
184
185 if (initialized)
186 {
187 TScalar beta = zrDotNew / (zrDot + verySmallReal);
188 p *= beta;
189 p += z;
190 pHistorySize++;
191 FA(p, Ap);
192 }
193
194 TScalar alpha = zrDotNew / (fDot(p, Ap) + verySmallReal);
195 x.addTo(p, alpha);
196
197 zrDot = zrDotNew;
198 initialized = true;
199 }
200 return false;
201 }
202 };
203}
Core type aliases, constants, and metaprogramming utilities for the DNDS framework.
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
Definition Errors.hpp:117
Robust linear-algebra primitives for small / moderately-sized Eigen matrices that are more numericall...
GMRES_LeftPreconditioned(uint32_t NkSubspace, Finit &&finit=[](TDATA &) {})
Definition Linear.hpp:22
bool solve(TFA &&FA, TFML &&FML, TFDot &&fDot, TDATA &b, TDATA &x, uint32_t nRestart, TFstop &&FStop)
Definition Linear.hpp:47
PCG_PreconditionedRes(Finit &&finit=[](TDATA &) {})
Definition Linear.hpp:148
bool solve(TFA &&FA, TFM &&FM, TFResPrec &&FResPrec, TFDot &&fDot, TDATA &x, uint32_t niter, TFstop &&FStop)
Definition Linear.hpp:163
Eigen::Index EigenLeastSquareSolve(const Eigen::MatrixXd &A, const Eigen::MatrixXd &B, Eigen::MatrixXd &AIB)
Least-squares solve A * AIB ~= B via a rank-revealing QR-style decomposition; returns the computed ra...
DNDS_CONSTANT const real verySmallReal
Catch-all lower bound ("effectively zero").
Definition Defines.hpp:199
DNDS_CONSTANT const real UnInitReal
Sentinel "not initialised" real value (NaN). Cheap to detect with std::isnan or IsUnInitReal; survive...
Definition Defines.hpp:179
Eigen::Matrix< real, Eigen::Dynamic, Eigen::Dynamic > MatrixXR
Column-major dynamic Eigen matrix of reals (default layout).
Definition Defines.hpp:210
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
Definition Defines.hpp:112
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
Definition Defines.hpp:110
Eigen::Vector< real, Eigen::Dynamic > VectorXR
Dynamic Eigen vector of reals.
Definition Defines.hpp:212
tVec r(NCells)
tVec z(NCells)
tVec x(NCells)
tVec b(NCells)
real alpha
const tPoint const tPoint const tPoint & p