Reference documentation for deal.II version 8.4.2
solver_minres.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2015 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_minres_h
17 #define dealii__solver_minres_h
18 
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/lac/solver.h>
22 #include <deal.II/lac/solver_control.h>
23 #include <deal.II/base/logstream.h>
24 #include <cmath>
25 #include <deal.II/base/subscriptor.h>
26 
27 DEAL_II_NAMESPACE_OPEN
28 
31 
67 template <class VectorType = Vector<double> >
68 class SolverMinRes : public Solver<VectorType>
69 {
70 public:
76  {
77  };
78 
84  const AdditionalData &data=AdditionalData());
85 
91  const AdditionalData &data=AdditionalData());
92 
96  virtual ~SolverMinRes ();
97 
101  template<typename MatrixType, typename PreconditionerType>
102  void
103  solve (const MatrixType &A,
104  VectorType &x,
105  const VectorType &b,
106  const PreconditionerType &precondition);
107 
116  DeclException0 (ExcPreconditionerNotDefinite);
118 
119 protected:
123  virtual double criterion();
129  virtual void print_vectors(const unsigned int step,
130  const VectorType &x,
131  const VectorType &r,
132  const VectorType &d) const;
133 
138  VectorType *Vu0, *Vu1, *Vu2;
139  VectorType *Vm0, *Vm1, *Vm2;
140  VectorType *Vv;
141 
148  double res2;
149 };
150 
152 /*------------------------- Implementation ----------------------------*/
153 
154 #ifndef DOXYGEN
155 
156 template<class VectorType>
159  const AdditionalData &)
160  :
161  Solver<VectorType>(cn,mem)
162 {}
163 
164 
165 
166 template<class VectorType>
168  const AdditionalData &)
169  :
171 {}
172 
173 
174 template<class VectorType>
176 {}
177 
178 
179 
180 template<class VectorType>
181 double
183 {
184  return res2;
185 }
186 
187 
188 template<class VectorType>
189 void
190 SolverMinRes<VectorType>::print_vectors(const unsigned int,
191  const VectorType &,
192  const VectorType &,
193  const VectorType &) const
194 {}
195 
196 
197 
198 template<class VectorType>
199 template<typename MatrixType, typename PreconditionerType>
200 void
201 SolverMinRes<VectorType>::solve (const MatrixType &A,
202  VectorType &x,
203  const VectorType &b,
204  const PreconditionerType &precondition)
205 {
207 
208  deallog.push("minres");
209 
210  // Memory allocation
211  Vu0 = this->memory.alloc();
212  Vu1 = this->memory.alloc();
213  Vu2 = this->memory.alloc();
214  Vv = this->memory.alloc();
215  Vm0 = this->memory.alloc();
216  Vm1 = this->memory.alloc();
217  Vm2 = this->memory.alloc();
218  // define some aliases for simpler access
219  typedef VectorType *vecptr;
220  vecptr u[3] = {Vu0, Vu1, Vu2};
221  vecptr m[3] = {Vm0, Vm1, Vm2};
222  VectorType &v = *Vv;
223  // resize the vectors, but do not set
224  // the values since they'd be overwritten
225  // soon anyway.
226  u[0]->reinit(b,true);
227  u[1]->reinit(b,true);
228  u[2]->reinit(b,true);
229  m[0]->reinit(b,true);
230  m[1]->reinit(b,true);
231  m[2]->reinit(b,true);
232  v.reinit(b,true);
233 
234  // some values needed
235  double delta[3] = { 0, 0, 0 };
236  double f[2] = { 0, 0 };
237  double e[2] = { 0, 0 };
238 
239  double r_l2 = 0;
240  double r0 = 0;
241  double tau = 0;
242  double c = 0;
243  double gamma = 0;
244  double s = 0;
245  double d_ = 0;
246  double d = 0;
247 
248  // The iteration step.
249  unsigned int j = 1;
250 
251 
252  // Start of the solution process
253  A.vmult(*m[0],x);
254  *u[1] = b;
255  *u[1] -= *m[0];
256  // Precondition is applied.
257  // The preconditioner has to be
258  // positive definite and symmetric
259 
260  // M v = u[1]
261  precondition.vmult (v,*u[1]);
262 
263  delta[1] = v * (*u[1]);
264  // Preconditioner positive
265  Assert (delta[1]>=0, ExcPreconditionerNotDefinite());
266 
267  r0 = std::sqrt(delta[1]);
268  r_l2 = r0;
269 
270 
271  u[0]->reinit(b);
272  delta[0] = 1.;
273  m[0]->reinit(b);
274  m[1]->reinit(b);
275  m[2]->reinit(b);
276 
277  conv = this->iteration_status(0, r_l2, x);
278 
279  while (conv==SolverControl::iterate)
280  {
281  if (delta[1]!=0)
282  v *= 1./std::sqrt(delta[1]);
283  else
284  v.reinit(b);
285 
286  A.vmult(*u[2],v);
287  u[2]->add (-std::sqrt(delta[1]/delta[0]), *u[0]);
288 
289  gamma = *u[2] * v;
290  u[2]->add (-gamma / std::sqrt(delta[1]), *u[1]);
291  *m[0] = v;
292 
293  // precondition: solve M v = u[2]
294  // Preconditioner has to be positive
295  // definite and symmetric.
296  precondition.vmult(v,*u[2]);
297 
298  delta[2] = v * (*u[2]);
299 
300  Assert (delta[2]>=0, ExcPreconditionerNotDefinite());
301 
302  if (j==1)
303  {
304  d_ = gamma;
305  e[1] = std::sqrt(delta[2]);
306  }
307  if (j>1)
308  {
309  d_ = s * e[0] - c * gamma;
310  e[0] = c * e[0] + s * gamma;
311  f[1] = s * std::sqrt(delta[2]);
312  e[1] = -c * std::sqrt(delta[2]);
313  }
314 
315  d = std::sqrt (d_*d_ + delta[2]);
316 
317  if (j>1)
318  tau *= s / c;
319  c = d_ / d;
320  tau *= c;
321 
322  s = std::sqrt(delta[2]) / d;
323 
324  if (j==1)
325  tau = r0 * c;
326 
327  m[0]->add (-e[0], *m[1]);
328  if (j>1)
329  m[0]->add (-f[0], *m[2]);
330  *m[0] *= 1./d;
331  x.add (tau, *m[0]);
332  r_l2 *= std::fabs(s);
333 
334  conv = this->iteration_status(j, r_l2, x);
335 
336  // next iteration step
337  ++j;
338  // All vectors have to be shifted
339  // one iteration step.
340  // This should be changed one time.
341  //
342  // the previous code was like this:
343  // m[2] = m[1];
344  // m[1] = m[0];
345  // but it can be made more efficient,
346  // since the value of m[0] is no more
347  // needed in the next iteration
348  swap (*m[2], *m[1]);
349  swap (*m[1], *m[0]);
350 
351  // likewise, but reverse direction:
352  // u[0] = u[1];
353  // u[1] = u[2];
354  swap (*u[0], *u[1]);
355  swap (*u[1], *u[2]);
356 
357  // these are scalars, so need
358  // to bother
359  f[0] = f[1];
360  e[0] = e[1];
361  delta[0] = delta[1];
362  delta[1] = delta[2];
363  }
364 
365  // Deallocation of Memory
366  this->memory.free(Vu0);
367  this->memory.free(Vu1);
368  this->memory.free(Vu2);
369  this->memory.free(Vv);
370  this->memory.free(Vm0);
371  this->memory.free(Vm1);
372  this->memory.free(Vm2);
373  // Output
374  deallog.pop ();
375 
376  // in case of failure: throw exception
378  SolverControl::NoConvergence (j, r_l2));
379 
380  // otherwise exit as normal
381 }
382 
383 #endif // DOXYGEN
384 
385 DEAL_II_NAMESPACE_CLOSE
386 
387 #endif
void pop()
Definition: logstream.cc:300
Continue iteration.
SolverMinRes(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
#define AssertThrow(cond, exc)
Definition: exceptions.h:358
VectorType * Vu0
virtual ~SolverMinRes()
Stop iteration, goal reached.
#define Assert(cond, exc)
Definition: exceptions.h:294
DeclException0(ExcPreconditionerNotDefinite)
VectorMemory< VectorType > & memory
Definition: solver.h:402
boost::signals2::signal< SolverControl::State(const unsigned int iteration, const double check_value, const VectorType &current_iterate), StateCombiner > iteration_status
Definition: solver.h:448
Definition: solver.h:325
void push(const std::string &text)
Definition: logstream.cc:288
virtual double criterion()
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &precondition)
virtual void print_vectors(const unsigned int step, const VectorType &x, const VectorType &r, const VectorType &d) const