oomph::BiCGStab< MATRIX > Class Template Reference

The conjugate gradient method. More...

#include <iterative_linear_solver.h>

+ Inheritance diagram for oomph::BiCGStab< MATRIX >:

Public Member Functions

 BiCGStab ()
 Constructor. More...
 
virtual ~BiCGStab ()
 Destructor (cleanup storage) More...
 
 BiCGStab (const BiCGStab &)=delete
 Broken copy constructor. More...
 
void operator= (const BiCGStab &)=delete
 Broken assignment operator. More...
 
void disable_resolve ()
 Overload disable resolve so that it cleans up memory too. More...
 
void solve (Problem *const &problem_pt, DoubleVector &result)
 
void solve (DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
 
void solve (DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
 
void resolve (const DoubleVector &rhs, DoubleVector &result)
 
unsigned iterations () const
 Number of iterations taken. More...
 
- Public Member Functions inherited from oomph::IterativeLinearSolver
 IterativeLinearSolver ()
 
 IterativeLinearSolver (const IterativeLinearSolver &)=delete
 Broken copy constructor. More...
 
void operator= (const IterativeLinearSolver &)=delete
 Broken assignment operator. More...
 
virtual ~IterativeLinearSolver ()
 Destructor (empty) More...
 
Preconditioner *& preconditioner_pt ()
 Access function to preconditioner. More...
 
Preconditioner *const & preconditioner_pt () const
 Access function to preconditioner (const version) More...
 
doubletolerance ()
 Access to convergence tolerance. More...
 
unsignedmax_iter ()
 Access to max. number of iterations. More...
 
void enable_doc_convergence_history ()
 Enable documentation of the convergence history. More...
 
void disable_doc_convergence_history ()
 Disable documentation of the convergence history. More...
 
void open_convergence_history_file_stream (const std::string &file_name, const std::string &zone_title="")
 
void close_convergence_history_file_stream ()
 Close convergence history output stream. More...
 
double jacobian_setup_time () const
 
double linear_solver_solution_time () const
 return the time taken to solve the linear system More...
 
virtual double preconditioner_setup_time () const
 returns the the time taken to setup the preconditioner More...
 
void enable_setup_preconditioner_before_solve ()
 Setup the preconditioner before the solve. More...
 
void disable_setup_preconditioner_before_solve ()
 Don't set up the preconditioner before the solve. More...
 
void enable_error_after_max_iter ()
 Throw an error if we don't converge within max_iter. More...
 
void disable_error_after_max_iter ()
 Don't throw an error if we don't converge within max_iter (default). More...
 
void enable_iterative_solver_as_preconditioner ()
 
void disable_iterative_solver_as_preconditioner ()
 
- Public Member Functions inherited from oomph::LinearSolver
 LinearSolver ()
 Empty constructor, initialise the member data. More...
 
 LinearSolver (const LinearSolver &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const LinearSolver &)=delete
 Broken assignment operator. More...
 
virtual ~LinearSolver ()
 Empty virtual destructor. More...
 
void enable_doc_time ()
 Enable documentation of solve times. More...
 
void disable_doc_time ()
 Disable documentation of solve times. More...
 
bool is_doc_time_enabled () const
 Is documentation of solve times enabled? More...
 
bool is_resolve_enabled () const
 Boolean flag indicating if resolves are enabled. More...
 
virtual void enable_resolve ()
 
virtual void solve_transpose (Problem *const &problem_pt, DoubleVector &result)
 
virtual void solve_transpose (DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &result)
 
virtual void solve_transpose (DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
 
virtual void resolve_transpose (const DoubleVector &rhs, DoubleVector &result)
 
virtual void enable_computation_of_gradient ()
 
void disable_computation_of_gradient ()
 
void reset_gradient ()
 
void get_gradient (DoubleVector &gradient)
 function to access the gradient, provided it has been computed More...
 
- Public Member Functions inherited from oomph::DistributableLinearAlgebraObject
 DistributableLinearAlgebraObject ()
 Default constructor - create a distribution. More...
 
 DistributableLinearAlgebraObject (const DistributableLinearAlgebraObject &matrix)=delete
 Broken copy constructor. More...
 
void operator= (const DistributableLinearAlgebraObject &)=delete
 Broken assignment operator. More...
 
virtual ~DistributableLinearAlgebraObject ()
 Destructor. More...
 
LinearAlgebraDistributiondistribution_pt () const
 access to the LinearAlgebraDistribution More...
 
unsigned nrow () const
 access function to the number of global rows. More...
 
unsigned nrow_local () const
 access function for the num of local rows on this processor. More...
 
unsigned nrow_local (const unsigned &p) const
 access function for the num of local rows on this processor. More...
 
unsigned first_row () const
 access function for the first row on this processor More...
 
unsigned first_row (const unsigned &p) const
 access function for the first row on this processor More...
 
bool distributed () const
 distribution is serial or distributed More...
 
bool distribution_built () const
 
void build_distribution (const LinearAlgebraDistribution *const dist_pt)
 
void build_distribution (const LinearAlgebraDistribution &dist)
 

Private Member Functions

void solve_helper (DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
 General interface to solve function. More...
 
void clean_up_memory ()
 Cleanup data that's stored for resolve (if any has been stored) More...
 

Private Attributes

unsigned Iterations
 Number of iterations taken. More...
 
MATRIX * Matrix_pt
 Pointer to matrix. More...
 
bool Resolving
 
bool Matrix_can_be_deleted
 

Additional Inherited Members

- Protected Member Functions inherited from oomph::DistributableLinearAlgebraObject
void clear_distribution ()
 
- Protected Attributes inherited from oomph::IterativeLinearSolver
bool Doc_convergence_history
 
std::ofstream Output_file_stream
 Output file stream for convergence history. More...
 
double Tolerance
 Convergence tolerance. More...
 
unsigned Max_iter
 Maximum number of iterations. More...
 
PreconditionerPreconditioner_pt
 Pointer to the preconditioner. More...
 
double Jacobian_setup_time
 Jacobian setup time. More...
 
double Solution_time
 linear solver solution time More...
 
double Preconditioner_setup_time
 Preconditioner setup time. More...
 
bool Setup_preconditioner_before_solve
 
bool Throw_error_after_max_iter
 
bool Use_iterative_solver_as_preconditioner
 Use the iterative solver as preconditioner. More...
 
bool First_time_solve_when_used_as_preconditioner
 
- Protected Attributes inherited from oomph::LinearSolver
bool Enable_resolve
 
bool Doc_time
 Boolean flag that indicates whether the time taken. More...
 
bool Compute_gradient
 
bool Gradient_has_been_computed
 flag that indicates whether the gradient was computed or not More...
 
DoubleVector Gradient_for_glob_conv_newton_solve
 
- Static Protected Attributes inherited from oomph::IterativeLinearSolver
static IdentityPreconditioner Default_preconditioner
 

Detailed Description

template<typename MATRIX>
class oomph::BiCGStab< MATRIX >

The conjugate gradient method.

//////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////

Constructor & Destructor Documentation

◆ BiCGStab() [1/2]

template<typename MATRIX >
oomph::BiCGStab< MATRIX >::BiCGStab ( )
inline

Constructor.

414  : Iterations(0),
415  Matrix_pt(0),
416  Resolving(false),
418  {
419  }
bool Matrix_can_be_deleted
Definition: iterative_linear_solver.h:533
MATRIX * Matrix_pt
Pointer to matrix.
Definition: iterative_linear_solver.h:525
unsigned Iterations
Number of iterations taken.
Definition: iterative_linear_solver.h:522
bool Resolving
Definition: iterative_linear_solver.h:529

◆ ~BiCGStab()

template<typename MATRIX >
virtual oomph::BiCGStab< MATRIX >::~BiCGStab ( )
inlinevirtual

Destructor (cleanup storage)

424  {
425  clean_up_memory();
426  }
void clean_up_memory()
Cleanup data that's stored for resolve (if any has been stored)
Definition: iterative_linear_solver.h:512

References oomph::BiCGStab< MATRIX >::clean_up_memory().

◆ BiCGStab() [2/2]

template<typename MATRIX >
oomph::BiCGStab< MATRIX >::BiCGStab ( const BiCGStab< MATRIX > &  )
delete

Broken copy constructor.

Member Function Documentation

◆ clean_up_memory()

template<typename MATRIX >
void oomph::BiCGStab< MATRIX >::clean_up_memory ( )
inlineprivatevirtual

Cleanup data that's stored for resolve (if any has been stored)

Reimplemented from oomph::LinearSolver.

513  {
514  if ((Matrix_pt != 0) && (Matrix_can_be_deleted))
515  {
516  delete Matrix_pt;
517  Matrix_pt = 0;
518  }
519  }

References oomph::BiCGStab< MATRIX >::Matrix_can_be_deleted, and oomph::BiCGStab< MATRIX >::Matrix_pt.

Referenced by oomph::BiCGStab< MATRIX >::disable_resolve(), and oomph::BiCGStab< MATRIX >::~BiCGStab().

◆ disable_resolve()

template<typename MATRIX >
void oomph::BiCGStab< MATRIX >::disable_resolve ( )
inlinevirtual

Overload disable resolve so that it cleans up memory too.

Reimplemented from oomph::LinearSolver.

436  {
438  clean_up_memory();
439  }
virtual void disable_resolve()
Definition: linear_solver.h:144

References oomph::BiCGStab< MATRIX >::clean_up_memory(), and oomph::LinearSolver::disable_resolve().

◆ iterations()

template<typename MATRIX >
unsigned oomph::BiCGStab< MATRIX >::iterations ( ) const
inlinevirtual

Number of iterations taken.

Implements oomph::IterativeLinearSolver.

500  {
501  return Iterations;
502  }

References oomph::BiCGStab< MATRIX >::Iterations.

◆ operator=()

template<typename MATRIX >
void oomph::BiCGStab< MATRIX >::operator= ( const BiCGStab< MATRIX > &  )
delete

Broken assignment operator.

◆ resolve()

template<typename MATRIX >
void oomph::BiCGStab< MATRIX >::resolve ( const DoubleVector rhs,
DoubleVector result 
)
virtual

Re-solve the system defined by the last assembled Jacobian and the rhs vector specified here. Solution is returned in the vector result.

//////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// Re-solve the system defined by the last assembled Jacobian and the rhs vector specified here. Solution is returned in the vector result.

Reimplemented from oomph::LinearSolver.

64  {
65  // We are re-solving
66  Resolving = true;
67 
68 #ifdef PARANOID
69  if (Matrix_pt == 0)
70  {
71  throw OomphLibError("No matrix was stored -- cannot re-solve",
74  }
75 #endif
76 
77  // Call linear algebra-style solver
78  this->solve(Matrix_pt, rhs, result);
79 
80  // Reset re-solving flag
81  Resolving = false;
82  }
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: iterative_linear_solver.cc:90
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86

References OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, and solve.

◆ solve() [1/3]

template<typename MATRIX >
void oomph::BiCGStab< MATRIX >::solve ( DoubleMatrixBase *const &  matrix_pt,
const DoubleVector rhs,
DoubleVector solution 
)
inlinevirtual

Linear-algebra-type solver: Takes pointer to a matrix and rhs vector and returns the solution of the linear system.

Reimplemented from oomph::LinearSolver.

451  {
452  // Store the matrix if required
453  if ((Enable_resolve) && (!Resolving))
454  {
455  Matrix_pt = dynamic_cast<MATRIX*>(matrix_pt);
456 
457  // Matrix has been passed in from the outside so we must not
458  // delete it
459  Matrix_can_be_deleted = false;
460  }
461 
462  // set the distribution
463  if (dynamic_cast<DistributableLinearAlgebraObject*>(matrix_pt))
464  {
465  // the solver has the same distribution as the matrix if possible
466  this->build_distribution(
467  dynamic_cast<DistributableLinearAlgebraObject*>(matrix_pt)
468  ->distribution_pt());
469  }
470  else
471  {
472  // the solver has the same distribution as the RHS
473  this->build_distribution(rhs.distribution_pt());
474  }
475 
476  // Call the helper function
477  this->solve_helper(matrix_pt, rhs, solution);
478  }
void solve_helper(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
General interface to solve function.
Definition: iterative_linear_solver.cc:171
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
Definition: linear_algebra_distribution.h:457
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
Definition: linear_algebra_distribution.h:507
DistributableLinearAlgebraObject()
Default constructor - create a distribution.
Definition: linear_algebra_distribution.h:438
bool Enable_resolve
Definition: linear_solver.h:73
void solution(const Vector< double > &x, Vector< double > &u)
Definition: two_d_biharmonic.cc:113

References oomph::DistributableLinearAlgebraObject::build_distribution(), oomph::DistributableLinearAlgebraObject::distribution_pt(), oomph::LinearSolver::Enable_resolve, oomph::BiCGStab< MATRIX >::Matrix_can_be_deleted, oomph::BiCGStab< MATRIX >::Matrix_pt, oomph::BiCGStab< MATRIX >::Resolving, BiharmonicTestFunctions1::solution(), and oomph::BiCGStab< MATRIX >::solve_helper().

◆ solve() [2/3]

template<typename MATRIX >
void oomph::BiCGStab< MATRIX >::solve ( DoubleMatrixBase *const &  matrix_pt,
const Vector< double > &  rhs,
Vector< double > &  result 
)
inlinevirtual

Linear-algebra-type solver: Takes pointer to a matrix and rhs vector and returns the solution of the linear system Call the broken base-class version. If you want this, please implement it

Reimplemented from oomph::LinearSolver.

487  {
488  LinearSolver::solve(matrix_pt, rhs, result);
489  }
virtual void solve(Problem *const &problem_pt, DoubleVector &result)=0

References oomph::LinearSolver::solve().

◆ solve() [3/3]

template<typename MATRIX >
void oomph::BiCGStab< MATRIX >::solve ( Problem *const &  problem_pt,
DoubleVector result 
)
virtual

Solver: Takes pointer to problem and returns the results vector which contains the solution of the linear system defined by the problem's fully assembled Jacobian and residual vector.

Implements oomph::LinearSolver.

91  {
92  // Initialise timer
93 #ifdef OOMPH_HAS_MPI
94  double t_start = TimingHelpers::timer();
95 #else
96  clock_t t_start = clock();
97 #endif
98 
99  // We're not re-solving
100  Resolving = false;
101 
102  // Get rid of any previously stored data
103  clean_up_memory();
104 
105  // Get Jacobian matrix in format specified by template parameter
106  // and nonlinear residual vector
107  Matrix_pt = new MATRIX;
108  DoubleVector f;
109  problem_pt->get_jacobian(f, *Matrix_pt);
110 
111 
112  // We've made the matrix, we can delete it...
113  Matrix_can_be_deleted = true;
114 
115  // Doc time for setup
116 #ifdef OOMPH_HAS_MPI
117  double t_end = TimingHelpers::timer();
118  Jacobian_setup_time = t_end - t_start;
119 #else
120  clock_t t_end = clock();
121  Jacobian_setup_time = double(t_end - t_start) / CLOCKS_PER_SEC;
122 #endif
123 
124  if (Doc_time)
125  {
126  oomph_info << "Time for setup of Jacobian [sec]: " << Jacobian_setup_time
127  << std::endl;
128  }
129 
130  // set the distribution
131  if (dynamic_cast<DistributableLinearAlgebraObject*>(Matrix_pt))
132  {
133  // the solver has the same distribution as the matrix if possible
134  this->build_distribution(
136  ->distribution_pt());
137  }
138  else
139  {
140  // the solver has the same distribution as the RHS
141  this->build_distribution(f.distribution_pt());
142  }
143 
144  // Call linear algebra-style solver
145  if ((result.built()) &&
146  (!(*result.distribution_pt() == *this->distribution_pt())))
147  {
148  LinearAlgebraDistribution temp_global_dist(result.distribution_pt());
149  result.build(this->distribution_pt(), 0.0);
150  this->solve_helper(Matrix_pt, f, result);
151  result.redistribute(&temp_global_dist);
152  }
153  else
154  {
155  this->solve_helper(Matrix_pt, f, result);
156  }
157 
158  // Kill matrix unless it's still required for resolve
160  };
std::vector< double > DoubleVector
loads clump configuration
Definition: ClumpInput.h:26
double Jacobian_setup_time
Jacobian setup time.
Definition: iterative_linear_solver.h:248
bool Doc_time
Boolean flag that indicates whether the time taken.
Definition: linear_solver.h:77
static int f(const TensorMap< Tensor< int, 3 > > &tensor)
Definition: cxx11_tensor_map.cpp:237
double timer()
returns the time in seconds after some point in past
Definition: oomph_utilities.cc:1295
OomphInfo oomph_info
Definition: oomph_definitions.cc:319

References oomph::DoubleVector::build(), oomph::DoubleVector::built(), oomph::TerminateHelper::clean_up_memory(), oomph::DistributableLinearAlgebraObject::distribution_pt(), f(), oomph::Problem::get_jacobian(), oomph::oomph_info, oomph::DoubleVector::redistribute(), and oomph::TimingHelpers::timer().

◆ solve_helper()

template<typename MATRIX >
void oomph::BiCGStab< MATRIX >::solve_helper ( DoubleMatrixBase *const &  matrix_pt,
const DoubleVector rhs,
DoubleVector solution 
)
private

General interface to solve function.

Linear-algebra-type solver: Takes pointer to a matrix and rhs vector and returns the solution of the linear system. Algorithm and variable names based on "Numerical Linear Algebra for High-Performance Computers" by Dongarra, Duff, Sorensen & van der Vorst. SIAM (1998), page 185.

174  {
175 #ifdef PARANOID
176  // check that the rhs vector is setup
177  if (!rhs.built())
178  {
179  std::ostringstream error_message_stream;
180  error_message_stream << "The vectors rhs must be setup";
181  throw OomphLibError(error_message_stream.str(),
184  }
185 
186  // check that the matrix is square
187  if (matrix_pt->nrow() != matrix_pt->ncol())
188  {
189  std::ostringstream error_message_stream;
190  error_message_stream << "The matrix at matrix_pt must be square.";
191  throw OomphLibError(error_message_stream.str(),
194  }
195 
196  // check that the matrix and the rhs vector have the same nrow()
197  if (matrix_pt->nrow() != rhs.nrow())
198  {
199  std::ostringstream error_message_stream;
200  error_message_stream
201  << "The matrix and the rhs vector must have the same number of rows.";
202  throw OomphLibError(error_message_stream.str(),
205  }
206 
207  // if the matrix is distributable then it too should have the same
208  // communicator as the rhs vector
209  DistributableLinearAlgebraObject* dist_matrix_pt =
210  dynamic_cast<DistributableLinearAlgebraObject*>(matrix_pt);
211  if (dist_matrix_pt != 0)
212  {
213  if (!(*dist_matrix_pt->distribution_pt() == *rhs.distribution_pt()))
214  {
215  std::ostringstream error_message_stream;
216  error_message_stream
217  << "The matrix matrix_pt must have the same communicator as the "
218  "vectors"
219  << " rhs and result must have the same communicator";
220  throw OomphLibError(error_message_stream.str(),
223  }
224  }
225  // if the matrix is not distributable then it the rhs vector should not be
226  // distributed
227  else
228  {
229  if (rhs.distribution_pt()->distributed())
230  {
231  std::ostringstream error_message_stream;
232  error_message_stream
233  << "The matrix (matrix_pt) is not distributable and therefore the rhs"
234  << " vector must not be distributed";
235  throw OomphLibError(error_message_stream.str(),
238  }
239  }
240  // if the result vector is setup then check it has the same distribution
241  // as the rhs
242  if (solution.built())
243  {
244  if (!(*solution.distribution_pt() == *rhs.distribution_pt()))
245  {
246  std::ostringstream error_message_stream;
247  error_message_stream << "The solution vector distribution has been "
248  "setup; it must have the "
249  << "same distribution as the rhs vector.";
250  throw OomphLibError(error_message_stream.str(),
253  }
254  }
255 #endif
256 
257  // setup the solution if it is not
258  if (!solution.distribution_pt()->built())
259  {
260  solution.build(this->distribution_pt(), 0.0);
261  }
262  // zero
263  else
264  {
265  solution.initialise(0.0);
266  }
267 
268  // Get number of dofs
269  // unsigned n_dof=rhs.size();
270  unsigned nrow_local = this->nrow_local();
271 
272  // Time solver
273 #ifdef OOMPH_HAS_MPI
274  double t_start = TimingHelpers::timer();
275 #else
276  clock_t t_start = clock();
277 #endif
278 
279  // Initialise: Zero initial guess so the initial residual is
280  // equal to the RHS, i.e. the nonlinear residual
281  DoubleVector residual(rhs);
282  double residual_norm = residual.norm();
283  double rhs_norm = residual_norm;
284  if (rhs_norm == 0.0) rhs_norm = 1.0;
285  DoubleVector x(rhs.distribution_pt(), 0.0);
286 
287  // Hat residual by copy operation
288  DoubleVector r_hat(residual);
289 
290  // Normalised residual
291  double normalised_residual_norm = residual_norm / rhs_norm;
292 
293  // if required will document convergence history to screen or file (if
294  // stream open)
296  {
297  if (!Output_file_stream.is_open())
298  {
299  oomph_info << 0 << " " << normalised_residual_norm << std::endl;
300  }
301  else
302  {
303  Output_file_stream << 0 << " " << normalised_residual_norm << std::endl;
304  }
305  }
306 
307  // Check immediate convergence
308  if (normalised_residual_norm < Tolerance)
309  {
310  if (Doc_time)
311  {
312  oomph_info << "BiCGStab converged immediately" << std::endl;
313  }
314  solution = x;
315 
316  // Doc time for solver
317  double t_end = TimingHelpers::timer();
318  Solution_time = t_end - t_start;
319 
320  if (Doc_time)
321  {
322  oomph_info << "Time for solve with BiCGStab [sec]: " << Solution_time
323  << std::endl;
324  }
325  return;
326  }
327 
328  // Setup preconditioner only if we're not re-solving
329  if (!Resolving)
330  {
331  // only setup the preconditioner if required
333  {
334  // Setup preconditioner from the Jacobian matrix
335  double t_start_prec = TimingHelpers::timer();
336 
337  preconditioner_pt()->setup(matrix_pt);
338 
339  // Doc time for setup of preconditioner
340  double t_end_prec = TimingHelpers::timer();
341  Preconditioner_setup_time = t_end_prec - t_start_prec;
342 
343  if (Doc_time)
344  {
345  oomph_info << "Time for setup of preconditioner [sec]: "
346  << Preconditioner_setup_time << std::endl;
347  }
348  }
349  }
350  else
351  {
352  if (Doc_time)
353  {
354  oomph_info << "Setup of preconditioner is bypassed in resolve mode"
355  << std::endl;
356  }
357  }
358 
359  // Some auxiliary variables
360  double rho_prev = 0.0;
361  double alpha = 0.0;
362  double omega = 0.0;
363  double rho, beta, dot_prod, dot_prod_tt, dot_prod_ts;
364  double s_norm, r_norm;
365 
366  // Some vectors
367  DoubleVector p(this->distribution_pt(), 0.0),
368  p_hat(this->distribution_pt(), 0.0), v(this->distribution_pt(), 0.0),
369  z(this->distribution_pt(), 0.0), t(this->distribution_pt(), 0.0),
370  s(this->distribution_pt(), 0.0);
371 
372  // Loop over max. number of iterations
373  for (unsigned iter = 1; iter <= Max_iter; iter++)
374  {
375  // Dot product for rho
376  rho = r_hat.dot(residual);
377 
378  // Breakdown?
379  if (rho == 0.0)
380  {
381  oomph_info << "BiCGStab has broken down after " << iter << " iterations"
382  << std::endl;
383  oomph_info << "Returning with current normalised residual of "
384  << normalised_residual_norm << std::endl;
385  }
386 
387  // First step is different
388  if (iter == 1)
389  {
390  p = residual;
391  }
392  else
393  {
394  beta = (rho / rho_prev) * (alpha / omega);
395  for (unsigned i = 0; i < nrow_local; i++)
396  {
397  p[i] = residual[i] + beta * (p[i] - omega * v[i]);
398  }
399  }
400 
401  // Apply precondtitioner: p_hat=P^-1*p
403 
404  // Matrix vector product: v=A*p_hat
405  matrix_pt->multiply(p_hat, v);
406  dot_prod = r_hat.dot(v);
407  alpha = rho / dot_prod;
408  for (unsigned i = 0; i < nrow_local; i++)
409  {
410  s[i] = residual[i] - alpha * v[i];
411  }
412  s_norm = s.norm();
413 
414  // Normalised residual
415  normalised_residual_norm = s_norm / rhs_norm;
416 
417  // if required will document convergence history to screen or file (if
418  // stream open)
420  {
421  if (!Output_file_stream.is_open())
422  {
423  oomph_info << double(iter - 0.5) << " " << normalised_residual_norm
424  << std::endl;
425  }
426  else
427  {
428  Output_file_stream << double(iter - 0.5) << " "
429  << normalised_residual_norm << std::endl;
430  }
431  }
432 
433  // Converged?
434  if (normalised_residual_norm < Tolerance)
435  {
436  for (unsigned i = 0; i < nrow_local; i++)
437  {
438  solution[i] = x[i] + alpha * p_hat[i];
439  }
440 
441  if (Doc_time)
442  {
443  oomph_info << std::endl;
444  oomph_info << "BiCGStab converged. Normalised residual norm: "
445  << normalised_residual_norm << std::endl;
446  oomph_info << "Number of iterations to convergence: " << iter
447  << std::endl;
448  oomph_info << std::endl;
449  }
450 
451  // Store number of iterations taken
452  Iterations = iter;
453 
454  // Doc time for solver
455  double t_end = TimingHelpers::timer();
456  Solution_time = t_end - t_start;
457 
458  if (Doc_time)
459  {
460  oomph_info << "Time for solve with BiCGStab [sec]: " << Solution_time
461  << std::endl;
462  }
463 
464  return;
465  }
466 
467  // Apply precondtitioner: z=P^-1*s
469 
470  // Matrix vector product: t=A*z
471  matrix_pt->multiply(z, t);
472  dot_prod_ts = t.dot(s);
473  dot_prod_tt = t.dot(t);
474  omega = dot_prod_ts / dot_prod_tt;
475  for (unsigned i = 0; i < nrow_local; i++)
476  {
477  x[i] += alpha * p_hat[i] + omega * z[i];
478  residual[i] = s[i] - omega * t[i];
479  }
480  r_norm = residual.norm();
481  rho_prev = rho;
482 
483  // Check convergence again
484  normalised_residual_norm = r_norm / rhs_norm;
485 
486  // if required will document convergence history to screen or file (if
487  // stream open)
489  {
490  if (!Output_file_stream.is_open())
491  {
492  oomph_info << iter << " " << normalised_residual_norm << std::endl;
493  }
494  else
495  {
496  Output_file_stream << iter << " " << normalised_residual_norm
497  << std::endl;
498  }
499  }
500 
501 
502  if (normalised_residual_norm < Tolerance)
503  {
504  if (Doc_time)
505  {
506  oomph_info << std::endl;
507  oomph_info << "BiCGStab converged. Normalised residual norm: "
508  << normalised_residual_norm << std::endl;
509  oomph_info << "Number of iterations to convergence: " << iter
510  << std::endl;
511  oomph_info << std::endl;
512  }
513  solution = x;
514 
515  // Store the number of itertions taken.
516  Iterations = iter;
517 
518  // Doc time for solver
519  double t_end = TimingHelpers::timer();
520  Solution_time = t_end - t_start;
521 
522  if (Doc_time)
523  {
524  oomph_info << "Time for solve with BiCGStab [sec]: " << Solution_time
525  << std::endl;
526  }
527  return;
528  }
529 
530 
531  // Breakdown: Omega has to be >0 for to be able to continue
532  if (omega == 0.0)
533  {
534  oomph_info << std::endl;
535  oomph_info << "BiCGStab breakdown with omega=0.0. "
536  << "Normalised residual norm: " << normalised_residual_norm
537  << std::endl;
538  oomph_info << "Number of iterations so far: " << iter << std::endl;
539  oomph_info << std::endl;
540  solution = x;
541 
542  // Store the number of itertions taken.
543  Iterations = iter;
544 
545  // Doc time for solver
546  double t_end = TimingHelpers::timer();
547  Solution_time = t_end - t_start;
548 
549  if (Doc_time)
550  {
551  oomph_info << "Time for solve with BiCGStab [sec]: " << Solution_time
552  << std::endl;
553  }
554  return;
555  }
556 
557 
558  } // end of iteration loop
559 
560 
561  // No convergence
562  oomph_info << std::endl;
563  oomph_info << "BiCGStab did not converge to required tolerance! "
564  << std::endl;
565  oomph_info << "Returning with normalised residual norm: "
566  << normalised_residual_norm << std::endl;
567  oomph_info << "after " << Max_iter << " iterations." << std::endl;
568  oomph_info << std::endl;
569 
570  solution = x;
571 
572  // Doc time for solver
573  double t_end = TimingHelpers::timer();
574  Solution_time = t_end - t_start;
575 
576  if (Doc_time)
577  {
578  oomph_info << "Time for solve with BiCGStab [sec]: " << Solution_time
579  << std::endl;
580  }
581 
583  {
584  std::string err = "Solver failed to converge and you requested an error";
585  err += " on convergence failures.";
586  throw OomphLibError(
588  }
589  }
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
int i
Definition: BiCGSTAB_step_by_step.cpp:9
float * p
Definition: Tutorial_Map_using.cpp:9
unsigned nrow_local() const
access function for the num of local rows on this processor.
Definition: linear_algebra_distribution.h:469
double Tolerance
Convergence tolerance.
Definition: iterative_linear_solver.h:239
bool Throw_error_after_max_iter
Definition: iterative_linear_solver.h:262
Preconditioner *& preconditioner_pt()
Access function to preconditioner.
Definition: iterative_linear_solver.h:95
double Preconditioner_setup_time
Preconditioner setup time.
Definition: iterative_linear_solver.h:254
unsigned Max_iter
Maximum number of iterations.
Definition: iterative_linear_solver.h:242
double Solution_time
linear solver solution time
Definition: iterative_linear_solver.h:251
std::ofstream Output_file_stream
Output file stream for convergence history.
Definition: iterative_linear_solver.h:231
bool Doc_convergence_history
Definition: iterative_linear_solver.h:228
bool Setup_preconditioner_before_solve
Definition: iterative_linear_solver.h:258
void setup(DoubleMatrixBase *matrix_pt)
Definition: preconditioner.h:94
virtual void preconditioner_solve(const DoubleVector &r, DoubleVector &z)=0
RealScalar s
Definition: level1_cplx_impl.h:130
RealScalar alpha
Definition: level1_cplx_impl.h:151
Scalar beta
Definition: level2_cplx_impl.h:36
Vector::Scalar omega(const Vector &t, const Vector &s, RealScalar angle)
Definition: IDRS.h:36
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
list x
Definition: plotDoE.py:28
t
Definition: plotPSD.py:36

References alpha, beta, oomph::DoubleVector::built(), oomph::LinearAlgebraDistribution::distributed(), oomph::DistributableLinearAlgebraObject::distribution_pt(), oomph::DoubleVector::dot(), i, Global_Variables::Iterations, oomph::BlackBoxFDNewtonSolver::Max_iter, oomph::DoubleMatrixBase::multiply(), oomph::DoubleMatrixBase::ncol(), oomph::DoubleVector::norm(), oomph::DistributableLinearAlgebraObject::nrow(), oomph::DoubleMatrixBase::nrow(), Eigen::internal::omega(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::oomph_info, p, s, BiharmonicTestFunctions1::solution(), oomph::Global_string_for_annotation::string(), plotPSD::t, oomph::TimingHelpers::timer(), v, and plotDoE::x.

Referenced by oomph::BiCGStab< MATRIX >::solve().

Member Data Documentation

◆ Iterations

template<typename MATRIX >
unsigned oomph::BiCGStab< MATRIX >::Iterations
private

Number of iterations taken.

Referenced by oomph::BiCGStab< MATRIX >::iterations().

◆ Matrix_can_be_deleted

template<typename MATRIX >
bool oomph::BiCGStab< MATRIX >::Matrix_can_be_deleted
private

Boolean flag to indicate if the matrix pointed to be Matrix_pt can be deleted.

Referenced by oomph::BiCGStab< MATRIX >::clean_up_memory(), and oomph::BiCGStab< MATRIX >::solve().

◆ Matrix_pt

template<typename MATRIX >
MATRIX* oomph::BiCGStab< MATRIX >::Matrix_pt
private

◆ Resolving

template<typename MATRIX >
bool oomph::BiCGStab< MATRIX >::Resolving
private

Boolean flag to indicate if the solve is done in re-solve mode, bypassing setup of matrix and preconditioner

Referenced by oomph::BiCGStab< MATRIX >::solve().


The documentation for this class was generated from the following files: