action functions
|
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 if you wish to be informed of the library's "official" release. |
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
1.4.7