Reference documentation for deal.II version 9.1.0-pre
solver_bicgstab.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_solver_bicgstab_h
17 #define dealii_solver_bicgstab_h
18 
19 
20 #include <deal.II/base/config.h>
21 
22 #include <deal.II/base/logstream.h>
23 #include <deal.II/base/signaling_nan.h>
24 #include <deal.II/base/subscriptor.h>
25 
26 #include <deal.II/lac/solver.h>
27 #include <deal.II/lac/solver_control.h>
28 
29 #include <cmath>
30 
31 DEAL_II_NAMESPACE_OPEN
32 
35 
36 namespace internal
37 {
43  {
44  protected:
48  double alpha;
52  double beta;
56  double omega;
60  double rho;
64  double rhobar;
65 
69  unsigned int step;
70 
74  double res;
75 
81  };
82 } // namespace internal
83 
123 template <typename VectorType = Vector<double>>
124 class SolverBicgstab : public Solver<VectorType>,
126 {
127 public:
139  {
146  explicit AdditionalData(const bool exact_residual = true,
147  const double breakdown = 1.e-10)
148  : exact_residual(exact_residual)
149  , breakdown(breakdown)
150  {}
158  double breakdown;
159  };
160 
166  const AdditionalData & data = AdditionalData());
167 
173  const AdditionalData &data = AdditionalData());
174 
178  virtual ~SolverBicgstab() override;
179 
183  template <typename MatrixType, typename PreconditionerType>
184  void
185  solve(const MatrixType & A,
186  VectorType & x,
187  const VectorType & b,
188  const PreconditionerType &preconditioner);
189 
190 protected:
194  VectorType *Vx;
195 
200 
205 
210 
215 
220 
225 
230 
234  const VectorType *Vb;
235 
239  template <typename MatrixType>
240  double
241  criterion(const MatrixType &A, const VectorType &x, const VectorType &b);
242 
248  virtual void
249  print_vectors(const unsigned int step,
250  const VectorType & x,
251  const VectorType & r,
252  const VectorType & d) const;
253 
258 
259 private:
263  template <typename MatrixType>
265  start(const MatrixType &A);
266 
272  {
273  bool breakdown;
274  SolverControl::State state;
275  unsigned int last_step;
276  double last_residual;
277 
278  IterationResult(const bool breakdown,
279  const SolverControl::State state,
280  const unsigned int last_step,
281  const double last_residual);
282  };
283 
288  template <typename MatrixType, typename PreconditionerType>
290  iterate(const MatrixType &A, const PreconditionerType &preconditioner);
291 };
292 
294 /*-------------------------Inline functions -------------------------------*/
295 
296 #ifndef DOXYGEN
297 
298 
299 template <typename VectorType>
301  const bool breakdown,
302  const SolverControl::State state,
303  const unsigned int last_step,
304  const double last_residual)
305  : breakdown(breakdown)
306  , state(state)
307  , last_step(last_step)
308  , last_residual(last_residual)
309 {}
310 
311 
312 
313 template <typename VectorType>
316  const AdditionalData & data)
317  : Solver<VectorType>(cn, mem)
318  , Vx(nullptr)
319  , Vb(nullptr)
320  , additional_data(data)
321 {}
322 
323 
324 
325 template <typename VectorType>
327  const AdditionalData &data)
328  : Solver<VectorType>(cn)
329  , Vx(nullptr)
330  , Vb(nullptr)
331  , additional_data(data)
332 {}
333 
334 
335 
336 template <typename VectorType>
338 {}
339 
340 
341 
342 template <typename VectorType>
343 template <typename MatrixType>
344 double
345 SolverBicgstab<VectorType>::criterion(const MatrixType &A,
346  const VectorType &x,
347  const VectorType &b)
348 {
349  A.vmult(*Vt, x);
350  Vt->add(-1., b);
351  res = Vt->l2_norm();
352 
353  return res;
354 }
355 
356 
357 
358 template <typename VectorType>
359 template <typename MatrixType>
361 SolverBicgstab<VectorType>::start(const MatrixType &A)
362 {
363  A.vmult(*Vr, *Vx);
364  Vr->sadd(-1., 1., *Vb);
365  res = Vr->l2_norm();
366 
367  return this->iteration_status(step, res, *Vx);
368 }
369 
370 
371 
372 template <typename VectorType>
373 void
375  const VectorType &,
376  const VectorType &,
377  const VectorType &) const
378 {}
379 
380 
381 
382 template <typename VectorType>
383 template <typename MatrixType, typename PreconditionerType>
385 SolverBicgstab<VectorType>::iterate(const MatrixType & A,
386  const PreconditionerType &preconditioner)
387 {
388  // TODO:[GK] Implement "use the length of the computed orthogonal residual" in
389  // the BiCGStab method.
391  alpha = omega = rho = 1.;
392 
393  VectorType &r = *Vr;
394  VectorType &rbar = *Vrbar;
395  VectorType &p = *Vp;
396  VectorType &y = *Vy;
397  VectorType &z = *Vz;
398  VectorType &t = *Vt;
399  VectorType &v = *Vv;
400 
401  rbar = r;
402  bool startup = true;
403 
404  do
405  {
406  ++step;
407 
408  rhobar = r * rbar;
409  beta = rhobar * alpha / (rho * omega);
410  rho = rhobar;
411  if (startup == true)
412  {
413  p = r;
414  startup = false;
415  }
416  else
417  {
418  p.sadd(beta, 1., r);
419  p.add(-beta * omega, v);
420  }
421 
422  preconditioner.vmult(y, p);
423  A.vmult(v, y);
424  rhobar = rbar * v;
425 
426  alpha = rho / rhobar;
427 
428  // TODO:[?] Find better breakdown criterion
429 
430  if (std::fabs(alpha) > 1.e10)
431  return IterationResult(true, state, step, res);
432 
433  res = std::sqrt(r.add_and_dot(-alpha, v, r));
434 
435  // check for early success, see the lac/bicgstab_early testcase as to
436  // why this is necessary
437  //
438  // note: the vector *Vx we pass to the iteration_status signal here is
439  // only the current approximation, not the one we will return with, which
440  // will be x=*Vx + alpha*y
441  if (this->iteration_status(step, res, *Vx) == SolverControl::success)
442  {
443  Vx->add(alpha, y);
444  print_vectors(step, *Vx, r, y);
446  }
447 
448  preconditioner.vmult(z, r);
449  A.vmult(t, z);
450  rhobar = t * r;
451  omega = rhobar / (t * t);
452  Vx->add(alpha, y, omega, z);
453 
454  if (additional_data.exact_residual)
455  {
456  r.add(-omega, t);
457  res = criterion(A, *Vx, *Vb);
458  }
459  else
460  res = std::sqrt(r.add_and_dot(-omega, t, r));
461 
462  state = this->iteration_status(step, res, *Vx);
463  print_vectors(step, *Vx, r, y);
464  }
465  while (state == SolverControl::iterate);
466  return IterationResult(false, state, step, res);
467 }
468 
469 
470 template <typename VectorType>
471 template <typename MatrixType, typename PreconditionerType>
472 void
473 SolverBicgstab<VectorType>::solve(const MatrixType & A,
474  VectorType & x,
475  const VectorType & b,
476  const PreconditionerType &preconditioner)
477 {
478  LogStream::Prefix prefix("Bicgstab");
479  Vr = typename VectorMemory<VectorType>::Pointer(this->memory);
480  Vrbar = typename VectorMemory<VectorType>::Pointer(this->memory);
481  Vp = typename VectorMemory<VectorType>::Pointer(this->memory);
482  Vy = typename VectorMemory<VectorType>::Pointer(this->memory);
483  Vz = typename VectorMemory<VectorType>::Pointer(this->memory);
484  Vt = typename VectorMemory<VectorType>::Pointer(this->memory);
485  Vv = typename VectorMemory<VectorType>::Pointer(this->memory);
486 
487  Vr->reinit(x, true);
488  Vrbar->reinit(x, true);
489  Vp->reinit(x, true);
490  Vy->reinit(x, true);
491  Vz->reinit(x, true);
492  Vt->reinit(x, true);
493  Vv->reinit(x, true);
494 
495  Vx = &x;
496  Vb = &b;
497 
498  step = 0;
499 
500  IterationResult state(false, SolverControl::failure, 0, 0);
501 
502  // iterate while the inner iteration returns a breakdown
503  do
504  {
505  if (step != 0)
506  deallog << "Restart step " << step << std::endl;
507  if (start(A) == SolverControl::success)
508  {
509  state.state = SolverControl::success;
510  break;
511  }
512  state = iterate(A, preconditioner);
513  ++step;
514  }
515  while (state.breakdown == true);
516 
517  // in case of failure: throw exception
518  AssertThrow(state.state == SolverControl::success,
519  SolverControl::NoConvergence(state.last_step,
520  state.last_residual));
521  // otherwise exit as normal
522 }
523 
524 #endif // DOXYGEN
525 
526 DEAL_II_NAMESPACE_CLOSE
527 
528 #endif
Stop iteration, goal not reached.
SolverBicgstab(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
Continue iteration.
VectorMemory< VectorType >::Pointer Vrbar
virtual ~SolverBicgstab() override
virtual void print_vectors(const unsigned int step, const VectorType &x, const VectorType &r, const VectorType &d) const
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
VectorMemory< VectorType >::Pointer Vv
VectorMemory< VectorType >::Pointer Vp
VectorMemory< VectorType >::Pointer Vr
Stop iteration, goal reached.
AdditionalData additional_data
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
VectorMemory< VectorType >::Pointer Vt
AdditionalData(const bool exact_residual=true, const double breakdown=1.e-10)
Definition: solver.h:328
const VectorType * Vb
IterationResult iterate(const MatrixType &A, const PreconditionerType &preconditioner)
VectorMemory< VectorType >::Pointer Vy
VectorMemory< VectorType >::Pointer Vz
SolverControl::State start(const MatrixType &A)
VectorType * Vx
double criterion(const MatrixType &A, const VectorType &x, const VectorType &b)