Reference documentation for deal.II version 9.0.0
eigen.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 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_eigen_h
17 #define dealii_eigen_h
18 
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/lac/linear_operator.h>
22 #include <deal.II/lac/precondition.h>
23 #include <deal.II/lac/solver_cg.h>
24 #include <deal.II/lac/solver_control.h>
25 #include <deal.II/lac/solver_gmres.h>
26 #include <deal.II/lac/solver.h>
27 #include <deal.II/lac/solver_minres.h>
28 #include <deal.II/lac/vector_memory.h>
29 
30 #include <cmath>
31 
32 DEAL_II_NAMESPACE_OPEN
33 
34 
37 
53 template <typename VectorType = Vector<double> >
54 class EigenPower : private Solver<VectorType>
55 {
56 public:
61 
66  {
71  double shift;
75  AdditionalData (const double shift = 0.)
76  :
77  shift(shift)
78  {}
79 
80  };
81 
87  const AdditionalData &data=AdditionalData());
88 
92  virtual ~EigenPower ();
93 
100  template <typename MatrixType>
101  void
102  solve (double &value,
103  const MatrixType &A,
104  VectorType &x);
105 
106 protected:
111 };
112 
136 template <typename VectorType = Vector<double> >
137 class EigenInverse : private Solver<VectorType>
138 {
139 public:
144 
149  {
153  double relaxation;
154 
158  unsigned int start_adaption;
167  unsigned int start_adaption = 6,
168  bool use_residual = true)
169  :
173  {}
174 
175  };
176 
182  const AdditionalData &data=AdditionalData());
183 
184 
188  virtual ~EigenInverse ();
189 
197  template <typename MatrixType>
198  void
199  solve (double &value,
200  const MatrixType &A,
201  VectorType &x);
202 
203 protected:
208 };
209 
211 //---------------------------------------------------------------------------
212 
213 
214 template <class VectorType>
217  const AdditionalData &data)
218  :
219  Solver<VectorType>(cn, mem),
220  additional_data(data)
221 {}
222 
223 
224 
225 template <class VectorType>
227 {}
228 
229 
230 
231 template <class VectorType>
232 template <typename MatrixType>
233 void
235  const MatrixType &A,
236  VectorType &x)
237 {
239 
240  LogStream::Prefix prefix("Power method");
241 
242  typename VectorMemory<VectorType>::Pointer Vy (this->memory);
243  VectorType &y = *Vy;
244  y.reinit (x);
245  typename VectorMemory<VectorType>::Pointer Vr (this->memory);
246  VectorType &r = *Vr;
247  r.reinit (x);
248 
249  double length = x.l2_norm ();
250  double old_length = 0.;
251  x *= 1./length;
252 
253  A.vmult (y,x);
254 
255  // Main loop
256  int iter=0;
257  for (; conv==SolverControl::iterate; iter++)
258  {
259  y.add(additional_data.shift, x);
260 
261  // Compute absolute value of eigenvalue
262  old_length = length;
263  length = y.l2_norm ();
264 
265  // do a little trick to compute the sign
266  // with not too much effect of round-off errors.
267  double entry = 0.;
268  size_type i = 0;
269  double thresh = length/x.size();
270  do
271  {
272  Assert (i<x.size(), ExcInternalError());
273  entry = y (i++);
274  }
275  while (std::fabs(entry) < thresh);
276 
277  --i;
278 
279  // Compute unshifted eigenvalue
280  value = (entry * x (i) < 0.) ? -length : length;
281  value -= additional_data.shift;
282 
283  // Update normalized eigenvector
284  x.equ (1/length, y);
285 
286  // Compute residual
287  A.vmult (y,x);
288 
289  // Check the change of the eigenvalue
290  // Brrr, this is not really a good criterion
291  conv = this->iteration_status (iter, std::fabs(1./length-1./old_length), x);
292  }
293 
294  // in case of failure: throw exception
296  std::fabs(1./length-1./old_length)));
297 
298  // otherwise exit as normal
299 }
300 
301 //---------------------------------------------------------------------------
302 
303 template <class VectorType>
306  const AdditionalData &data)
307  :
308  Solver<VectorType>(cn, mem),
309  additional_data(data)
310 {}
311 
312 
313 
314 template <class VectorType>
316 {}
317 
318 
319 
320 template <class VectorType>
321 template <typename MatrixType>
322 void
324  const MatrixType &A,
325  VectorType &x)
326 {
327  LogStream::Prefix prefix("Wielandt");
328 
330 
331  // Prepare matrix for solver
332  auto A_op = linear_operator(A);
333  double current_shift = -value;
334  auto A_s = A_op + current_shift * identity_operator(A_op);
335 
336  // Define solver
337  ReductionControl inner_control (5000, 1.e-16, 1.e-5, false, false);
340  solver(inner_control, this->memory);
341 
342  // Next step for recomputing the shift
343  unsigned int goal = additional_data.start_adaption;
344 
345  // Auxiliary vector
346  typename VectorMemory<VectorType>::Pointer Vy (this->memory);
347  VectorType &y = *Vy;
348  y.reinit (x);
349  typename VectorMemory<VectorType>::Pointer Vr (this->memory);
350  VectorType &r = *Vr;
351  r.reinit (x);
352 
353  double length = x.l2_norm ();
354  double old_value = value;
355 
356  x *= 1./length;
357 
358  // Main loop
359  double res = -std::numeric_limits<double>::max();
360  size_type iter=0;
361  for (; conv==SolverControl::iterate; iter++)
362  {
363  solver.solve (A_s, y, x, prec);
364 
365  // Compute absolute value of eigenvalue
366  length = y.l2_norm ();
367 
368  // do a little trick to compute the sign
369  // with not too much effect of round-off errors.
370  double entry = 0.;
371  size_type i = 0;
372  double thresh = length/x.size();
373  do
374  {
375  Assert (i<x.size(), ExcInternalError());
376  entry = y (i++);
377  }
378  while (std::fabs(entry) < thresh);
379 
380  --i;
381 
382  // Compute unshifted eigenvalue
383  value = (entry * x(i) < 0. ? -1. : 1.) / length - current_shift;
384 
385  if (iter==goal)
386  {
387  const auto &relaxation = additional_data.relaxation;
388  const double new_shift =
389  relaxation * (-value) + (1. - relaxation) * current_shift;
390 
391  A_s = A_op + new_shift * identity_operator(A_op);
392  current_shift = new_shift;
393 
394  ++goal;
395  }
396 
397  // Update normalized eigenvector
398  x.equ (1./length, y);
399  // Compute residual
400  if (additional_data.use_residual)
401  {
402  y.equ (value, x);
403  A.vmult(r,x);
404  r.sadd(-1., value, x);
405  res = r.l2_norm();
406  // Check the residual
407  conv = this->iteration_status (iter, res, x);
408  }
409  else
410  {
411  res = std::fabs(1./value-1./old_value);
412  conv = this->iteration_status (iter, res, x);
413  }
414  old_value = value;
415  }
416 
417  // in case of failure: throw
418  // exception
421  res));
422  // otherwise exit as normal
423 }
424 
425 DEAL_II_NAMESPACE_CLOSE
426 
427 #endif
types::global_dof_index size_type
Definition: eigen.h:143
Continue iteration.
AdditionalData additional_data
Definition: eigen.h:110
void solve(double &value, const MatrixType &A, VectorType &x)
Definition: eigen.h:234
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
void solve(double &value, const MatrixType &A, VectorType &x)
Definition: eigen.h:323
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
unsigned int global_dof_index
Definition: types.h:88
Stop iteration, goal reached.
#define Assert(cond, exc)
Definition: exceptions.h:1142
AdditionalData additional_data
Definition: eigen.h:207
EigenPower(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
Definition: eigen.h:215
AdditionalData(const double shift=0.)
Definition: eigen.h:75
EigenInverse(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
Definition: eigen.h:304
virtual ~EigenInverse()
Definition: eigen.h:315
virtual ~EigenPower()
Definition: eigen.h:226
unsigned int start_adaption
Definition: eigen.h:158
LinearOperator< Range, Range, Payload > identity_operator(const std::function< void(Range &, bool)> &reinit_vector)
Definition: solver.h:322
types::global_dof_index size_type
Definition: eigen.h:60
AdditionalData(double relaxation=1., unsigned int start_adaption=6, bool use_residual=true)
Definition: eigen.h:166
LinearOperator< Range, Domain, Payload > linear_operator(const Matrix &matrix)
static ::ExceptionBase & ExcInternalError()