G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsIterativeSolver.h
Go to the documentation of this file.
1 
13 #pragma once
14 
15 #include <gsCore/gsExport.h>
16 #include <gsCore/gsLinearAlgebra.h>
17 #include <gsSolver/gsMatrixOp.h>
18 #include <gsIO/gsOptionList.h>
19 
20 namespace gismo
21 {
25 template<class T=real_t>
27 {
28 public:
29  typedef memory::shared_ptr<gsIterativeSolver> Ptr;
30  typedef memory::unique_ptr<gsIterativeSolver> uPtr;
31  typedef T ScalarType;
32  typedef gsMatrix<T> VectorType;
33  typedef typename gsLinearOperator<T>::Ptr LinOpPtr;
34 
41  gsIterativeSolver( const LinOpPtr& mat,
42  const LinOpPtr& precond)
43  : m_mat(mat),
44  m_precond(precond),
45  m_max_iters(1000),
46  m_tol(1e-10),
47  m_num_iter(-1),
48  m_rhs_norm(-1),
49  m_error(-1)
50  {
51  GISMO_ASSERT(m_mat->rows() == m_mat->cols(), "The matrix is not square." );
52 
54  GISMO_ASSERT(m_precond->rows() == m_precond->cols(), "The preconditioner is not square." );
55  GISMO_ASSERT(m_precond->rows() == m_mat->rows(), "The preconditioner does not match the matrix: "
56  <<m_precond->rows()<<"!="<<m_mat->rows() );
57  }
58 
70  template<typename Derived>
71  gsIterativeSolver( const gsEigen::EigenBase<Derived> & mat,
72  const LinOpPtr& precond)
73  : m_mat(makeMatrixOp(mat.derived())),
74  m_precond(precond),
75  m_max_iters(1000),
76  m_tol(1e-10),
77  m_num_iter(-1),
78  m_rhs_norm(-1),
79  m_error(-1)
80  {
81  GISMO_ASSERT(m_mat->rows() == m_mat->cols(), "The matrix is not square." );
82 
84  GISMO_ASSERT(m_precond->rows() == m_precond->cols(), "The preconditioner is not square." );
85  GISMO_ASSERT(m_precond->rows() == m_mat->rows(), "The preconditioner does not match the matrix: "
86  <<m_precond->rows()<<"!="<<m_mat->rows() );
87  }
88 
89  virtual ~gsIterativeSolver() {}
90 
93  {
94  gsOptionList opt;
95  opt.addInt ("MaxIterations" , "Maximum number of iterations", 1000 );
96  opt.addReal ("Tolerance" , "Tolerance for the error criteria on the "
97  "relative residual error", 1e-10 );
98  return opt;
99  }
100 
103  {
104  m_max_iters = opt.askInt ("MaxIterations" , m_max_iters );
105  m_tol = opt.askReal ("Tolerance" , m_tol );
106  return *this;
107  }
108 
114  void solve( const VectorType& rhs, VectorType& x )
115  {
116  if (initIteration(rhs, x)) return;
117 
118  while (m_num_iter < m_max_iters)
119  {
120  m_num_iter++;
121  if (step(x)) break;
122  }
123 
125  }
126 
134  void solveDetailed( const VectorType& rhs, VectorType& x, VectorType& error_history )
135  {
136  if (initIteration(rhs, x))
137  {
138  error_history.resize(1,1); //VectorType is actually gsMatrix
139  error_history(0,0) = m_error;
140  //gsDebug<<"Solution reached at iteration 0, err="<<m_error<<"\n";
141  return;
142  }
143 
144  std::vector<T> tmp_error_hist;
145  tmp_error_hist.clear();
146  tmp_error_hist.reserve(m_max_iters / 3 );
147  tmp_error_hist.push_back(m_error); // store initial error (as provided by initIteration)
148 
149  while (m_num_iter < m_max_iters)
150  {
151  m_num_iter++;
152  //gsDebug<<"Iteration : "<<std::setw(5)<<std::left<< m_num_iter<<"\n";
153 
154  if (step(x))
155  {
156  tmp_error_hist.push_back(m_error);
157  //gsDebug<<" err = "<<m_error<<" --> Solution reached.\n";
158  break;
159  }
160 
161  tmp_error_hist.push_back(m_error);
162  //gsDebug<<" err = "<<m_error<<"\n";
163  }
164 
165  //if (m_num_iter == m_max_iters) gsDebug<<"Maximum number of iterations reached.\n";
166 
168  error_history = gsAsVector<T>(tmp_error_hist);
169  }
170 
172  virtual bool initIteration( const VectorType& rhs, VectorType& x )
173  {
174  GISMO_ASSERT( rhs.cols() == 1,
175  "Iterative solvers only work for single column right-hand side." );
176  GISMO_ASSERT( rhs.rows() == m_mat->rows(),
177  "The right-hand side does not match the matrix: "
178  << rhs.rows() <<"!="<< m_mat->rows() );
179 
180  m_num_iter = 0;
181 
182  m_rhs_norm = rhs.norm();
183 
184  if (0 == m_rhs_norm) // special case of zero rhs
185  {
186  x.setZero(rhs.rows(),rhs.cols()); // for sure zero is a solution
187  m_error = 0.;
188  return true; // iteration is finished
189  }
190 
191  if ( 0 == x.size() ) // if no initial solution, start with zeros
192  x.setZero(rhs.rows(), rhs.cols());
193  else
194  {
195  GISMO_ASSERT( x.cols() == 1,
196  "Iterative solvers only work for single right-hand side and solution." );
197  GISMO_ASSERT( x.rows() == m_mat->cols(),
198  "The initial guess does not match the matrix: "
199  << x.rows() <<"!="<< m_mat->cols() );
200  }
201  return false; // iteration is not finished
202  }
203 
204  virtual bool step( VectorType& x ) = 0;
205  virtual void finalizeIteration( VectorType& ) {}
206 
208  index_t size() const { return m_mat->rows(); }
209 
211  void setPreconditioner(const LinOpPtr & precond) { m_precond = precond; }
212 
214  LinOpPtr preconditioner() const { return m_precond; }
215 
217  LinOpPtr underlying() const { return m_mat; }
218 
220  void setMaxIterations(index_t max_iters) { m_max_iters = max_iters; }
221 
223  void setTolerance(T tol) { m_tol = tol; }
224 
226  index_t iterations() const { return m_num_iter; }
227 
232  T error() const { return m_error; }
233 
235  T tolerance() const { return m_tol; }
236 
238  virtual std::ostream &print(std::ostream &os) const = 0;
239 
241  virtual std::string detail() const
242  {
243  std::ostringstream os;
244  print(os);
245  os << " Tolerance : " << tolerance() << "\n";
246  os << " Solver error : " << error() << "\n";
247  os << " Number of iterations : " << iterations() << " (max="<<m_max_iters<<")\n";
248  return os.str();
249  }
250 
251 protected:
252  const LinOpPtr m_mat;
253  LinOpPtr m_precond;
255  gsOptionList::Real m_tol;
259 };
260 
263 template<class T>
264 std::ostream &operator<<(std::ostream &os, const gsIterativeSolver<T>& b)
265 {return b.print(os); }
266 
268 template <class SolverType>
269 class gsIterativeSolverOp GISMO_FINAL : public gsLinearOperator<typename SolverType::ScalarType>
270 {
271  typedef typename SolverType::ScalarType T;
272  typedef typename gsLinearOperator<T>::Ptr LinOpPtr;
273 public:
275  typedef memory::shared_ptr<gsIterativeSolverOp> Ptr;
276 
278  typedef memory::unique_ptr<gsIterativeSolverOp> uPtr;
279 
281  template<class MatrixType>
282  gsIterativeSolverOp(const MatrixType& matrix, const LinOpPtr& preconditioner = LinOpPtr())
283  : m_solver(matrix, preconditioner) {}
284 
286  template<class MatrixType>
287  static uPtr make(const MatrixType& matrix, const LinOpPtr& preconditioner = LinOpPtr())
288  { return uPtr( new gsIterativeSolverOp(matrix,preconditioner) ); }
289 
291  static uPtr make(SolverType solver) { return memory::make_unique( new gsIterativeSolverOp(solver) ); }
292 
293  void apply(const gsMatrix<T> & input, gsMatrix<T> & res) const
294  {
295  res.setZero(input.rows(), input.cols());
296  m_solver.solve(input, res);
297  gsDebug << ( (m_solver.error() < m_solver.tolerance())
298  ? "gsIterativeSolverOp reached desired error bound after "
299  : "msIterativeSolverOp did not reach desired error bound within " )
300  << m_solver.iterations() << " iterations.\n";
301  gsDebug << input.rows() << "; " << input.norm() << "; " << res.norm() << "\n";
302  }
303 
304  index_t rows() const { return m_solver.underlying()->rows(); }
305 
306  index_t cols() const { return m_solver.underlying()->cols(); }
307 
309  SolverType& solver() { return m_solver; }
310 
312  const SolverType& solver() const { return m_solver; }
313 
314 private:
315  mutable SolverType m_solver; // The iterative solvers change their state during solving
316 };
317 
318 
319 } // namespace gismo
const LinOpPtr m_mat
The matrix/operator to be solved for.
Definition: gsIterativeSolver.h:252
unique_ptr< T > make_unique(T *x)
Definition: gsMemory.h:198
void solve(const VectorType &rhs, VectorType &x)
Solves the linear system and stores the solution in x.
Definition: gsIterativeSolver.h:114
index_t size() const
Returns the size of the linear system.
Definition: gsIterativeSolver.h:208
virtual gsIterativeSolver & setOptions(const gsOptionList &opt)
Set the options based on a gsOptionList.
Definition: gsIterativeSolver.h:102
virtual bool step(VectorType &x)=0
Perform one step, requires initIteration.
memory::unique_ptr< gsIterativeSolverOp > uPtr
Unique pointer for gsIterativeSolverOp.
Definition: gsIterativeSolver.h:278
#define gsDebug
Definition: gsDebug.h:61
virtual bool initIteration(const VectorType &rhs, VectorType &x)
Init the iteration.
Definition: gsIterativeSolver.h:172
gsOptionList::Real m_tol
The tolerance for m_error to be reached.
Definition: gsIterativeSolver.h:255
void setPreconditioner(const LinOpPtr &precond)
Set the preconditionner.
Definition: gsIterativeSolver.h:211
virtual index_t rows() const =0
Returns the number of rows of the operator.
static uPtr make(index_t dim)
Make function returning a smart pointer.
Definition: gsLinearOperator.h:132
#define index_t
Definition: gsConfig.h:32
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
LinOpPtr preconditioner() const
Get the preconditioner.
Definition: gsIterativeSolver.h:214
Handles shared library creation and other class attributes.
LinOpPtr underlying() const
Get the underlying matrix/operator to be solved for.
Definition: gsIterativeSolver.h:217
T m_rhs_norm
The norm of the right-hand-side.
Definition: gsIterativeSolver.h:257
void addInt(const std::string &label, const std::string &desc, const index_t &value)
Adds a option named label, with description desc and value value.
Definition: gsOptionList.cpp:201
Creates a mapped object or data pointer to a vector without copying data.
Definition: gsLinearAlgebra.h:129
Provides a list of labeled parameters/options that can be set and accessed easily.
memory::shared_ptr< gsLinearOperator > Ptr
Shared pointer for gsLinearOperator.
Definition: gsLinearOperator.h:33
static gsOptionList defaultOptions()
Returns a list of default options.
Definition: gsIterativeSolver.h:92
void solveDetailed(const VectorType &rhs, VectorType &x, VectorType &error_history)
Solves the linear system and stores the solution in x and records the error histroy.
Definition: gsIterativeSolver.h:134
index_t m_max_iters
The upper bound for the number of iterations.
Definition: gsIterativeSolver.h:254
void setTolerance(T tol)
Set the tolerance for the error criteria on the relative residual error (default: 1e-10) ...
Definition: gsIterativeSolver.h:223
T m_error
The relative error as absolute_error/m_rhs_norm.
Definition: gsIterativeSolver.h:258
Real askReal(const std::string &label, const Real &value=0) const
Reads value for option label from options.
Definition: gsOptionList.cpp:139
void setMaxIterations(index_t max_iters)
Set the maximum number of iterations (default: 1000)
Definition: gsIterativeSolver.h:220
virtual std::ostream & print(std::ostream &os) const =0
Prints the object as a string.
Simple abstract class for discrete operators.
Definition: gsLinearOperator.h:28
T tolerance() const
The chosen tolerance for the error criteria on the relative residual error.
Definition: gsIterativeSolver.h:235
index_t askInt(const std::string &label, const index_t &value=0) const
Reads value for option label from options.
Definition: gsOptionList.cpp:117
void addReal(const std::string &label, const std::string &desc, const Real &value)
Adds a option named label, with description desc and value value.
Definition: gsOptionList.cpp:211
virtual std::string detail() const
Prints the object as a string with extended details.
Definition: gsIterativeSolver.h:241
memory::shared_ptr< gsIterativeSolverOp > Ptr
Shared pointer for gsIterativeSolverOp.
Definition: gsIterativeSolver.h:275
index_t iterations() const
The number of iterations needed to reach the error criteria.
Definition: gsIterativeSolver.h:226
This is the main header file that collects wrappers of Eigen for linear algebra.
virtual void apply(const gsMatrix< SolverType::ScalarType > &input, gsMatrix< SolverType::ScalarType > &x) const =0
apply the operator on the input vector and store the result in x
virtual index_t cols() const =0
Returns the number of columns of the operator.
Abstract class for iterative solvers.
Definition: gsIterativeSolver.h:26
Class which holds a list of parameters/options, and provides easy access to them. ...
Definition: gsOptionList.h:32
gsIterativeSolver(const LinOpPtr &mat, const LinOpPtr &precond)
Contructor using a linear operator to be solved for and a preconditioner.
Definition: gsIterativeSolver.h:41
gsIterativeSolver(const gsEigen::EigenBase< Derived > &mat, const LinOpPtr &precond)
Contructor using any dense or sparse matrix and a preconditioner.
Definition: gsIterativeSolver.h:71
T error() const
The relative residual error of the current iterate.
Definition: gsIterativeSolver.h:232
This wrapper class allows gsIterativeSolver to be used as gsLinearOperator.
Definition: gsIterativeSolver.h:269
Simple adapter classes to use matrices or linear solvers as gsLinearOperators.
virtual void finalizeIteration(VectorType &)
Some post-processing might be required.
Definition: gsIterativeSolver.h:205
index_t m_num_iter
The number of iterations performed.
Definition: gsIterativeSolver.h:256
LinOpPtr m_precond
The preconditioner.
Definition: gsIterativeSolver.h:253