1 #pragma once // Ensure that file is included only once in a single compilation.
30 const char*
what()
const throw() {
return "The sparse CG method did not converge."; }
47 template <
typename vectorT>
48 typename vectorT::value_type
inner_product(
const vectorT& left,
const vectorT& right)
50 hy_assert(left.size() == right.size(),
"Both vectors of inner product must be of same size!");
52 typename vectorT::value_type product = 0.;
53 for (decltype(left.size()) i = 0; i < left.size(); ++i)
54 product += left[i] * right[i];
70 template <
typename vectorT>
71 typename vectorT::value_type
norm_2(
const vectorT& vec)
92 template <
typename vectorT>
94 const vectorT& leftVec,
95 const typename vectorT::value_type rightFac,
96 const vectorT& rightVec)
98 hy_assert(leftVec.size() == rightVec.size(),
"Linear combined vectors must be of same size!");
100 vectorT lin_comb(leftVec.size(), 0.);
101 for (decltype(leftVec.size()) i = 0; i < leftVec.size(); ++i)
102 lin_comb[i] = leftFac * leftVec[i] + rightFac * rightVec[i];
123 template <
typename vectorT>
125 const vectorT& leftV,
126 const typename vectorT::value_type rightFac,
127 const vectorT& rightV,
130 hy_assert(leftV.size() == rightV.size() && leftV.size() == result.size(),
131 "All three vectors of linear combination must be of same size!");
133 for (decltype(leftV.size()) i = 0; i < result.size(); ++i)
134 result[i] = leftFac * leftV[i] + rightFac * rightV[i];
156 template <
class ProblemT,
typename vectorT>
159 unsigned int n_iterations = 0,
160 const typename vectorT::value_type
tolerance = 1e-9)
162 vectorT x(b.size(), (
typename vectorT::value_type)0.);
166 typename vectorT::value_type r_square_new =
inner_product(r, r);
167 typename vectorT::value_type r_square_old = r_square_new;
175 if (n_iterations == 0)
176 n_iterations = b.size();
177 hy_assert(n_iterations > 0,
"Number of allowed iterations of CG solver must be positive.");
179 for (
unsigned int k = 0; k < n_iterations; ++k)
181 vectorT z = problem.trace_to_flux(d);
182 r_square_old = r_square_new;
184 typename vectorT::value_type alpha = r_square_old /
inner_product(d, z);
190 typename vectorT::value_type beta = r_square_new / r_square_old;
195 n_iterations = k + 1;