HyperHDG
sparse_la.hxx
Go to the documentation of this file.
1 #pragma once // Ensure that file is included only once in a single compilation.
2 
3 #include <HyperHDG/hy_assert.hxx>
4 
5 // #include <cmath>
6 // #include <exception>
7 
8 /*!*************************************************************************************************
9  * \brief A namespace containing different functions that implement basic linear algebra
10  * operations using large vectors.
11  *
12  * This namespace provides several functions to implement basic linear algebra operations of (long)
13  * vector type in combination with a class providing a function \c matrix_vector_multiply. This
14  * is mainly used for C++ examples and test cases that do not use the Python interface and its
15  * version of an CG method, for example.
16  *
17  * \authors Guido Kanschat, Heidelberg University, 2020.
18  * \authors Andreas Rupp, Heidelberg University, 2020.
19  **************************************************************************************************/
20 namespace SparseLA
21 {
22 /*!*************************************************************************************************
23  * \brief Exception to be thrown if conjugate gradient fails.
24  *
25  * \authors Guido Kanschat, Heidelberg University, 2019.
26  * \authors Andreas Rupp, Heidelberg University, 2019.
27  **************************************************************************************************/
29 {
30  const char* what() const throw() { return "The sparse CG method did not converge."; }
31 };
32 /*!*************************************************************************************************
33  * \brief Evaluate the inner product of two vectors.
34  *
35  * Naive implementation of an Euclidean inner product of two large vectors which are supposed to be
36  * of the same size. This function is needed to calculate a vector's 2 norm or to implement a CG
37  * scheme.
38  *
39  * \tparam vectorT The class name of the large vector.
40  * \param left Left argument of the inner product.
41  * \param right Right argument of the inner product.
42  * \retval product Inner product of the two arguments.
43  *
44  * \authors Guido Kanschat, Heidelberg University, 2020.
45  * \authors Andreas Rupp, Heidelberg University, 2020.
46  **************************************************************************************************/
47 template <typename vectorT>
48 typename vectorT::value_type inner_product(const vectorT& left, const vectorT& right)
49 {
50  hy_assert(left.size() == right.size(), "Both vectors of inner product must be of same size!");
51 
52  typename vectorT::value_type product = 0.;
53  for (decltype(left.size()) i = 0; i < left.size(); ++i)
54  product += left[i] * right[i];
55  return product;
56 }
57 /*!*************************************************************************************************
58  * \brief Evaluate 2 norm of a vector.
59  *
60  * Naive implementation of an 2 norm of a vector. This is the square root of the \c inner_product of
61  * a vector paired with itself.
62  *
63  * \tparam vectorT The class name of the large vector.
64  * \param vec Vector whose 2 norm is to be calculates.
65  * \retval norm 2 norm of given vector.
66  *
67  * \authors Guido Kanschat, Heidelberg University, 2020.
68  * \authors Andreas Rupp, Heidelberg University, 2020.
69  **************************************************************************************************/
70 template <typename vectorT>
71 typename vectorT::value_type norm_2(const vectorT& vec)
72 {
73  return std::sqrt(inner_product(vec, vec));
74 }
75 /*!*************************************************************************************************
76  * \brief Evaluate linear combination of vectors and return the result.
77  *
78  * This functions takes two large vectors and two floating points, and returns their linear
79  * combination "leftFac * leftVec + rightFac * rightVec" as a new vector (in contrast to just a
80  * reference to a vector).
81  *
82  * \tparam vectorT The class name of the large vector.
83  * \param leftFac Scaling factor of left vector.
84  * \param leftVec Left vector in linear combination.
85  * \param rightFac Scaling factor of right vector.
86  * \param rightVec Right vector in linear combination.
87  * \retval lin_comb Linear combination of vectors with respective coefficients.
88  *
89  * \authors Guido Kanschat, Heidelberg University, 2020.
90  * \authors Andreas Rupp, Heidelberg University, 2020.
91  **************************************************************************************************/
92 template <typename vectorT>
93 vectorT linear_combination(const typename vectorT::value_type leftFac,
94  const vectorT& leftVec,
95  const typename vectorT::value_type rightFac,
96  const vectorT& rightVec)
97 {
98  hy_assert(leftVec.size() == rightVec.size(), "Linear combined vectors must be of same size!");
99 
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];
103  return lin_comb;
104 }
105 /*!*************************************************************************************************
106  * \brief Evaluate linear combination of vectors and return reference to result.
107  *
108  * This functions takes two large vectors and two floating points, and returns their linear
109  * combination "leftFac * leftVec + rightFac * rightVec" as a reference to a vector. This vector
110  * needs to be passed to the function
111  *
112  * \tparam vectorT The class name of the large vector.
113  * \param leftFac Scaling factor of left vector.
114  * \param leftV Left vector in linear combination.
115  * \param rightFac Scaling factor of right vector.
116  * \param rightV Right vector in linear combination.
117  * \param result Reference to vector whicb is supposed to contain the result.
118  * \retval result Linear combination of vectors with respective coefficients.
119  *
120  * \authors Guido Kanschat, Heidelberg University, 2020.
121  * \authors Andreas Rupp, Heidelberg University, 2020.
122  **************************************************************************************************/
123 template <typename vectorT>
124 void linear_combination(const typename vectorT::value_type leftFac,
125  const vectorT& leftV,
126  const typename vectorT::value_type rightFac,
127  const vectorT& rightV,
128  vectorT& result)
129 {
130  hy_assert(leftV.size() == rightV.size() && leftV.size() == result.size(),
131  "All three vectors of linear combination must be of same size!");
132 
133  for (decltype(leftV.size()) i = 0; i < result.size(); ++i)
134  result[i] = leftFac * leftV[i] + rightFac * rightV[i];
135 }
136 /*!*************************************************************************************************
137  * \brief Execute conjugate gradient algorithm to find solution to system of equations.
138  *
139  * Execute conjugate gradient algorithm where the matrix is not explicitly given, but the template
140  * class \c ProblemT is supposed to implement a function \c matrix_vector_multiply which only takes
141  * a \c large vector and generates the matrix vector product from that. The associated matrix is
142  * assumed to be square and symmetric positive definite.
143  *
144  * \tparam ProblemT Class to implement matrix vector multiplication.
145  * \tparam vectorT The class name of the large vector.
146  * \param b Right-hand side of linear system of equations.
147  * \param problem Class instantiation to implement matrix vector multiplication.
148  * \param n_iterations Maximum number of iterations. 0 is default and the size of b.
149  * \param tolerance Absolute tolerance value in 2 norm. Default is 1e-9.
150  * \retval solution Vector sufficing Ax = b up to given tolerance if converged.
151  * \retval n_iterations Number of needed iterations. -1 indicates no convergence.
152  *
153  * \authors Guido Kanschat, Heidelberg University, 2020.
154  * \authors Andreas Rupp, Heidelberg University, 2020.
155  **************************************************************************************************/
156 template <class ProblemT, typename vectorT>
157 vectorT conjugate_gradient(const vectorT& b,
158  ProblemT& problem,
159  unsigned int n_iterations = 0,
160  const typename vectorT::value_type tolerance = 1e-9)
161 {
162  vectorT x(b.size(), (typename vectorT::value_type)0.);
163  vectorT r = b; // b - A * x (with x = 0)
164  vectorT d = r;
165 
166  typename vectorT::value_type r_square_new = inner_product(r, r);
167  typename vectorT::value_type r_square_old = r_square_new;
168 
169  if (r_square_new < tolerance * tolerance)
170  {
171  n_iterations = 0;
172  return x;
173  }
174 
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.");
178 
179  for (unsigned int k = 0; k < n_iterations; ++k)
180  {
181  vectorT z = problem.trace_to_flux(d);
182  r_square_old = r_square_new;
183 
184  typename vectorT::value_type alpha = r_square_old / inner_product(d, z);
185  linear_combination((typename vectorT::value_type)1., x, alpha, d, x);
186  linear_combination((typename vectorT::value_type)1., r, -alpha, z, r);
187 
188  r_square_new = inner_product(r, r);
189 
190  typename vectorT::value_type beta = r_square_new / r_square_old;
191  linear_combination((typename vectorT::value_type)1., r, beta, d, d);
192 
193  if (r_square_new < tolerance * tolerance)
194  {
195  n_iterations = k + 1;
196  return x;
197  }
198  }
199 
200  throw SparseLA::SolveException();
201 
202  return x;
203 }
204 
205 } // end of namespace SparseLA
hy_assert.hxx
This file provides the function hy_assert.
SparseLA::conjugate_gradient
vectorT conjugate_gradient(const vectorT &b, ProblemT &problem, unsigned int n_iterations=0, const typename vectorT::value_type tolerance=1e-9)
Execute conjugate gradient algorithm to find solution to system of equations.
Definition: sparse_la.hxx:157
SparseLA
A namespace containing different functions that implement basic linear algebra operations using large...
Definition: sparse_la.hxx:20
exception
if the work is an executable linked with the with the complete machine readable work that uses the as object code and or source so that the user can modify the Library and then relink to produce a modified executable containing the modified rather than copying library functions into the if the user installs as long as the modified version is interface compatible with the version that the work was made with c Accompany the work with a written valid for at least three to give the same user the materials specified in for a charge no more than the cost of performing this distribution d If distribution of the work is made by offering access to copy from a designated offer equivalent access to copy the above specified materials from the same place e Verify that the user has already received a copy of these materials or that you have already sent this user a copy For an the required form of the work that uses the Library must include any data and utility programs needed for reproducing the executable from it as a special exception
Definition: License.txt:320
SparseLA::norm_2
vectorT::value_type norm_2(const vectorT &vec)
Evaluate 2 norm of a vector.
Definition: sparse_la.hxx:71
SparseLA::SolveException
Exception to be thrown if conjugate gradient fails.
Definition: sparse_la.hxx:28
SparseLA::inner_product
vectorT::value_type inner_product(const vectorT &left, const vectorT &right)
Evaluate the inner product of two vectors.
Definition: sparse_la.hxx:48
hy_assert
#define hy_assert(Expr, Msg)
The assertion to be used within HyperHDG — deactivate using -DNDEBUG compile flag.
Definition: hy_assert.hxx:38
SparseLA::linear_combination
vectorT linear_combination(const typename vectorT::value_type leftFac, const vectorT &leftVec, const typename vectorT::value_type rightFac, const vectorT &rightVec)
Evaluate linear combination of vectors and return the result.
Definition: sparse_la.hxx:93
diffusion_uniform.tolerance
int tolerance
Definition: diffusion_uniform.py:27
SparseLA::SolveException::what
const char * what() const
Definition: sparse_la.hxx:30