G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsIterativeSolver.h
Go to the documentation of this file.
1
13#pragma once
14
15#include <gsCore/gsExport.h>
17#include <gsSolver/gsMatrixOp.h>
18#include <gsIO/gsOptionList.h>
19
20namespace gismo
21{
25template<class T=real_t>
27{
28public:
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
251protected:
252 const LinOpPtr m_mat;
253 LinOpPtr m_precond;
255 gsOptionList::Real m_tol;
259};
260
263template<class T>
264std::ostream &operator<<(std::ostream &os, const gsIterativeSolver<T>& b)
265{return b.print(os); }
266
268template <class SolverType>
269class gsIterativeSolverOp GISMO_FINAL : public gsLinearOperator<typename SolverType::ScalarType>
270{
271 typedef typename SolverType::ScalarType T;
272 typedef typename gsLinearOperator<T>::Ptr LinOpPtr;
273public:
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
314private:
315 mutable SolverType m_solver; // The iterative solvers change their state during solving
316};
317
318
319} // namespace gismo
Creates a mapped object or data pointer to a vector without copying data.
Definition gsAsMatrix.h:239
static uPtr make(index_t dim)
Make function returning a smart pointer.
Definition gsLinearOperator.h:132
This wrapper class allows gsIterativeSolver to be used as gsLinearOperator.
Definition gsIterativeSolver.h:270
const SolverType & solver() const
Access the solver class.
Definition gsIterativeSolver.h:312
index_t rows() const
Returns the number of rows of the operator.
Definition gsIterativeSolver.h:304
void apply(const gsMatrix< T > &input, gsMatrix< T > &res) const
apply the operator on the input vector and store the result in x
Definition gsIterativeSolver.h:293
gsIterativeSolverOp(const MatrixType &matrix, const LinOpPtr &preconditioner=LinOpPtr())
Constructor taking the underlying matrix/operator and the preconditioner.
Definition gsIterativeSolver.h:282
static uPtr make(const MatrixType &matrix, const LinOpPtr &preconditioner=LinOpPtr())
Make function taking the underlying matrix/operator and the preconditioner.
Definition gsIterativeSolver.h:287
static uPtr make(SolverType solver)
Make function taking a matrix OR a shared pointer.
Definition gsIterativeSolver.h:291
index_t cols() const
Returns the number of columns of the operator.
Definition gsIterativeSolver.h:306
SolverType & solver()
Access the solver class.
Definition gsIterativeSolver.h:309
memory::shared_ptr< gsIterativeSolverOp > Ptr
Shared pointer for gsIterativeSolverOp.
Definition gsIterativeSolver.h:275
memory::unique_ptr< gsIterativeSolverOp > uPtr
Unique pointer for gsIterativeSolverOp.
Definition gsIterativeSolver.h:278
Abstract class for iterative solvers.
Definition gsIterativeSolver.h:27
virtual gsIterativeSolver & setOptions(const gsOptionList &opt)
Set the options based on a gsOptionList.
Definition gsIterativeSolver.h:102
index_t iterations() const
The number of iterations needed to reach the error criteria.
Definition gsIterativeSolver.h:226
virtual void finalizeIteration(VectorType &)
Some post-processing might be required.
Definition gsIterativeSolver.h:205
void setMaxIterations(index_t max_iters)
Set the maximum number of iterations (default: 1000)
Definition gsIterativeSolver.h:220
T m_rhs_norm
The norm of the right-hand-side.
Definition gsIterativeSolver.h:257
T tolerance() const
The chosen tolerance for the error criteria on the relative residual error.
Definition gsIterativeSolver.h:235
T m_error
The relative error as absolute_error/m_rhs_norm.
Definition gsIterativeSolver.h:258
void setTolerance(T tol)
Set the tolerance for the error criteria on the relative residual error (default: 1e-10)
Definition gsIterativeSolver.h:223
void solve(const VectorType &rhs, VectorType &x)
Solves the linear system and stores the solution in x.
Definition gsIterativeSolver.h:114
virtual std::ostream & print(std::ostream &os) const =0
Prints the object as a string.
gsIterativeSolver(const LinOpPtr &mat, const LinOpPtr &precond)
Contructor using a linear operator to be solved for and a preconditioner.
Definition gsIterativeSolver.h:41
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 size() const
Returns the size of the linear system.
Definition gsIterativeSolver.h:208
LinOpPtr underlying() const
Get the underlying matrix/operator to be solved for.
Definition gsIterativeSolver.h:217
virtual bool step(VectorType &x)=0
Perform one step, requires initIteration.
LinOpPtr m_precond
The preconditioner.
Definition gsIterativeSolver.h:253
std::ostream & operator<<(std::ostream &os, const gsIterativeSolver< T > &b)
Print (as string) operator for iterative solvers.
Definition gsIterativeSolver.h:264
LinOpPtr preconditioner() const
Get the preconditioner.
Definition gsIterativeSolver.h:214
void setPreconditioner(const LinOpPtr &precond)
Set the preconditionner.
Definition gsIterativeSolver.h:211
T error() const
The relative residual error of the current iterate.
Definition gsIterativeSolver.h:232
gsIterativeSolver(const gsEigen::EigenBase< Derived > &mat, const LinOpPtr &precond)
Contructor using any dense or sparse matrix and a preconditioner.
Definition gsIterativeSolver.h:71
static gsOptionList defaultOptions()
Returns a list of default options.
Definition gsIterativeSolver.h:92
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
index_t m_num_iter
The number of iterations performed.
Definition gsIterativeSolver.h:256
virtual std::string detail() const
Prints the object as a string with extended details.
Definition gsIterativeSolver.h:241
index_t m_max_iters
The upper bound for the number of iterations.
Definition gsIterativeSolver.h:254
const LinOpPtr m_mat
The matrix/operator to be solved for.
Definition gsIterativeSolver.h:252
Simple abstract class for discrete operators.
Definition gsLinearOperator.h:29
memory::shared_ptr< gsLinearOperator > Ptr
Shared pointer for gsLinearOperator.
Definition gsLinearOperator.h:33
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
Class which holds a list of parameters/options, and provides easy access to them.
Definition gsOptionList.h:33
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
Real askReal(const std::string &label, const Real &value=0) const
Reads value for option label from options.
Definition gsOptionList.cpp:139
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
index_t askInt(const std::string &label, const index_t &value=0) const
Reads value for option label from options.
Definition gsOptionList.cpp:117
#define index_t
Definition gsConfig.h:32
#define gsDebug
Definition gsDebug.h:61
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Handles shared library creation and other class attributes.
This is the main header file that collects wrappers of Eigen for linear algebra.
Simple adapter classes to use matrices or linear solvers as gsLinearOperators.
Provides a list of labeled parameters/options that can be set and accessed easily.
unique_ptr< T > make_unique(T *x)
Definition gsMemory.h:198
The G+Smo namespace, containing all definitions for the library.