Loading...
Searching...
No Matches
CG-Impl.hpp
Go to the documentation of this file.
1// This code is based on Jet framework.
2// Copyright (c) 2018 Doyub Kim
3// CubbyFlow is voxel-based fluid simulation engine for computer games.
4// Copyright (c) 2020 CubbyFlow Team
5// Core Part: Chris Ohk, Junwoo Hwang, Jihong Sin, Seungwoo Yoo
6// AI Part: Dongheon Cho, Minseo Kim
7// We are making my contributions/submissions to this project solely in our
8// personal capacity and are not conveying any rights to any intellectual
9// property of any third parties.
10
11#ifndef CUBBYFLOW_CG_IMPL_HPP
12#define CUBBYFLOW_CG_IMPL_HPP
13
15
16#include <limits>
17
18namespace CubbyFlow
19{
20template <typename BLASType>
21void CG(const typename BLASType::MatrixType& A,
22 const typename BLASType::VectorType& b,
23 unsigned int maxNumberOfIterations, double tolerance,
24 typename BLASType::VectorType* x, typename BLASType::VectorType* r,
25 typename BLASType::VectorType* d, typename BLASType::VectorType* q,
26 typename BLASType::VectorType* s, unsigned int* lastNumberOfIterations,
27 double* lastResidualNorm)
28{
31
33 x, r, d, q, s, lastNumberOfIterations,
34 lastResidualNorm);
35}
36
37template <typename BLASType>
38void CR(const typename BLASType::MatrixType& A,
39 const typename BLASType::VectorType& b,
40 unsigned int maxNumberOfIterations, double tolerance,
41 typename BLASType::VectorType* x, typename BLASType::VectorType* r,
42 typename BLASType::VectorType* d, typename BLASType::VectorType* q,
43 typename BLASType::VectorType* s, unsigned int* lastNumberOfIterations,
44 double* lastResidualNorm)
45{
46 BLASType::Residual(A, *x, b, r);
47 BLASType::Set(*r, d);
48 BLASType::MVM(A, *r, s);
49 BLASType::Set(*s, q);
50
51 double rho = BLASType::Dot(*r, *s);
52 double residualNorm = BLASType::L2Norm(*r);
53 unsigned int iter = 0;
54
55 while (residualNorm > tolerance && iter < maxNumberOfIterations)
56 {
57 const double denominator = BLASType::Dot(*q, *q);
58
59 if (!std::isfinite(rho) || !std::isfinite(denominator) ||
60 denominator <= 0.0 || rho == 0.0)
61 {
62 residualNorm = std::numeric_limits<double>::infinity();
63 break;
64 }
65
66 const double alpha = rho / denominator;
67
68 BLASType::AXPlusY(alpha, *d, *x, x);
69 BLASType::AXPlusY(-alpha, *q, *r, r);
70
71 residualNorm = BLASType::L2Norm(*r);
72 ++iter;
73
74 if (!std::isfinite(residualNorm))
75 {
76 residualNorm = std::numeric_limits<double>::infinity();
77 break;
78 }
79
80 if (residualNorm <= tolerance)
81 {
82 break;
83 }
84
85 BLASType::MVM(A, *r, s);
86
87 const double rhoNew = BLASType::Dot(*r, *s);
88
89 if (!std::isfinite(rhoNew))
90 {
91 residualNorm = std::numeric_limits<double>::infinity();
92 break;
93 }
94
95 const double beta = rhoNew / rho;
96
97 BLASType::AXPlusY(beta, *d, *r, d);
98 BLASType::AXPlusY(beta, *q, *s, q);
99 rho = rhoNew;
100 }
101
103 *lastResidualNorm = residualNorm;
104}
105
106template <typename BLASType, typename PrecondType>
107void PCG(const typename BLASType::MatrixType& A,
108 const typename BLASType::VectorType& b,
109 unsigned int maxNumberOfIterations, double tolerance, PrecondType* M,
110 typename BLASType::VectorType* x, typename BLASType::VectorType* r,
111 typename BLASType::VectorType* d, typename BLASType::VectorType* q,
112 typename BLASType::VectorType* s, unsigned int* lastNumberOfIterations,
113 double* lastResidualNorm)
114{
115 // Clear
116 BLASType::Set(0, r);
117 BLASType::Set(0, d);
118 BLASType::Set(0, q);
119 BLASType::Set(0, s);
120
121 // r = b - Ax
122 BLASType::Residual(A, *x, b, r);
123
124 // d = M^-1r
125 M->Solve(*r, d);
126
127 // sigmaNew = r.d
128 double sigmaNew = BLASType::Dot(*r, *d);
129
130 unsigned int iter = 0;
131 bool trigger = false;
132
133 while (sigmaNew > Square(tolerance) && iter < maxNumberOfIterations)
134 {
135 // q = Ad
136 BLASType::MVM(A, *d, q);
137
138 // alpha = sigmaNew / d.q
139 double alpha = sigmaNew / BLASType::Dot(*d, *q);
140
141 // x = x + alpha * d
142 BLASType::AXPlusY(alpha, *d, *x, x);
143
144 // if i is divisible by 50...
145 if (trigger || (iter % 50 == 0 && iter > 0))
146 {
147 // r = b - Ax
148 BLASType::Residual(A, *x, b, r);
149 trigger = false;
150 }
151 else
152 {
153 // r = r - alpha * q
154 BLASType::AXPlusY(-alpha, *q, *r, r);
155 }
156
157 // s = M^-1r
158 M->Solve(*r, s);
159
160 // sigmaOld = sigmaNew
161 const double sigmaOld = sigmaNew;
162
163 // sigmaNew = r.s
165
166 if (sigmaNew > sigmaOld)
167 {
168 trigger = true;
169 }
170
171 // beta = sigmaNew / sigmaOld
172 double beta = sigmaNew / sigmaOld;
173
174 // d = s + beta*d
175 BLASType::AXPlusY(beta, *d, *s, d);
176
177 ++iter;
178 }
179
181
182 // std::fabs(sigmaNew) - Workaround for negative zero
183 *lastResidualNorm = std::sqrt(std::fabs(sigmaNew));
184}
185} // namespace CubbyFlow
186
187#endif
std::enable_if_t<(IsMatrixSizeDynamic< Rows, Cols >()||Cols==1) &&(IsMatrixSizeDynamic< R, C >()||C==1), U > Dot(const MatrixExpression< T, R, C, E > &expression) const
Definition MatrixExpression-Impl.hpp:391
Definition Matrix.hpp:30
Definition pybind11Utils.hpp:22
void CR(const typename BLASType::MatrixType &A, const typename BLASType::VectorType &b, unsigned int maxNumberOfIterations, double tolerance, typename BLASType::VectorType *x, typename BLASType::VectorType *r, typename BLASType::VectorType *d, typename BLASType::VectorType *q, typename BLASType::VectorType *s, unsigned int *lastNumberOfIterations, double *lastResidualNorm)
Solves a symmetric linear system with conjugate residual.
Definition CG-Impl.hpp:38
std::enable_if_t< std::is_arithmetic< T >::value, T > Square(T x)
Returns the square of x.
Definition MathUtils-Impl.hpp:154
Matrix< T, Rows, 1 > Vector
Definition Matrix.hpp:648
void PCG(const typename BLASType::MatrixType &A, const typename BLASType::VectorType &b, unsigned int maxNumberOfIterations, double tolerance, PrecondType *M, typename BLASType::VectorType *x, typename BLASType::VectorType *r, typename BLASType::VectorType *d, typename BLASType::VectorType *q, typename BLASType::VectorType *s, unsigned int *lastNumberOfIterations, double *lastResidualNorm)
Solves pre-conditioned conjugate gradient.
Definition CG-Impl.hpp:107
void CG(const typename BLASType::MatrixType &A, const typename BLASType::VectorType &b, unsigned int maxNumberOfIterations, double tolerance, typename BLASType::VectorType *x, typename BLASType::VectorType *r, typename BLASType::VectorType *d, typename BLASType::VectorType *q, typename BLASType::VectorType *s, unsigned int *lastNumberOfIterations, double *lastResidualNorm)
Solves conjugate gradient.
Definition CG-Impl.hpp:21