G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsConjugateGradient.hpp
Go to the documentation of this file.
1 
15 
16 namespace gismo
17 {
18 
19 template<class T>
22 {
23  if (m_calcEigenvals)
24  {
25  m_delta.clear();
26  m_delta.resize(1,0);
27  m_delta.reserve(m_max_iters / 3);
28 
29  m_gamma.clear();
30  m_gamma.reserve(m_max_iters / 3);
31  }
32 
33  if (Base::initIteration(rhs,x))
34  return true;
35 
36  index_t n = m_mat->cols();
37  index_t m = 1; // == rhs.cols();
38  m_tmp.resize(n,m);
39  m_update.resize(n,m);
40 
41  m_mat->apply(x,m_tmp); // apply the system matrix
42  m_res = rhs - m_tmp; // initial residual
43 
44  m_error = m_res.norm() / m_rhs_norm;
45  if (m_error < m_tol)
46  return true;
47 
48  m_precond->apply(m_res,m_update); // initial search direction
49  m_abs_new = m_res.col(0).dot(m_update.col(0)); // the square of the absolute value of r scaled by invM
50 
51  return false;
52 }
53 
54 template<class T>
56 {
57  m_mat->apply(m_update,m_tmp); // apply system matrix
58 
59  T alpha = m_abs_new / m_update.col(0).dot(m_tmp.col(0)); // the amount we travel on dir
60  if (m_calcEigenvals)
61  m_delta.back()+=(1./alpha);
62 
63  x += alpha * m_update; // update solution
64  m_res -= alpha * m_tmp; // update residual
65 
66  m_error = m_res.norm() / m_rhs_norm;
67  if (m_error < m_tol)
68  return true;
69 
70  m_precond->apply(m_res, m_tmp); // approximately solve for "A tmp = residual"
71 
72  T abs_old = m_abs_new;
73 
74  m_abs_new = m_res.col(0).dot(m_tmp.col(0)); // update the absolute value of r
75  T beta = m_abs_new / abs_old; // calculate the Gram-Schmidt value used to create the new search direction
76  m_update = m_tmp + beta * m_update; // update search direction
77 
78  if (m_calcEigenvals)
79  {
80  m_gamma.push_back(-math::sqrt(beta)/alpha);
81  m_delta.push_back(beta/alpha);
82  }
83  return false;
84 }
85 
86 template<class T>
88 {
89  if ( m_delta.empty() )
90  {
91  gsWarn<< "Condition number needs eigenvalues set setCalcEigenvalues(true)"
92  " and call solve with an arbitrary right hand side";
93  return -1;
94  }
95  // If the condition number is calculated before the solver has ended,
96  // then we need to scale the last entry
97  if (m_error < m_tol)
98  {
99  gsLanczosMatrix<T> L(m_gamma,m_delta);
100  return L.maxEigenvalue()/L.minEigenvalue();
101  }
102  else
103  {
104  T tmp_original = m_delta.back();
105  m_mat->apply(m_update,m_tmp);
106  T alpha = m_abs_new / m_update.col(0).dot(m_tmp.col(0));
107  m_delta.back()+=(1./alpha);
108  gsLanczosMatrix<T> L(m_gamma,m_delta);
109  T result = L.maxEigenvalue()/L.minEigenvalue();
110  m_delta.back() = tmp_original;
111  return result;
112  }
113 }
114 
115 template<class T>
117 {
118  if ( m_delta.empty() )
119  {
120  gsWarn<< "Eigenvalues were not computed, set setCalcEigenvalues(true)"
121  " and call solve with an arbitrary right hand side";
122  eigs.clear();
123  return;
124  }
125 
126  gsLanczosMatrix<T> LM(m_gamma,m_delta);
127  gsSparseMatrix<T> L = LM.matrix();
128  // there is probably a better option...
129  typename gsMatrix<T>::SelfAdjEigenSolver eigensolver(L);
130  eigs = eigensolver.eigenvalues();
131 }
132 
133 
134 } // end namespace gismo
bool step(VectorType &x)
Perform one step, requires initIteration.
Definition: gsConjugateGradient.hpp:55
Class for representing a Lanczos matrix and calculating its eigenvalues.
Definition: gsLanczosMatrix.h:27
Class for representing a Lanczos matrix and calculating its eigenvalues.
#define index_t
Definition: gsConfig.h:32
T getConditionNumber()
returns the condition number of the (preconditioned) system matrix
Definition: gsConjugateGradient.hpp:87
bool initIteration(const VectorType &rhs, VectorType &x)
Init the iteration.
Definition: gsConjugateGradient.hpp:20
#define gsWarn
Definition: gsDebug.h:50
void getEigenvalues(VectorType &eigs)
returns the eigenvalues of the Lanczos matrix
Definition: gsConjugateGradient.hpp:116
T minEigenvalue(index_t maxIter=20, T tol=1.e-6)
Calculates the smallest eigenvalue.
Definition: gsLanczosMatrix.h:76
gsSparseMatrix< T > matrix()
This function returns the Lanczos matrix as gsSparseMatrix.
Definition: gsLanczosMatrix.h:88
T maxEigenvalue(index_t maxIter=20, T tol=1.e-6)
Calculates the largest eigenvalue.
Definition: gsLanczosMatrix.h:50