Reference documentation for deal.II version 8.5.1
solver_qmrs.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 2017 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 
70 template <typename VectorType = Vector<double> >
71 class SolverQMRS : public Solver<VectorType>
72 {
73 public:
86  {
93  explicit
95  double breakdown=1.e-16) :
98  {}
99 
104 
108  double breakdown;
109  };
110 
116  const AdditionalData &data=AdditionalData());
117 
123  const AdditionalData &data=AdditionalData());
124 
128  template<typename MatrixType, typename PreconditionerType>
129  void
130  solve (const MatrixType &A,
131  VectorType &x,
132  const VectorType &b,
133  const PreconditionerType &precondition);
134 
140  virtual void print_vectors (const unsigned int step,
141  const VectorType &x,
142  const VectorType &r,
143  const VectorType &d) const;
144 protected:
148  virtual double criterion();
149 
154  VectorType *Vv;
155  VectorType *Vp;
156  VectorType *Vq;
157  VectorType *Vt;
158  VectorType *Vd;
162  VectorType *Vx;
166  const VectorType *Vb;
167 
174  double res2;
175 
180 
181 private:
182 
188  {
189  SolverControl::State state;
190  double last_residual;
191 
193  const double last_residual);
194  };
195 
196 
201  template<typename MatrixType, typename PreconditionerType>
203  iterate (const MatrixType &A,
204  const PreconditionerType &precondition);
205 
209  unsigned int step;
210 };
211 
213 /*------------------------- Implementation ----------------------------*/
214 
215 #ifndef DOXYGEN
216 
217 template<class VectorType>
219  const double last_residual)
220  :
221  state (state),
222  last_residual (last_residual)
223 {}
224 
225 
226 template<class VectorType>
229  const AdditionalData &data)
230  :
231  Solver<VectorType>(cn,mem),
232  additional_data(data)
233 {}
234 
235 
236 
237 template<class VectorType>
239  const AdditionalData &data)
240  :
241  Solver<VectorType>(cn),
242  additional_data(data)
243 {}
244 
245 
246 
247 template<class VectorType>
248 double
250 {
251  return std::sqrt(res2);
252 }
253 
254 
255 
256 template<class VectorType>
257 void
258 SolverQMRS<VectorType>::print_vectors(const unsigned int,
259  const VectorType &,
260  const VectorType &,
261  const VectorType &) const
262 {}
263 
264 
265 
266 template<class VectorType>
267 template<typename MatrixType, typename PreconditionerType>
268 void
269 SolverQMRS<VectorType>::solve (const MatrixType &A,
270  VectorType &x,
271  const VectorType &b,
272  const PreconditionerType &precondition)
273 {
274  deallog.push("QMRS");
275 
276  // Memory allocation
277  Vv = this->memory.alloc();
278  Vp = this->memory.alloc();
279  Vq = this->memory.alloc();
280  Vt = this->memory.alloc();
281  Vd = this->memory.alloc();
282 
283  Vx = &x;
284  Vb = &b;
285  // resize the vectors, but do not set
286  // the values since they'd be overwritten
287  // soon anyway.
288  Vv->reinit(x, true);
289  Vp->reinit(x, true);
290  Vq->reinit(x, true);
291  Vt->reinit(x, true);
292 
293  step = 0;
294 
295  IterationResult state (SolverControl::failure,0);
296 
297  do
298  {
299  if (step > 0)
300  deallog << "Restart step " << step << std::endl;
301  state = iterate(A, precondition);
302  }
303  while (state.state == SolverControl::iterate);
304 
305  // Deallocate Memory
306  this->memory.free(Vv);
307  this->memory.free(Vp);
308  this->memory.free(Vq);
309  this->memory.free(Vt);
310  this->memory.free(Vd);
311 
312  // Output
313  deallog.pop();
314 
315  // in case of failure: throw exception
316  AssertThrow(state.state == SolverControl::success,
318  state.last_residual));
319  // otherwise exit as normal
320 }
321 
322 
323 
324 template<class VectorType>
325 template<typename MatrixType, typename PreconditionerType>
327 SolverQMRS<VectorType>::iterate(const MatrixType &A,
328  const PreconditionerType &precondition)
329 {
330  /* Remark: the matrix A in the article is the preconditioned matrix.
331  * Therefore, we have to precondition x before we compute the first residual.
332  * In step 1 we replace p by q to avoid one preconditioning step.
333  * There are still two steps left, making this algorithm expensive.
334  */
335 
337 
338  // define some aliases for simpler access
339  VectorType &v = *Vv;
340  VectorType &p = *Vp;
341  VectorType &q = *Vq;
342  VectorType &t = *Vt;
343  VectorType &d = *Vd;
344  VectorType &x = *Vx;
345  const VectorType &b = *Vb;
346 
347  int it=0;
348 
349  double tau, rho, theta=0;
350  double res;
351 
352  d.reinit(x);
353 
354  // Apply right preconditioning to x
355  precondition.vmult(q,x);
356  // Preconditioned residual
357  A.vmult(v,q);
358  v.sadd(-1.,1.,b);
359  res = v.l2_norm();
360 
361  if (this->iteration_status(step, res, x) == SolverControl::success)
362  return IterationResult(SolverControl::success, res);
363 
364  p = v;
365 
366  precondition.vmult(q,p);
367 
368  tau = v.norm_sqr();
369  rho = q*v;
370 
371  while (state == SolverControl::iterate)
372  {
373  step++;
374  it++;
375  // Step 1
376  A.vmult(t,q);
377  // Step 2
378  const double sigma = q*t;
379 
380 //TODO:[?] Find a really good breakdown criterion. The absolute one detects breakdown instead of convergence
381  if (std::fabs(sigma/rho) < additional_data.breakdown)
382  return IterationResult(SolverControl::iterate, std::fabs(sigma/rho));
383  // Step 3
384  const double alpha = rho/sigma;
385 
386  v.add(-alpha,t);
387  // Step 4
388  const double theta_old = theta;
389  theta = v*v/tau;
390  const double psi = 1./(1.+theta);
391  tau *= theta*psi;
392 
393  d.sadd(psi*theta_old, psi*alpha, p);
394  x.add(d);
395 
396  print_vectors(step,x,v,d);
397  // Step 5
398  if (additional_data.exact_residual)
399  {
400  A.vmult(q,x);
401  q.sadd(-1.,1.,b);
402  res = q.l2_norm();
403  }
404  else
405  res = std::sqrt((it+1)*tau);
406  state = this->iteration_status(step,res,x);
407  if ((state == SolverControl::success)
408  || (state == SolverControl::failure))
409  return IterationResult(state, res);
410  // Step 6
411  if (std::fabs(rho) < additional_data.breakdown)
412  return IterationResult(SolverControl::iterate, std::fabs(rho));
413  // Step 7
414  const double rho_old = rho;
415  precondition.vmult(q,v);
416  rho = q*v;
417 
418  const double beta = rho/rho_old;
419  p.sadd(beta,v);
420  precondition.vmult(q,p);
421  }
422  return IterationResult(SolverControl::success, std::fabs(rho));
423 }
424 
425 #endif // DOXYGEN
426 
427 DEAL_II_NAMESPACE_CLOSE
428 
429 #endif
Stop iteration, goal not reached.
void pop()
Definition: logstream.cc:306
IterationResult iterate(const MatrixType &A, const PreconditionerType &precondition)
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &precondition)
Continue iteration.
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
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.
const VectorType * Vb
Definition: solver_qmrs.h:166
unsigned int step
Definition: solver_qmrs.h:209
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
VectorType * Vx
Definition: solver_qmrs.h:162
Definition: solver.h:325
VectorType * Vv
Definition: solver_qmrs.h:154
AdditionalData(bool exact_residual=false, double breakdown=1.e-16)
Definition: solver_qmrs.h:94
void push(const std::string &text)
Definition: logstream.cc:294
AdditionalData additional_data
Definition: solver_qmrs.h:179
double res2
Definition: solver_qmrs.h:174
virtual double criterion()