Example codes
and tutorials
The (Not-so) Quick Guide
List of tutorials/demo codes
Single-Physics Problems
Poisson
Adaptivity illustrated for Poisson
Advection-Diffusion
Unsteady heat equation
Linear wave equation
The Young-Laplace equation
Navier-Stokes
Free-surface Navier-Stokes
Axisymmetric Navier-Stokes
Solid mechanics
Beam structures
Shell structures
Multi-physics Problems
Fluid-structure interaction
Boussinesq convection
Steady thermoelasticity
Methods-based example codes and tutorials
Mesh generation
Linear solvers and preconditioners
Visualisation of the results
Parallel processing
How to write a new element
How to write a new refineable element
Default nonlinear solvers -- the sequence of action functions
...
Documentation
FE theory and top-down discussion of the data structure
The (Not-so) Quick Guide
Comprehensive bottom-up discussion of the data structure
List of available structured and unstructured meshes
Linear solvers and preconditioners
Visualisation of the results
Parallel processing
Coding conventions and C++ style
Creating documentation
Optimisation - robustness vs. "raw speed"
Linear vs. nonlinear problems
Storing shape functions
Changing the default "full" integration scheme
Disabling the ALE formulation of unsteady equations
C vs. C++ output
Different sparse assembly techniques and the STL memory pool
Publications
Publications
Talks
Journal publications
Theses
Picture show
Download
Copyright
Download/installation instructions
Download page
FAQ & Contact
FAQ
Change log
Bugs and other known problems
Completeness of the library & our "To-Do List"
Contact the developers
Get involved

 


Beta release!

Please note that the library has not been "officially" released. While we continue to work on the documentation, these web pages are likely to contain broken links and documents in draft form. Please send an email to

oomph-lib AT maths DOT man DOT ac DOT uk

if you wish to be informed of the library's "official" release.

general_purpose_preconditioners.h

Go to the documentation of this file.
00001 //LIC// ====================================================================
00002 //LIC// This file forms part of oomph-lib, the object-oriented, 
00003 //LIC// multi-physics finite-element library, available 
00004 //LIC// at http://www.oomph-lib.org.
00005 //LIC// 
00006 //LIC//           Version 0.90. August 3, 2009.
00007 //LIC// 
00008 //LIC// Copyright (C) 2006-2009 Matthias Heil and Andrew Hazel
00009 //LIC// 
00010 //LIC// This library is free software; you can redistribute it and/or
00011 //LIC// modify it under the terms of the GNU Lesser General Public
00012 //LIC// License as published by the Free Software Foundation; either
00013 //LIC// version 2.1 of the License, or (at your option) any later version.
00014 //LIC// 
00015 //LIC// This library is distributed in the hope that it will be useful,
00016 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 //LIC// Lesser General Public License for more details.
00019 //LIC// 
00020 //LIC// You should have received a copy of the GNU Lesser General Public
00021 //LIC// License along with this library; if not, write to the Free Software
00022 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00023 //LIC// 02110-1301  USA.
00024 //LIC// 
00025 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
00026 //LIC// 
00027 //LIC//====================================================================
00028 //Include guards
00029 #ifndef OOMPH_GENERAL_PRECONDITION_HEADER
00030 #define OOMPH_GENERAL_PRECONDITION_HEADER
00031 
00032 
00033 // Config header generated by autoconfig
00034 #ifdef HAVE_CONFIG_H
00035   #include <oomph-lib-config.h>
00036 #endif
00037 
00038 #include "preconditioner.h"
00039 #include "iterative_linear_solver.h"
00040 #include "matrices.h"
00041 #include "problem.h"
00042 #include <algorithm>
00043 
00044 
00045 
00046 namespace oomph
00047 {
00048 
00049 
00050 
00051 //=====================================================================
00052 /// Matrix-based diagonal preconditioner
00053 //=====================================================================
00054 class MatrixBasedDiagPreconditioner : public Preconditioner
00055 {
00056  public:
00057  
00058  ///Constructor (empty)
00059  MatrixBasedDiagPreconditioner(){};
00060  
00061  ///Destructor (empty)
00062  ~MatrixBasedDiagPreconditioner(){};
00063  
00064  /// Broken copy constructor
00065  MatrixBasedDiagPreconditioner(const MatrixBasedDiagPreconditioner&) 
00066   { 
00067    BrokenCopy::broken_copy("MatrixBasedDiagPreconditioner");
00068   } 
00069  
00070  /// Broken assignment operator
00071  void operator=(const MatrixBasedDiagPreconditioner&) 
00072   {
00073    BrokenCopy::broken_assign("MatrixBasedDiagPreconditioner");
00074   }
00075 
00076   /// Apply preconditioner to z, i.e. z=D^-1 
00077   void preconditioner_solve(const DoubleVector&r, DoubleVector &z);
00078 
00079   /// \short Setup the preconditioner (store diagonal) from the fully
00080   /// assembled matrix.
00081   void setup(Problem* problem_pt, DoubleMatrixBase* matrix_pt);
00082 
00083  private:
00084 
00085   /// Vector of inverse diagonal entries
00086   Vector<double> Inv_diag;
00087 };
00088 
00089 //=============================================================================
00090 /// Matrix-based lumped preconditioner
00091 //=============================================================================
00092 template<typename MATRIX>
00093 class MatrixBasedLumpedPreconditioner : public Preconditioner
00094 {
00095  public:
00096  
00097  ///Constructor
00098  MatrixBasedLumpedPreconditioner()
00099   {
00100    // default the positive matrix boolean to false
00101    Positive_matrix = false;
00102 
00103    // set the pointers to the lumped vector to 0
00104    Inv_lumped_diag_pt = 0;
00105   };
00106  
00107  ///Destructor 
00108  ~MatrixBasedLumpedPreconditioner()
00109   {
00110    this->clean_up_memory();
00111   }
00112  
00113  /// Broken copy constructor
00114  MatrixBasedLumpedPreconditioner(const MatrixBasedDiagPreconditioner&) 
00115   { 
00116    BrokenCopy::broken_copy("MatrixBasedDiagPreconditioner");
00117   } 
00118  
00119  /// Broken assignment operator
00120  void operator=(const MatrixBasedLumpedPreconditioner&) 
00121   {
00122    BrokenCopy::broken_assign("MatrixBasedDiagPreconditioner");
00123   }
00124 
00125   /// Apply preconditioner to z, i.e. z=D^-1 
00126   void preconditioner_solve(const DoubleVector &r, DoubleVector &z);
00127 
00128   /// \short Setup the preconditioner (store diagonal) from the fully
00129   /// assembled matrix. Problem pointer is ignored.
00130   void setup(Problem* problem_pt, DoubleMatrixBase* matrix_pt);
00131 
00132   /// \short Access function to the Positive_matrix which indicates whether 
00133   /// lumped matrix was positive
00134   bool& positive_matrix()
00135    {
00136     /// paranoid check that preconditioner has been setup
00137 #ifdef PARANOID
00138    if (Inv_lumped_diag_pt == 0) 
00139    {
00140     throw OomphLibError(
00141      "The preconditioner has not been setup.",
00142      "MatrixBasedDiagPreconditioner::positive_matrix()",
00143      OOMPH_EXCEPTION_LOCATION);
00144    }
00145 #endif
00146     return Positive_matrix;
00147    }
00148 
00149 
00150   /// \short Access function to the inverse of the lumped vector assembled in
00151   /// the preconditioner setup routine
00152   double* inverse_lumped_vector_pt()
00153    {
00154     /// paranoid check that vector has been created
00155 #ifdef PARANOID
00156    if (Inv_lumped_diag_pt == 0) 
00157    {
00158     throw OomphLibError(
00159      "The inverse lumped vector has not been created. Created in setup(...)",
00160      "MatrixBasedLumpedPreconditioner::inverse_lumped_vector_pt()",
00161      OOMPH_EXCEPTION_LOCATION);
00162    }
00163 #endif
00164     return Inv_lumped_diag_pt;
00165    }
00166 
00167 
00168   /// \short Access function to number of rows for this preconditioner
00169   unsigned& nrow() { return Nrow; }
00170 
00171   /// clean up memory - just delete the inverse lumped vector
00172   void clean_up_memory()
00173    {
00174     delete[] Inv_lumped_diag_pt;
00175    }
00176  private:
00177 
00178 
00179   /// Vector of inverse diagonal entries
00180   double* Inv_lumped_diag_pt;
00181 
00182   // boolean to indicate whether the lumped matrix was positive
00183   bool Positive_matrix;
00184 
00185   // number of rows in preconditioner
00186   unsigned Nrow;
00187 };
00188 
00189 
00190 
00191 //=============================================================================
00192 /// \short Class for a compressed-matrix coefficent (for either CC or CR
00193 /// matrices). Contains the (row or column) index and value of a 
00194 /// coefficient in a compressed row or column.
00195 /// Currently only used in ILU(0) for CCDoubleMatrices to allow the 
00196 /// coefficients in each compressed column [row] to be sorted by 
00197 /// their row [column] index.
00198 //=============================================================================
00199 class CompressedMatrixCoefficient
00200 {
00201 
00202   public:
00203 
00204  /// Constructor (no arguments)
00205  CompressedMatrixCoefficient(){}
00206 
00207  /// Constructor (takes the index and value as arguments)
00208  CompressedMatrixCoefficient(const unsigned& index, const double& value)
00209   {
00210    // store the index and value
00211    Index = index;
00212    Value = value;
00213   }
00214 
00215  /// Destructor (does nothing)
00216  ~CompressedMatrixCoefficient(){}
00217 
00218   /// Copy Constructor. Not Broken. Required for STL sort function. 
00219  CompressedMatrixCoefficient(const CompressedMatrixCoefficient& a) 
00220   { 
00221    Index = a.index();
00222    Value = a.value();   
00223   } 
00224  
00225  /// Assignment Operator. Not Broken. Required for STL sort function.
00226  void operator=(const CompressedMatrixCoefficient& a) 
00227   { 
00228    Index = a.index();
00229    Value = a.value();
00230   } 
00231 
00232  /// Less Than Operator (for the STL sort function)
00233  bool operator<(const CompressedMatrixCoefficient& a) const
00234   {
00235    return Index < a.index();
00236   }
00237 
00238  /// access function for the coefficient's (row or column) index
00239  unsigned& index() { return Index; }
00240 
00241  /// access function for the coefficient value
00242  double& value() { return Value; }
00243 
00244  /// \short Access function for the coefficient's (row or column_ index 
00245  /// (const version)
00246  unsigned index() const { return Index; }
00247 
00248  /// access function for the coefficient's value (const version)
00249  double value() const { return Value; }
00250 
00251   private:
00252 
00253  /// the row or column index of the compressed-matrix coefficient
00254  unsigned Index;
00255 
00256  /// the value of the compressed-matrix coefficient
00257  double Value;
00258 
00259 };
00260 
00261 
00262 
00263 
00264 
00265 //=============================================================================
00266 /// ILU(0) Preconditioner
00267 //=============================================================================
00268 template <typename MATRIX> 
00269 class ILUZeroPreconditioner : public Preconditioner
00270 {
00271 };
00272 
00273 
00274 //=============================================================================
00275 /// ILU(0) Preconditioner for matrices of CCDoubleMatrix Format
00276 //=============================================================================
00277 template <> 
00278 class ILUZeroPreconditioner<CCDoubleMatrix> : public Preconditioner
00279 {
00280  
00281  public :
00282   
00283   ///Constructor (empty)
00284   ILUZeroPreconditioner(){};
00285  
00286  ///Destructor (empty)
00287  ~ILUZeroPreconditioner(){};
00288  
00289 
00290  /// Broken copy constructor
00291  ILUZeroPreconditioner(const ILUZeroPreconditioner&) 
00292   { 
00293    BrokenCopy::broken_copy("ILUZeroPreconditioner");
00294   } 
00295  
00296  /// Broken assignment operator
00297  void operator=(const ILUZeroPreconditioner&) 
00298   {
00299    BrokenCopy::broken_assign("ILUZeroPreconditioner");
00300   }
00301 
00302  
00303  /// Apply preconditioner to r 
00304  void preconditioner_solve(const DoubleVector&r, DoubleVector &z);
00305 
00306  /// \short Setup the preconditioner (store diagonal) from the fully
00307  /// assembled matrix. Problem pointer is ignored.
00308  void setup(Problem* problem_pt, DoubleMatrixBase* matrix_pt);
00309  
00310   private:
00311 
00312  /// Column start for upper triangular matrix 
00313  Vector<unsigned> U_column_start;
00314 
00315  /// \short Row entry for the upper triangular matrix (each element of the 
00316  /// vector contains the row index and coefficient) 
00317  Vector<CompressedMatrixCoefficient> U_row_entry;
00318 
00319  /// Column start for lower triangular matrix 
00320  Vector<unsigned> L_column_start;
00321 
00322  /// \short Row entry for the lower triangular matrix (each element of the 
00323  /// vector contains the row index and coefficient)
00324  Vector<CompressedMatrixCoefficient> L_row_entry;
00325 
00326 };
00327 
00328 
00329 //=============================================================================
00330 /// ILU(0) Preconditioner for matrices of CRDoubleMatrix Format
00331 //=============================================================================
00332 template <> 
00333 class ILUZeroPreconditioner<CRDoubleMatrix> : public Preconditioner
00334 {
00335  
00336  public :
00337   
00338   ///Constructor (empty)
00339   ILUZeroPreconditioner(){};
00340  
00341 
00342  /// Broken copy constructor
00343  ILUZeroPreconditioner(const ILUZeroPreconditioner&) 
00344   { 
00345    BrokenCopy::broken_copy("ILUZeroPreconditioner");
00346   } 
00347  
00348  /// Broken assignment operator
00349  void operator=(const ILUZeroPreconditioner&) 
00350   {
00351    BrokenCopy::broken_assign("ILUZeroPreconditioner");
00352   }
00353  
00354  ///Destructor (empty)
00355  ~ILUZeroPreconditioner(){};
00356  
00357  /// Apply preconditioner to r
00358  void preconditioner_solve(const DoubleVector&r, DoubleVector &z);
00359  
00360  /// \short Setup the preconditioner (store diagonal) from the fully
00361  /// assembled matrix. Problem pointer is ignored.
00362  void setup(Problem* problem_pt, DoubleMatrixBase* matrix_pt);
00363  
00364  
00365   private:
00366 
00367 
00368  /// Row start for upper triangular matrix 
00369  Vector<unsigned> U_row_start;
00370 
00371  /// \short column entry for the upper triangular matrix (each element of the 
00372  /// vector contains the column index and coefficient) 
00373  Vector<CompressedMatrixCoefficient> U_row_entry;
00374  
00375  /// Row start for lower triangular matrix 
00376  Vector<unsigned> L_row_start;
00377 
00378  /// \short column entry for the lower triangular matrix (each element of the 
00379  /// vector contains the column index and coefficient) 
00380  Vector<CompressedMatrixCoefficient> L_row_entry;
00381 };
00382 
00383 //=============================================================================
00384 /// \short A preconditioner for performing inner iteration preconditioner 
00385 /// solves. The template argument SOLVER specifies the inner iteration
00386 /// solver (which must be derived from IterativeLinearSolver) and the
00387 /// template argument PRECONDITIONER specifies the preconditioner for the 
00388 /// inner iteration iterative solver.\n
00389 /// Note: For no preconditioning use the IdentityPreconditioner.
00390 //=============================================================================
00391 template <class SOLVER, class PRECONDITIONER> 
00392 class InnerIterationPreconditioner : public Preconditioner
00393 {
00394   public:
00395 
00396  /// Constructor
00397  InnerIterationPreconditioner()
00398   {
00399    // create the solver
00400    Solver_pt = new SOLVER;
00401 
00402    // create the preconditioner
00403    Preconditioner_pt = new PRECONDITIONER;
00404 
00405 #ifdef PARANOID
00406    // paranoid check that the solver is an iterative solver and 
00407    // the preconditioner is a preconditioner
00408    if (dynamic_cast<IterativeLinearSolver* >(Solver_pt) == 0)
00409     {
00410      throw OomphLibError(
00411       "The template argument SOLVER must be of type IterativeLinearSolver",
00412       "InnerIterationPreconditioner::InnerIterationPreconditioner()",
00413       OOMPH_EXCEPTION_LOCATION);     
00414     }
00415    if (dynamic_cast<Preconditioner*>(Preconditioner_pt) == 0)
00416     {
00417      throw OomphLibError(
00418       "The template argument PRECONDITIONER must be of type Preconditioner",
00419       "InnerIterationPreconditioner::InnerIterationPreconditioner()",
00420       OOMPH_EXCEPTION_LOCATION);     
00421     }
00422 #endif
00423 
00424    // ensure the solver does not re-setup the preconditioner
00425    Solver_pt->setup_preconditioner_before_solve() = false;
00426 
00427    // pass the preconditioner to the solver
00428    Solver_pt->preconditioner_pt() = Preconditioner_pt;
00429   }
00430 
00431  // destructor
00432  ~InnerIterationPreconditioner()
00433   {
00434    delete Solver_pt;
00435    delete Preconditioner_pt;
00436   }
00437 
00438  // clean the memory
00439  void clean_up_memory()
00440   {
00441    Preconditioner_pt->clean_up_memory();
00442    Solver_pt->clean_up_memory();
00443   }
00444 
00445  /// \short Preconditioner setup method. Setup the preconditioner for the inner
00446  /// iteration solver.
00447  void setup(Problem* problem_pt, DoubleMatrixBase* matrix_pt)
00448   {
00449    
00450    // set the distribution
00451    DistributableLinearAlgebraObject* dist_pt = 
00452     dynamic_cast<DistributableLinearAlgebraObject*>
00453     (matrix_pt);
00454    if (dist_pt != 0)
00455     {
00456      Distribution_pt->rebuild(dist_pt->distribution_pt());
00457     }
00458    else
00459     {
00460      Distribution_pt->rebuild(problem_pt->communicator_pt(),
00461                               matrix_pt->nrow(),false);
00462     }
00463 
00464    // setup the inner iteration preconditioner
00465    Preconditioner_pt->setup(problem_pt,matrix_pt);
00466 
00467    // setup the solverready for resolve
00468    unsigned max_iter = Solver_pt->max_iter();
00469    Solver_pt->max_iter() = 1;
00470    DoubleVector x(Distribution_pt,0.0);
00471    DoubleVector y(x);
00472    Solver_pt->enable_resolve();
00473    Solver_pt->solve(matrix_pt,x,y);
00474    Solver_pt->max_iter() = max_iter;
00475   }
00476  
00477  /// \short Preconditioner solve method. Performs the specified number
00478  /// of Krylov iterations preconditioned with the specified preconditioner
00479  void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
00480   {
00481    Solver_pt->resolve(r,z);
00482   }
00483 
00484  /// Access to convergence tolerance of the inner iteration solver
00485  double& tolerance() {return Solver_pt->tolerance();}
00486  
00487  /// Access to max. number of iterations of the inner iteration solver
00488  unsigned& max_iter() {return Solver_pt->max_iter();} 
00489 
00490  ///
00491  SOLVER* solver_pt() { return Solver_pt; }
00492 
00493  /// 
00494  PRECONDITIONER* preconditioner_pt() { return Preconditioner_pt; }
00495 
00496   private:
00497 
00498  /// pointer to the underlying solver
00499  SOLVER* Solver_pt;
00500 
00501  /// pointer to the underlying preconditioner
00502  PRECONDITIONER* Preconditioner_pt;
00503 };
00504 }
00505 #endif

Generated on Mon Aug 10 11:23:46 2009 by  doxygen 1.4.7