FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
bicgstabl.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
9#include <kernel/solver/iterative.hpp>
10
11namespace FEAT
12{
13 namespace Solver
14 {
15
21 {
22 left,
23 right
24 };
25
27
30 inline std::ostream& operator<<(std::ostream& os, BiCGStabLPreconVariant precon_variant)
31 {
32 switch(precon_variant)
33 {
34 case BiCGStabLPreconVariant::left:
35 return os << "left";
36 case BiCGStabLPreconVariant::right:
37 return os << "right";
38 default:
39 return os << "-unknown-";
40 }
41 }
42
43 inline std::istream& operator>>(std::istream& is, BiCGStabLPreconVariant& precon_variant)
44 {
45 String s;
46 if((is >> s).fail())
47 return is;
48
49 if(s.compare_no_case("left") == 0)
50 precon_variant = BiCGStabLPreconVariant::left;
51 else if(s.compare_no_case("right") == 0)
52 precon_variant = BiCGStabLPreconVariant::right;
53 else
54 is.setstate(std::ios_base::failbit);
55
56 return is;
57 }
58
60
92 template<typename Matrix_, typename Filter_>
93 class BiCGStabL :
94 public PreconditionedIterativeSolver<typename Matrix_::VectorTypeR>
95 {
96 public:
98 typedef Matrix_ MatrixType;
100 typedef Filter_ FilterType;
102 typedef typename MatrixType::VectorTypeR VectorType;
104 typedef typename MatrixType::DataType DataType;
109
110 protected:
115
122
124 std::vector<VectorType> _vec_uj_hat;
125
127 std::vector<VectorType> _vec_rj_hat;
128
131
133 int _l;
134
135 public:
154 explicit BiCGStabL(const MatrixType& matrix, const FilterType& filter,
155 int l = 2, //default parameter 2 (1 would lead to standard BiCGStab algorithm)
156 std::shared_ptr<PrecondType> precond = nullptr,
157 BiCGStabLPreconVariant precon_variant = BiCGStabLPreconVariant::left)
158 :
159 BaseClass("BiCGStab(" + stringify(l) +")", precond),
160 _system_matrix(matrix),
161 _system_filter(filter),
162 _precon_variant(precon_variant),
163 _l(l)
164 {
165 // we always need to compute defect norms
166 this->_force_def_norm_calc = true;
167
168 // set communicator by system matrix
169 this->_set_comm_by_matrix(matrix);
170 XASSERT(precon_variant == BiCGStabLPreconVariant::left || precon_variant == BiCGStabLPreconVariant::right);
171 XASSERTM(_l > 0, "bicgstabl polynomial degree must be greater than zero!");
172 }
173
174
195 explicit BiCGStabL(const String& section_name, const PropertyMap* section,
196 const MatrixType& matrix, const FilterType& filter,
197 std::shared_ptr<PrecondType> precond = nullptr)
198 :
199 BaseClass("BiCGStabL", section_name, section, precond),
200 _system_matrix(matrix),
201 _system_filter(filter),
203 {
204 // we always need to compute defect norms
205 this->_force_def_norm_calc = true;
206
207 // set communicator by system matrix
208 this->_set_comm_by_matrix(matrix);
209 // Check if we have set _p_variant
210 auto p_variant_p = section->query("precon_variant");
211 if(p_variant_p.second && !p_variant_p.first.parse(this->_precon_variant))
212 throw ParseError(section_name + ".precon_variant", p_variant_p.first, "one of: left, right");
213
214 //Check if we have set the solver parameter _l
215 std::pair<String , bool> l_pair = section->query("polynomial_degree");
216
217 int l_pm = 2; //use default l, if the parameter is not given
218 if (l_pair.second && (!l_pair.first.parse(l_pm) || (l_pm <= 0)))
219 throw ParseError(section_name + ".polynomial_degree", l_pair.first, "a positive integer");
220
221 this->_l = l_pm;
222 this->set_plot_name("BiCGStab(" + stringify(_l) + ")");
223 }
224
226 virtual String name() const override
227 {
228 return "BiCGStabL";
229 }
230
237 virtual void force_defect_norm_calc(bool DOXY(force)) override
238 {
239 // force is already applied in constructor
240 }
241
243 virtual void init_symbolic() override
244 {
246
247 // create all temporary vectors
248 _vec_r0_tilde = this->_system_matrix.create_vector_r();
249 _vec_u0 = this->_system_matrix.create_vector_r();
250 _vec_pc = this->_system_matrix.create_vector_r();
251
252 _vec_uj_hat.resize(Index(_l+1));
253 _vec_rj_hat.resize(Index(_l+1));
254 for (int i=0; i <= _l; i++)
255 {
256 _vec_rj_hat.at(Index(i)) = this->_system_matrix.create_vector_r();
257 _vec_uj_hat.at(Index(i)) = this->_system_matrix.create_vector_r();
258 }
259 }
260
262 virtual void done_symbolic() override
263 {
264 _vec_r0_tilde.clear();
265 _vec_u0.clear();
266 _vec_pc.clear();
267 for (int i=0; i <= _l; i++)
268 {
269 _vec_rj_hat.at(Index(i)).clear();
270 _vec_uj_hat.at(Index(i)).clear();
271 }
273 }
274
276 virtual Status correct(VectorType& vec_sol, const VectorType& vec_rhs) override
277 {
278 // compute initial defect
279 this->_system_matrix.apply(this->_vec_rj_hat.at(0), vec_sol, vec_rhs, -DataType(1));
280 this->_system_filter.filter_def(this->_vec_rj_hat.at(0));
281
282 // apply solver
283 this->_status = _apply_intern(vec_sol, vec_rhs);
284
285 // plot summary
286 this->plot_summary();
287
288 // return status
289 return this->_status;
290 }
291
293 virtual Status apply(VectorType& vec_cor, const VectorType& vec_def) override
294 {
295 // save rhs vector as initial defect
296 this->_vec_rj_hat.at(0).copy(vec_def);
297
298 // format solution vector
299 vec_cor.format();
300
301 // apply solver
302 this->_status = _apply_intern(vec_cor, vec_def);
303
304 // plot summary
305 this->plot_summary();
306
307 // return status
308 return this->_status;
309 }
310
311
318 virtual void set_precon_variant(BiCGStabLPreconVariant precon_variant)
319 {
320 XASSERT(precon_variant == BiCGStabLPreconVariant::left || precon_variant == BiCGStabLPreconVariant::right);
321 _precon_variant = precon_variant;
322 }
323
324 protected:
336 Status _apply_intern(VectorType& vec_sol, const VectorType& vec_rhs)
337 {
338 IterationStats pre_iter(*this);
339 Statistics::add_solver_expression(std::make_shared<ExpressionStartSolve>(this->name()));
340
341
342 int l (_l);
343
344 //choose vec_r0_tilde as vec_r0_hat (vec_rj_hat[0])
345 _vec_r0_tilde.copy(_vec_rj_hat.at(0));
346 _vec_uj_hat.at(0).format();
347
348 std::vector<DataType> tau ( Index( l*(l-1) ) , DataType(0)); //vector for tau_ij (j from 0 to l-1 , i from 0 to j-1, so LESS THAN HALF of the vector gets used)
349 //tau_ij = tau[j*(l-1) + i] (column major ordering)
350
351 std::vector<DataType> sigma ( Index(l) , DataType(0) ); //0-offset in implementation; 1-offset in pseudo-code
352 std::vector<DataType> gamma_j ( Index(l) , DataType(0) ); //0-offset in implementation; 1-offset in pseudo-code
353 std::vector<DataType> gamma_prime ( Index(l) , DataType(0) ); //0-offset in implementation; 1-offset in pseudo-code
354 std::vector<DataType> gamma_prime_prime ( Index(l) , DataType(0) ); //0-offset in implementation; 1-offset in pseudo-code
355
356 DataType rho_0(1), alpha(0), omega(1), rho_1(0), beta(0), gamma(0);
357
358
359 const MatrixType& mat_sys(this->_system_matrix);
360 const FilterType& fil_sys(this->_system_filter);
361 Status status(Status::progress);
362
363 // Compute initial defect
364 status = this->_set_initial_defect(_vec_rj_hat.at(0), vec_sol);
365
366 if (_precon_variant == BiCGStabLPreconVariant::left)
367 {
368 _vec_pc.copy(_vec_rj_hat.at(0));
369 if(!this->_apply_precond(_vec_rj_hat.at(0), _vec_pc, fil_sys))
370 {
371 Statistics::add_solver_expression(
372 std::make_shared<ExpressionEndSolve>(this->name(), Status::aborted, this->get_num_iter()));
373 return Status::aborted;
374 }
375 }
376
377
378 pre_iter.destroy();
379 while(status == Status::progress)
380 {
381 IterationStats stat(*this);
382 rho_0 *= (-omega);
383
384
385 for( int j(0); j < l ; j++)
386 {
387 rho_1 = _vec_rj_hat.at( Index(j) ).dot(_vec_r0_tilde);
388 beta = alpha * rho_1 / rho_0;
389 rho_0 = rho_1;
390 for ( int i(0) ; i <= j ; i++)
391 {
392 _vec_uj_hat.at(Index(i)).scale(_vec_uj_hat.at(Index(i)), -beta);
393 _vec_uj_hat.at(Index(i)).axpy(_vec_rj_hat.at( Index(i)));
394 }
395
396
397
398 if (_precon_variant == BiCGStabLPreconVariant::left)
399 {
400 mat_sys.apply(_vec_pc, _vec_uj_hat.at(Index(j)) );
401 fil_sys.filter_def(_vec_pc);
402 if(!this->_apply_precond(_vec_uj_hat.at( Index(j+1) ), _vec_pc, fil_sys))
403 {
404 Statistics::add_solver_expression(
405 std::make_shared<ExpressionEndSolve>(this->name(), Status::aborted, this->get_num_iter()));
406 return Status::aborted;
407 }
408 }
409 else
410 {
411 if(!this->_apply_precond(_vec_pc, _vec_uj_hat.at( Index(j) ), fil_sys))
412 {
413 Statistics::add_solver_expression(
414 std::make_shared<ExpressionEndSolve>(this->name(), Status::aborted, this->get_num_iter()));
415 return Status::aborted;
416 }
417 mat_sys.apply(_vec_uj_hat.at( Index(j+1) ), _vec_pc);
418 fil_sys.filter_def(_vec_uj_hat.at( Index(j+1) ));
419 }
420
421 gamma = _vec_uj_hat.at( Index(j+1) ).dot(_vec_r0_tilde);
422 alpha = rho_0 / gamma;
423
424 for ( int i(0) ; i <= j ; i++)
425 {
426 _vec_rj_hat.at(Index(i)).axpy(_vec_uj_hat.at( Index(i+1)), -alpha);
427 }
428
429 if (_precon_variant == BiCGStabLPreconVariant::left)
430 {
431
432 mat_sys.apply( _vec_pc, _vec_rj_hat.at(Index(j)) );
433 fil_sys.filter_def(_vec_pc);
434 if(!this->_apply_precond(_vec_rj_hat.at( Index(j+1) ) , _vec_pc, fil_sys))
435 {
436 Statistics::add_solver_expression(
437 std::make_shared<ExpressionEndSolve>(this->name(), Status::aborted, this->get_num_iter()));
438 return Status::aborted;
439 }
440 }
441 else
442 {
443 if(!this->_apply_precond(_vec_pc, _vec_rj_hat.at(Index(j)), fil_sys))
444 {
445 Statistics::add_solver_expression(
446 std::make_shared<ExpressionEndSolve>(this->name(), Status::aborted, this->get_num_iter()));
447 return Status::aborted;
448 }
449 mat_sys.apply(_vec_rj_hat.at(Index(j+1)), _vec_pc);
450 fil_sys.filter_def( _vec_rj_hat.at(Index(j+1)) );
451 }
452
453 vec_sol.axpy(_vec_uj_hat.at(0), alpha);
454 }
455 for ( int j(0) ; j < l ; j++) //changed counter in comparison to pseudo code
456 {
457
458 for ( int i(0); i<j ; i++) //changed counter
459 {
460 tau.at( Index(j*(l-1) + i) ) = ( _vec_rj_hat.at( Index(i+1) ).dot( _vec_rj_hat.at( Index(j+1) ) ) ) / sigma.at(Index(i));
461 _vec_rj_hat.at(Index(j+1)).axpy(_vec_rj_hat.at(Index(i+1)), -tau.at( Index(j*(l-1) + i)));
462 }
463 sigma.at(Index(j)) = _vec_rj_hat.at( Index(j+1) ).dot( _vec_rj_hat.at(Index(j+1)) );
464 gamma_prime.at(Index(j)) = ( _vec_rj_hat.at(0).dot( _vec_rj_hat.at(Index(j+1)) ) ) / sigma.at(Index(j));
465 }
466 gamma_j.at(Index(l-1)) = gamma_prime.at(Index(l-1));
467 omega = gamma_j.at(Index(l-1));
468
469 for ( int j(l-2) ; j >= 0 ; j--) //changed counter
470 {
471 gamma_j.at(Index(j)) = gamma_prime.at(Index(j));
472 for ( int i(j+1) ; i < l ; i++)
473 {
474 gamma_j.at(Index(j)) -= tau.at( Index(i*(l-1) + j) ) * gamma_j.at(Index(i));
475 }
476 }
477
478 for ( int j(0); j < l-1 ; j++) //changed counter
479 {
480 gamma_prime_prime.at( Index(j) ) = gamma_j.at( Index(j+1) );
481 for ( int i(j+1) ; i < l-1 ; i++) //changed counter
482 {
483 gamma_prime_prime.at(Index(j)) += tau.at(Index(i*(l-1) + j)) * gamma_j.at(Index(i+1));
484 }
485 }
486 vec_sol.axpy(_vec_rj_hat.at(0), gamma_j.at(0));
487 _vec_rj_hat.at(0).axpy(_vec_rj_hat.at(Index(l)), -gamma_prime.at(Index(l-1)));
488 _vec_uj_hat.at(0).axpy(_vec_uj_hat.at(Index(l)), -gamma_j.at(Index(l-1)));
489
490 for ( int j(1) ; j<l; j++)
491 {
492 _vec_uj_hat.at(0).axpy(_vec_uj_hat.at(Index(j)), -gamma_j.at(Index(j-1)));
493 vec_sol.axpy(_vec_rj_hat.at(Index(j)), gamma_prime_prime.at(Index(j-1)));
494 _vec_rj_hat.at(0).axpy(_vec_rj_hat.at(Index(j)), -gamma_prime.at(Index(j-1)));
495 }
496 // Compute defect norm
497 if (_precon_variant == BiCGStabLPreconVariant::left)
498 {
499 mat_sys.apply(_vec_pc, vec_sol);
500 fil_sys.filter_def(_vec_pc);
501 _vec_pc.axpy( vec_rhs, -1);
502 fil_sys.filter_def(_vec_pc);
503 status = this->_set_new_defect(_vec_pc, vec_sol);
504 }
505 else
506 {
507 status = this->_set_new_defect(_vec_rj_hat.at(0), vec_sol);
508 }
509
510 if(status != Status::progress)
511 {
512 stat.destroy();
513 Statistics::add_solver_expression(
514 std::make_shared<ExpressionEndSolve>(this->name(), status, this->get_num_iter()));
515 if (_precon_variant == BiCGStabLPreconVariant::right)
516 {
517 if(!this->_apply_precond(_vec_pc, vec_sol, fil_sys))
518 {
519 Statistics::add_solver_expression(
520 std::make_shared<ExpressionEndSolve>(this->name(), Status::aborted, this->get_num_iter()));
521 return Status::aborted;
522 }
523 vec_sol.copy(_vec_pc);
524 }
525 return status;
526 }
527
528 }
529 // we should never reach this point...
530 Statistics::add_solver_expression(
531 std::make_shared<ExpressionEndSolve>(this->name(), Status::undefined, this->get_num_iter()));
532 return Status::undefined;
533 }
534 };
535
557 template<typename Matrix_, typename Filter_>
558 inline std::shared_ptr<BiCGStabL<Matrix_, Filter_>> new_bicgstabl(
559 const Matrix_& matrix, const Filter_& filter, int l = 2,
560 std::shared_ptr<SolverBase<typename Matrix_::VectorTypeL>> precond = nullptr,
561 BiCGStabLPreconVariant precon_variant = BiCGStabLPreconVariant::left)
562 {
563 return std::make_shared<BiCGStabL<Matrix_, Filter_>>(matrix, filter, l, precond, precon_variant);
564 }
565
587 template<typename Matrix_, typename Filter_>
588 inline std::shared_ptr<BiCGStabL<Matrix_, Filter_>> new_bicgstabl(
589 const String& section_name, const PropertyMap* section,
590 const Matrix_& matrix, const Filter_& filter,
591 std::shared_ptr<SolverBase<typename Matrix_::VectorTypeL>> precond = nullptr)
592 {
593 return std::make_shared<BiCGStabL<Matrix_, Filter_>>(section_name, section, matrix, filter, precond);
594 }
595
596 } // namespace Solver
597} // namespace FEAT
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Class for parser related errors.
Definition: exception.hpp:132
A class organizing a tree of key-value pairs.
std::pair< String, bool > query(String key_path) const
Queries a value by its key path.
(Preconditioned) BiCGStab(l) solver implementation
Definition: bicgstabl.hpp:95
virtual Status correct(VectorType &vec_sol, const VectorType &vec_rhs) override
Solver correction method.
Definition: bicgstabl.hpp:276
Filter_ FilterType
The filter to apply.
Definition: bicgstabl.hpp:100
virtual void done_symbolic() override
Symbolic finalization method.
Definition: bicgstabl.hpp:262
BiCGStabL(const MatrixType &matrix, const FilterType &filter, int l=2, std::shared_ptr< PrecondType > precond=nullptr, BiCGStabLPreconVariant precon_variant=BiCGStabLPreconVariant::left)
Constructor.
Definition: bicgstabl.hpp:154
VectorType _vec_r0_tilde
arbitrary vector for the algorithm
Definition: bicgstabl.hpp:117
std::vector< VectorType > _vec_uj_hat
vector 'list' for the algorithm (size = l+1);
Definition: bicgstabl.hpp:124
VectorType _vec_pc
auxiliary vector for preconditioning
Definition: bicgstabl.hpp:121
virtual void init_symbolic() override
Symbolic initialization method.
Definition: bicgstabl.hpp:243
virtual String name() const override
Returns a descriptive string.
Definition: bicgstabl.hpp:226
virtual void force_defect_norm_calc(bool force) override
Forces the calculation of defect norms in every iteration (overridden)
Definition: bicgstabl.hpp:237
int _l
Parameter l configuring the solver.
Definition: bicgstabl.hpp:133
MatrixType::VectorTypeR VectorType
The vector type this solver can be applied to.
Definition: bicgstabl.hpp:102
Matrix_ MatrixType
The matrix type this solver can be applied to.
Definition: bicgstabl.hpp:98
virtual Status apply(VectorType &vec_cor, const VectorType &vec_def) override
Solver application method.
Definition: bicgstabl.hpp:293
VectorType _vec_u0
vector for the algorithm
Definition: bicgstabl.hpp:119
BiCGStabL(const String &section_name, const PropertyMap *section, const MatrixType &matrix, const FilterType &filter, std::shared_ptr< PrecondType > precond=nullptr)
Constructor using a PropertyMap.
Definition: bicgstabl.hpp:195
const MatrixType & _system_matrix
the matrix for the solver
Definition: bicgstabl.hpp:112
BiCGStabLPreconVariant _precon_variant
Precondition from left or right?
Definition: bicgstabl.hpp:130
Status _apply_intern(VectorType &vec_sol, const VectorType &vec_rhs)
Internal function, applies the solver.
Definition: bicgstabl.hpp:336
virtual void set_precon_variant(BiCGStabLPreconVariant precon_variant)
Sets the preconditioning variant (left or right)
Definition: bicgstabl.hpp:318
MatrixType::DataType DataType
The floating point precision.
Definition: bicgstabl.hpp:104
SolverBase< VectorType > PrecondType
The type of the preconditioner.
Definition: bicgstabl.hpp:108
std::vector< VectorType > _vec_rj_hat
vector 'list' for the algorithm (size = l+1); r[0] is the residual vector of the preconditioned syste...
Definition: bicgstabl.hpp:127
const FilterType & _system_filter
the filter for the solver
Definition: bicgstabl.hpp:114
PreconditionedIterativeSolver< VectorType > BaseClass
Our base class.
Definition: bicgstabl.hpp:106
Helper class for iteration statistics collection.
Definition: base.hpp:392
void destroy()
destroy the objects contents (and generate Statistics::expression) before the actual destructor call
Definition: base.hpp:464
bool _force_def_norm_calc
whether skipping of defect computation is allowed or not
Definition: iterative.hpp:249
void set_plot_name(const String &plot_name)
Sets the plot name of the solver.
Definition: iterative.hpp:517
Index get_num_iter() const
Returns number of performed iterations.
Definition: iterative.hpp:462
Status _status
current status of the solver
Definition: iterative.hpp:213
void _set_comm_by_matrix(const Matrix_ &matrix)
Sets the communicator for the solver from a matrix.
Definition: iterative.hpp:680
virtual Status _set_new_defect(const VectorType &vec_def, const VectorType &vec_sol)
Internal function: sets the new (next) defect vector.
Definition: iterative.hpp:924
virtual void plot_summary() const
Plot a summary of the last solver run.
Definition: iterative.hpp:627
virtual Status _set_initial_defect(const VectorType &vec_def, const VectorType &vec_sol)
Internal function: sets the initial defect vector.
Definition: iterative.hpp:802
Abstract base-class for preconditioned iterative solvers.
Definition: iterative.hpp:1027
virtual void init_symbolic() override
Symbolic initialization method.
Definition: iterative.hpp:1086
bool _apply_precond(VectorType &vec_cor, const VectorType &vec_def, const Filter_ &filter)
Applies the preconditioner onto a defect vector.
Definition: iterative.hpp:1140
virtual void done_symbolic() override
Symbolic finalization method.
Definition: iterative.hpp:1110
Polymorphic solver interface.
Definition: base.hpp:183
String class implementation.
Definition: string.hpp:46
std::istream & operator>>(std::istream &is, Pack::Type &t)
stream input operator for Pack::Type
Definition: pack.hpp:189
std::shared_ptr< BiCGStabL< Matrix_, Filter_ > > new_bicgstabl(const Matrix_ &matrix, const Filter_ &filter, int l=2, std::shared_ptr< SolverBase< typename Matrix_::VectorTypeL > > precond=nullptr, BiCGStabLPreconVariant precon_variant=BiCGStabLPreconVariant::left)
Creates a new BiCGStabL solver object.
Definition: bicgstabl.hpp:558
Status
Solver status return codes enumeration.
Definition: base.hpp:47
@ progress
continue iteration (internal use only)
@ undefined
undefined status
@ aborted
premature abort (solver aborted due to internal errors or preconditioner failure)
BiCGStabLPreconVariant
Enum for diffent preconditioning variants for BiCGStabL.
Definition: bicgstabl.hpp:21
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944
std::uint64_t Index
Index data type.