Reference documentation for deal.II version 9.0.0
solver_qmrs.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_solver_qmrs_h
17 #define dealii_solver_qmrs_h
18 
19 #include <deal.II/base/config.h>
20 #include <deal.II/lac/solver.h>
21 #include <deal.II/lac/solver_control.h>
22 #include <deal.II/base/logstream.h>
23 #include <cmath>
24 #include <deal.II/base/subscriptor.h>
25 
26 #include <cmath>
27 
28 DEAL_II_NAMESPACE_OPEN
29 
32 
91 template <typename VectorType = Vector<double> >
92 class SolverQMRS : public Solver<VectorType>
93 {
94 public:
116  {
123  explicit
125  const double solver_tolerance = 1.e-9,
126  const bool breakdown_testing = true,
127  const double breakdown_threshold = 1.e-16)
128  :
133  {
134  }
135 
140 
145 
150 
155  };
156 
162  const AdditionalData &data = AdditionalData ());
163 
169  const AdditionalData &data = AdditionalData ());
170 
174  template <typename MatrixType, typename PreconditionerType>
175  void
176  solve (const MatrixType &A,
177  VectorType &x,
178  const VectorType &b,
179  const PreconditionerType &preconditioner);
180 
186  virtual void
187  print_vectors (const unsigned int step,
188  const VectorType &x,
189  const VectorType &r,
190  const VectorType &d) const;
191 
192 protected:
193 
198 
199 private:
205  {
206  SolverControl::State state;
207  double last_residual;
208 
210  const double last_residual);
211  };
212 
217  template <typename MatrixType, typename PreconditionerType>
219  iterate (const MatrixType &A,
220  VectorType &x,
221  const VectorType &b,
222  const PreconditionerType &preconditioner,
223  VectorType &r,
224  VectorType &u,
225  VectorType &q,
226  VectorType &t,
227  VectorType &d);
228 
232  unsigned int step;
233 };
234 
236 /*------------------------- Implementation ----------------------------*/
237 
238 #ifndef DOXYGEN
239 
240 
241 template <class VectorType>
243  const double last_residual)
244  :
245  state (state),
246  last_residual (last_residual)
247 {}
248 
249 
250 
251 template <class VectorType>
254  const AdditionalData &data)
255  :
256  Solver<VectorType> (cn, mem),
257  additional_data (data),
258  step (0)
259 {
260 }
261 
262 template <class VectorType>
264  const AdditionalData &data)
265  :
266  Solver<VectorType> (cn),
267  additional_data (data),
268  step (0)
269 {
270 }
271 
272 template <class VectorType>
273 void
274 SolverQMRS<VectorType>::print_vectors (const unsigned int,
275  const VectorType &,
276  const VectorType &,
277  const VectorType &) const
278 {
279 }
280 
281 template <class VectorType>
282 template <typename MatrixType, typename PreconditionerType>
283 void
284 SolverQMRS<VectorType>::solve (const MatrixType &A,
285  VectorType &x,
286  const VectorType &b,
287  const PreconditionerType &preconditioner)
288 {
289  LogStream::Prefix prefix("SQMR");
290 
291 
292 // temporary vectors, allocated trough the @p VectorMemory object at the
293 // start of the actual solution process and deallocated at the end.
294  typename VectorMemory<VectorType>::Pointer Vr(this->memory);
295  typename VectorMemory<VectorType>::Pointer Vu(this->memory);
296  typename VectorMemory<VectorType>::Pointer Vq(this->memory);
297  typename VectorMemory<VectorType>::Pointer Vt(this->memory);
298  typename VectorMemory<VectorType>::Pointer Vd(this->memory);
299 
300 
301  // resize the vectors, but do not set
302  // the values since they'd be overwritten
303  // soon anyway.
304  Vr->reinit (x, true);
305  Vu->reinit (x, true);
306  Vq->reinit (x, true);
307  Vt->reinit (x, true);
308  Vd->reinit (x, true);
309 
310  step = 0;
311 
312  IterationResult state (SolverControl::failure, 0);
313 
314  do
315  {
316  if (step > 0)
317  deallog << "Restart step " << step << std::endl;
318  state = iterate (A, x, b, preconditioner, *Vr, *Vu, *Vq, *Vt, *Vd);
319  }
320  while (state.state == SolverControl::iterate);
321 
322 
323  // in case of failure: throw exception
324  AssertThrow(state.state == SolverControl::success,
325  SolverControl::NoConvergence (step, state.last_residual));
326  // otherwise exit as normal
327 }
328 
329 template <class VectorType>
330 template <typename MatrixType, typename PreconditionerType>
332 SolverQMRS<VectorType>::iterate (const MatrixType &A,
333  VectorType &x,
334  const VectorType &b,
335  const PreconditionerType &preconditioner,
336  VectorType &r,
337  VectorType &u,
338  VectorType &q,
339  VectorType &t,
340  VectorType &d)
341 {
342 
344 
345  int it = 0;
346 
347  double tau, rho, theta = 0;
348  double res;
349 
350  // Compute the start residual
351  A.vmult (r, x);
352  r.sadd (-1., 1., b);
353 
354  // Doing the initial preconditioning
355  if (additional_data.left_preconditioning)
356  {
357  // Left preconditioning
358  preconditioner.vmult (t, r);
359  q = t;
360  }
361  else
362  {
363  // Right preconditioning
364  t = r;
365  preconditioner.vmult (q, t);
366  }
367 
368  tau = t.norm_sqr ();
369  res = std::sqrt (tau);
370 
371  if (this->iteration_status (step, res, x) == SolverControl::success)
372  return IterationResult (SolverControl::success, res);
373 
374  rho = q * r;
375 
376  while (state == SolverControl::iterate)
377  {
378  step++;
379  it++;
380  //--------------------------------------------------------------
381  // Step 1: apply the system matrix and compute one inner product
382  //--------------------------------------------------------------
383  A.vmult (t, q);
384  const double sigma = q * t;
385 
386  // Check the breakdown criterion
387  if (additional_data.breakdown_testing == true
388  && std::fabs (sigma) < additional_data.breakdown_threshold)
389  return IterationResult (SolverControl::iterate,
390  res);
391  // Update the residual
392  const double alpha = rho / sigma;
393  r.add (-alpha, t);
394 
395  //--------------------------------------------------------------
396  // Step 2: update the solution vector
397  //--------------------------------------------------------------
398  const double theta_old = theta;
399 
400  // Apply the preconditioner
401  if (additional_data.left_preconditioning)
402  {
403  // Left Preconditioning
404  preconditioner.vmult (t, r);
405  }
406  else
407  {
408  // Right Preconditioning
409  t = r;
410  }
411 
412  // Double updates
413  theta = t * t / tau;
414  const double psi = 1. / (1. + theta);
415  tau *= theta * psi;
416 
417  // Actual update of the solution vector
418  d.sadd (psi * theta_old, psi * alpha, q);
419  x += d;
420 
421  print_vectors (step, x, r, d);
422 
423  // Check for convergence
424  // Compute a simple and cheap upper bound of the norm of the residual vector b-Ax
425  res = std::sqrt ((it + 1) * tau);
426  // If res lies close enough, within the desired tolerance, calculate the exact residual
427  if (res < additional_data.solver_tolerance)
428  {
429  A.vmult (u, x);
430  u.sadd (-1., 1., b);
431  res = u.l2_norm ();
432  }
433  state = this->iteration_status (step, res, x);
434  if ((state == SolverControl::success)
435  || (state == SolverControl::failure))
436  return IterationResult (state, res);
437 
438  //--------------------------------------------------------------
439  // Step 3: check breakdown criterion and update the vectors
440  //--------------------------------------------------------------
441  if (additional_data.breakdown_testing == true
442  && std::fabs (sigma) < additional_data.breakdown_threshold)
443  return IterationResult (SolverControl::iterate, res);
444 
445  const double rho_old = rho;
446 
447  // Applying the preconditioner
448  if (additional_data.left_preconditioning)
449  {
450  // Left preconditioning
451  u = t;
452  }
453  else
454  {
455  // Right preconditioning
456  preconditioner.vmult (u, t);
457  }
458 
459  // Double and vector updates
460  rho = u * r;
461  const double beta = rho / rho_old;
462  q.sadd (beta, u);
463  }
464  return IterationResult (SolverControl::success, res);
465 }
466 
467 #endif // DOXYGEN
468 
469 DEAL_II_NAMESPACE_CLOSE
470 
471 #endif
Stop iteration, goal not reached.
Continue iteration.
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
virtual void print_vectors(const unsigned int step, const VectorType &x, const VectorType &r, const VectorType &d) const
SolverQMRS(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
Stop iteration, goal reached.
unsigned int step
Definition: solver_qmrs.h:232
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
Definition: solver.h:322
AdditionalData(const bool left_preconditioning=false, const double solver_tolerance=1.e-9, const bool breakdown_testing=true, const double breakdown_threshold=1.e-16)
Definition: solver_qmrs.h:124
IterationResult iterate(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner, VectorType &r, VectorType &u, VectorType &q, VectorType &t, VectorType &d)
AdditionalData additional_data
Definition: solver_qmrs.h:197