Reference documentation for deal.II version 8.5.1
precondition_block_base.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 2016 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__precondition_block_base_h
17 #define dealii__precondition_block_base_h
18 
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/base/exceptions.h>
22 #include <deal.II/base/subscriptor.h>
23 #include <deal.II/base/smartpointer.h>
24 #include <deal.II/base/memory_consumption.h>
25 #include <deal.II/lac/householder.h>
26 #include <deal.II/lac/lapack_full_matrix.h>
27 
28 #include <vector>
29 
30 DEAL_II_NAMESPACE_OPEN
31 
32 template <typename number> class FullMatrix;
33 template <typename number> class Vector;
34 
53 template <typename number>
55 {
56 public:
61 
66  enum Inversion
67  {
81  };
82 
87  Inversion method = gauss_jordan);
88 
93 
98  void clear();
99 
104  void reinit(unsigned int nblocks, size_type blocksize, bool compress,
105  Inversion method = gauss_jordan);
106 
110  void inverses_computed(bool are_they);
111 
120  void set_same_diagonal ();
121 
125  bool same_diagonal () const;
126 
130  bool store_diagonals() const;
131 
135  bool inverses_ready () const;
136 
140  bool empty () const;
141 
145  unsigned int size() const;
146 
151  number el(size_type i, size_type j) const;
152 
156  template <typename number2>
157  void inverse_vmult(size_type i, Vector<number2> &dst, const Vector<number2> &src) const;
158 
162  template <typename number2>
163  void inverse_Tvmult(size_type i, Vector<number2> &dst, const Vector<number2> &src) const;
164 
169 
174 
179 
183  const FullMatrix<number> &inverse (size_type i) const;
184 
189 
194 
199 
203  const FullMatrix<number> &diagonal (size_type i) const;
204 
210  void log_statistics () const;
211 
216  std::size_t memory_consumption () const;
217 
223 
230 
231 protected:
236 
237 private:
241  unsigned int n_diagonal_blocks;
242 
249  std::vector<FullMatrix<number> > var_inverse_full;
250 
257  std::vector<Householder<number> > var_inverse_householder;
258 
265  std::vector<LAPACKFullMatrix<number> > var_inverse_svd;
266 
272  std::vector<FullMatrix<number> > var_diagonal;
273 
274 
279 
284 
290 };
291 
292 //----------------------------------------------------------------------//
293 
294 template <typename number>
295 inline
297  bool store, Inversion method)
298  :
299  inversion(method),
300  n_diagonal_blocks(0),
301  var_store_diagonals(store),
302  var_same_diagonal(false),
303  var_inverses_ready(false)
304 {}
305 
306 
307 template <typename number>
308 inline
309 void
311 {
312  if (var_inverse_full.size()!=0)
313  var_inverse_full.erase(var_inverse_full.begin(), var_inverse_full.end());
314  if (var_inverse_householder.size()!=0)
315  var_inverse_householder.erase(var_inverse_householder.begin(), var_inverse_householder.end());
316  if (var_inverse_svd.size()!=0)
317  var_inverse_svd.erase(var_inverse_svd.begin(), var_inverse_svd.end());
318  if (var_diagonal.size()!=0)
319  var_diagonal.erase(var_diagonal.begin(), var_diagonal.end());
320  var_same_diagonal = false;
321  var_inverses_ready = false;
322  n_diagonal_blocks = 0;
323 }
324 
325 template <typename number>
326 inline
327 void
328 PreconditionBlockBase<number>::reinit(unsigned int n, size_type b, bool compress,
329  Inversion method)
330 {
331  inversion = method;
332  var_same_diagonal = compress;
333  var_inverses_ready = false;
334  n_diagonal_blocks = n;
335 
336  if (compress)
337  {
338  switch (inversion)
339  {
340  case gauss_jordan:
341  var_inverse_full.resize(1);
342  var_inverse_full[0].reinit(b,b);
343  break;
344  case householder:
345  var_inverse_householder.resize(1);
346  break;
347  case svd:
348  var_inverse_svd.resize(1);
349  var_inverse_svd[0].reinit(b,b);
350  break;
351  default:
352  Assert(false, ExcNotImplemented());
353  }
354 
355  if (store_diagonals())
356  {
357  var_diagonal.resize(1);
358  var_diagonal[0].reinit(b,b);
359  }
360  }
361  else
362  {
363  // set the arrays to the right
364  // size. we could do it like this:
365  // var_inverse = vector<>(nblocks,FullMatrix<>())
366  // but this would involve copying many
367  // FullMatrix objects.
368  //
369  // the following is a neat trick which
370  // avoids copying
371  if (store_diagonals())
372  {
373  std::vector<FullMatrix<number> >
374  tmp(n, FullMatrix<number>(b));
375  var_diagonal.swap (tmp);
376  }
377 
378  switch (inversion)
379  {
380  case gauss_jordan:
381  {
382  std::vector<FullMatrix<number> >
383  tmp(n, FullMatrix<number>(b));
384  var_inverse_full.swap (tmp);
385  break;
386  }
387  case householder:
388  var_inverse_householder.resize(n);
389  break;
390  case svd:
391  {
392  std::vector<LAPACKFullMatrix<number> >
393  tmp(n, LAPACKFullMatrix<number>(b));
394  var_inverse_svd.swap (tmp);
395  break;
396  }
397  default:
398  Assert(false, ExcNotImplemented());
399  }
400  }
401 }
402 
403 
404 template <typename number>
405 inline
406 unsigned int
408 {
409  return n_diagonal_blocks;
410 }
411 
412 template <typename number>
413 template <typename number2>
414 inline
415 void
417  size_type i, Vector<number2> &dst, const Vector<number2> &src) const
418 {
419  const size_type ii = same_diagonal() ? 0U : i;
420 
421  switch (inversion)
422  {
423  case gauss_jordan:
424  AssertIndexRange (ii, var_inverse_full.size());
425  var_inverse_full[ii].vmult(dst, src);
426  break;
427  case householder:
428  AssertIndexRange (ii, var_inverse_householder.size());
429  var_inverse_householder[ii].vmult(dst, src);
430  break;
431  case svd:
432  AssertIndexRange (ii, var_inverse_svd.size());
433  var_inverse_svd[ii].vmult(dst, src);
434  break;
435  default:
436  Assert(false, ExcNotImplemented());
437  }
438 }
439 
440 
441 template <typename number>
442 template <typename number2>
443 inline
444 void
446  size_type i, Vector<number2> &dst, const Vector<number2> &src) const
447 {
448  const size_type ii = same_diagonal() ? 0U : i;
449 
450  switch (inversion)
451  {
452  case gauss_jordan:
453  AssertIndexRange (ii, var_inverse_full.size());
454  var_inverse_full[ii].Tvmult(dst, src);
455  break;
456  case householder:
457  AssertIndexRange (ii, var_inverse_householder.size());
458  var_inverse_householder[ii].Tvmult(dst, src);
459  break;
460  case svd:
461  AssertIndexRange (ii, var_inverse_svd.size());
462  var_inverse_svd[ii].Tvmult(dst, src);
463  break;
464  default:
465  Assert(false, ExcNotImplemented());
466  }
467 }
468 
469 
470 template <typename number>
471 inline
472 const FullMatrix<number> &
474 {
475  if (same_diagonal())
476  return var_inverse_full[0];
477 
478  Assert (i < var_inverse_full.size(), ExcIndexRange(i,0,var_inverse_full.size()));
479  return var_inverse_full[i];
480 }
481 
482 
483 template <typename number>
484 inline
485 const Householder<number> &
487 {
488  if (same_diagonal())
489  return var_inverse_householder[0];
490 
491  AssertIndexRange (i, var_inverse_householder.size());
492  return var_inverse_householder[i];
493 }
494 
495 
496 template <typename number>
497 inline
500 {
501  if (same_diagonal())
502  return var_inverse_svd[0];
503 
504  AssertIndexRange (i, var_inverse_svd.size());
505  return var_inverse_svd[i];
506 }
507 
508 
509 template <typename number>
510 inline
511 const FullMatrix<number> &
513 {
514  Assert(store_diagonals(), ExcDiagonalsNotStored());
515 
516  if (same_diagonal())
517  return var_diagonal[0];
518 
519  Assert (i < var_diagonal.size(), ExcIndexRange(i,0,var_diagonal.size()));
520  return var_diagonal[i];
521 }
522 
523 
524 template <typename number>
525 inline
528 {
529  Assert(var_inverse_full.size() != 0, ExcInverseNotAvailable());
530 
531  if (same_diagonal())
532  return var_inverse_full[0];
533 
534  Assert (i < var_inverse_full.size(), ExcIndexRange(i,0,var_inverse_full.size()));
535  return var_inverse_full[i];
536 }
537 
538 
539 template <typename number>
540 inline
543 {
544  Assert(var_inverse_householder.size() != 0, ExcInverseNotAvailable());
545 
546  if (same_diagonal())
547  return var_inverse_householder[0];
548 
549  AssertIndexRange (i, var_inverse_householder.size());
550  return var_inverse_householder[i];
551 }
552 
553 
554 template <typename number>
555 inline
558 {
559  Assert(var_inverse_svd.size() != 0, ExcInverseNotAvailable());
560 
561  if (same_diagonal())
562  return var_inverse_svd[0];
563 
564  AssertIndexRange (i, var_inverse_svd.size());
565  return var_inverse_svd[i];
566 }
567 
568 
569 template <typename number>
570 inline
573 {
574  Assert(store_diagonals(), ExcDiagonalsNotStored());
575 
576  if (same_diagonal())
577  return var_diagonal[0];
578 
579  Assert (i < var_diagonal.size(), ExcIndexRange(i,0,var_diagonal.size()));
580  return var_diagonal[i];
581 }
582 
583 
584 template <typename number>
585 inline bool
587 {
588  return var_same_diagonal;
589 }
590 
591 
592 template <typename number>
593 inline bool
595 {
596  return var_store_diagonals;
597 }
598 
599 
600 template <typename number>
601 inline void
603 {
604  var_inverses_ready = x;
605 }
606 
607 
608 template <typename number>
609 inline bool
611 {
612  return var_inverses_ready;
613 }
614 
615 
616 template <typename number>
617 inline void
619 {
620  deallog << "PreconditionBlockBase: " << size() << " blocks; ";
621 
622  if (inversion == svd)
623  {
624  unsigned int kermin = 100000000, kermax = 0;
625  double sigmin = 1.e300, sigmax= -1.e300;
626  double kappamin = 1.e300, kappamax= -1.e300;
627 
628  for (size_type b=0; b<size(); ++b)
629  {
630  const LAPACKFullMatrix<number> &matrix = inverse_svd(b);
631  size_type k=1;
632  while (k <= matrix.n_cols() && matrix.singular_value(matrix.n_cols()-k) == 0)
633  ++k;
634  const double s0 = matrix.singular_value(0);
635  const double sm = matrix.singular_value(matrix.n_cols()-k);
636  const double co = sm/s0;
637 
638  if (kermin > k) kermin = k-1;
639  if (kermax < k) kermax = k-1;
640  if (s0 < sigmin) sigmin = s0;
641  if (sm > sigmax) sigmax = sm;
642  if (co < kappamin) kappamin = co;
643  if (co > kappamax) kappamax = co;
644  }
645  deallog << "dim ker [" << kermin << ':' << kermax
646  << "] sigma [" << sigmin << ':' << sigmax
647  << "] kappa [" << kappamin << ':' << kappamax << ']' << std::endl;
648 
649  }
650  else if (inversion == householder)
651  {
652  }
653  else if (inversion == gauss_jordan)
654  {
655  }
656  else
657  {
658  Assert(false, ExcNotImplemented());
659  }
660 }
661 
662 
663 template <typename number>
664 inline
665 std::size_t
667 {
668  std::size_t mem = sizeof(*this);
669  for (size_type i=0; i<var_inverse_full.size(); ++i)
670  mem += MemoryConsumption::memory_consumption(var_inverse_full[i]);
671  for (size_type i=0; i<var_diagonal.size(); ++i)
672  mem += MemoryConsumption::memory_consumption(var_diagonal[i]);
673  return mem;
674 }
675 
676 
677 DEAL_II_NAMESPACE_CLOSE
678 
679 #endif
types::global_dof_index size_type
#define AssertIndexRange(index, range)
Definition: exceptions.h:1170
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
void inverses_computed(bool are_they)
void inverse_vmult(size_type i, Vector< number2 > &dst, const Vector< number2 > &src) const
std::vector< FullMatrix< number > > var_diagonal
FullMatrix< number > & inverse(size_type i)
PreconditionBlockBase(bool store_diagonals=false, Inversion method=gauss_jordan)
unsigned int global_dof_index
Definition: types.h:88
#define Assert(cond, exc)
Definition: exceptions.h:313
#define DeclException0(Exception0)
Definition: exceptions.h:541
std::vector< FullMatrix< number > > var_inverse_full
void reinit(unsigned int nblocks, size_type blocksize, bool compress, Inversion method=gauss_jordan)
void inverse_Tvmult(size_type i, Vector< number2 > &dst, const Vector< number2 > &src) const
number el(size_type i, size_type j) const
std_cxx11::enable_if< std_cxx11::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
static ::ExceptionBase & ExcDiagonalsNotStored()
std::vector< LAPACKFullMatrix< number > > var_inverse_svd
LAPACKFullMatrix< number > & inverse_svd(size_type i)
Householder< number > & inverse_householder(size_type i)
static ::ExceptionBase & ExcNotImplemented()
std::size_t memory_consumption() const
std::vector< Householder< number > > var_inverse_householder
FullMatrix< number > & diagonal(size_type i)
static ::ExceptionBase & ExcInverseNotAvailable()