$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 #ifndef LIBMESH_PETSC_LINEAR_SOLVER_H 00021 #define LIBMESH_PETSC_LINEAR_SOLVER_H 00022 00023 #include "libmesh/libmesh_config.h" 00024 00025 #ifdef LIBMESH_HAVE_PETSC 00026 00027 #include "libmesh/petsc_macro.h" 00028 00033 EXTERN_C_FOR_PETSC_BEGIN 00034 #if PETSC_VERSION_LESS_THAN(2,2,0) 00035 # include <petscsles.h> 00036 #else 00037 # include <petscksp.h> 00038 #endif 00039 EXTERN_C_FOR_PETSC_END 00040 00041 // Local includes 00042 #include "libmesh/linear_solver.h" 00043 00044 // C++ includes 00045 #include <cstddef> 00046 #include <vector> 00047 00048 //-------------------------------------------------------------------- 00049 // Functions with C linkage to pass to PETSc. PETSc will call these 00050 // methods as needed for preconditioning 00051 // 00052 // Since they must have C linkage they have no knowledge of a namespace. 00053 // Give them an obscure name to avoid namespace pollution. 00054 extern "C" 00055 { 00056 // Older versions of PETSc do not have the different int typedefs. 00057 // On 64-bit machines, PetscInt may actually be a long long int. 00058 // This change occurred in Petsc-2.2.1. 00059 #if PETSC_VERSION_LESS_THAN(2,2,1) 00060 typedef int PetscErrorCode; 00061 typedef int PetscInt; 00062 #endif 00063 00064 #if PETSC_RELEASE_LESS_THAN(3,0,1) 00065 00069 PetscErrorCode __libmesh_petsc_preconditioner_setup (void * ctx); 00070 00075 PetscErrorCode __libmesh_petsc_preconditioner_apply(void *ctx, Vec x, Vec y); 00076 #else 00077 PetscErrorCode __libmesh_petsc_preconditioner_setup (PC); 00078 PetscErrorCode __libmesh_petsc_preconditioner_apply(PC, Vec x, Vec y); 00079 #endif 00080 } // end extern "C" 00081 00082 00083 namespace libMesh 00084 { 00085 00086 // forward declarations 00087 template <typename T> class PetscMatrix; 00088 00097 template <typename T> 00098 class PetscLinearSolver : public LinearSolver<T> 00099 { 00100 public: 00104 PetscLinearSolver (const libMesh::Parallel::Communicator &comm_in 00105 LIBMESH_CAN_DEFAULT_TO_COMMWORLD); 00106 00110 ~PetscLinearSolver (); 00111 00115 void clear (); 00116 00122 void init (const char *name = NULL); 00123 00127 void init (PetscMatrix<T>* matrix, const char *name = NULL); 00128 00137 virtual void init_names (const System&); 00138 00146 virtual void restrict_solve_to (const std::vector<unsigned int>* const dofs, 00147 const SubsetSolveMode subset_solve_mode=SUBSET_ZERO); 00148 00153 std::pair<unsigned int, Real> 00154 solve (SparseMatrix<T> &matrix_in, 00155 NumericVector<T> &solution_in, 00156 NumericVector<T> &rhs_in, 00157 const double tol, 00158 const unsigned int m_its) 00159 { 00160 return this->solve(matrix_in, matrix_in, solution_in, rhs_in, tol, m_its); 00161 } 00162 00163 00168 std::pair<unsigned int, Real> 00169 adjoint_solve (SparseMatrix<T> &matrix_in, 00170 NumericVector<T> &solution_in, 00171 NumericVector<T> &rhs_in, 00172 const double tol, 00173 const unsigned int m_its); 00174 00175 00191 std::pair<unsigned int, Real> 00192 solve (SparseMatrix<T> &matrix, 00193 SparseMatrix<T> &preconditioner, 00194 NumericVector<T> &solution, 00195 NumericVector<T> &rhs, 00196 const double tol, 00197 const unsigned int m_its); 00198 00202 std::pair<unsigned int, Real> 00203 solve (const ShellMatrix<T>& shell_matrix, 00204 NumericVector<T>& solution_in, 00205 NumericVector<T>& rhs_in, 00206 const double tol, 00207 const unsigned int m_its); 00208 00214 virtual std::pair<unsigned int, Real> 00215 solve (const ShellMatrix<T>& shell_matrix, 00216 const SparseMatrix<T>& precond_matrix, 00217 NumericVector<T>& solution_in, 00218 NumericVector<T>& rhs_in, 00219 const double tol, 00220 const unsigned int m_its); 00221 00227 PC pc() { this->init(); return _pc; } 00228 00234 KSP ksp() { this->init(); return _ksp; } 00235 00240 void get_residual_history(std::vector<double>& hist); 00241 00248 Real get_initial_residual(); 00249 00253 virtual LinearConvergenceReason get_converged_reason() const; 00254 00255 private: 00256 00261 void set_petsc_solver_type (); 00262 00266 static PetscErrorCode _petsc_shell_matrix_mult(Mat mat, Vec arg, Vec dest); 00267 00271 static PetscErrorCode _petsc_shell_matrix_mult_add(Mat mat, Vec arg, Vec add, Vec dest); 00272 00276 static PetscErrorCode _petsc_shell_matrix_get_diagonal(Mat mat, Vec dest); 00277 00278 // SLES removed from >= PETSc 2.2.0 00279 #if PETSC_VERSION_LESS_THAN(2,2,0) 00280 00284 SLES _sles; 00285 00286 #endif 00287 00291 PC _pc; 00292 00296 KSP _ksp; 00297 00302 IS _restrict_solve_to_is; 00303 00309 IS _restrict_solve_to_is_complement; 00310 00315 PetscInt _restrict_solve_to_is_local_size(void)const; 00316 00322 void _create_complement_is (const NumericVector<T> &vec_in); 00323 00328 SubsetSolveMode _subset_solve_mode; 00329 00330 }; 00331 00332 00333 /*----------------------- functions ----------------------------------*/ 00334 template <typename T> 00335 inline 00336 PetscLinearSolver<T>::PetscLinearSolver(const libMesh::Parallel::Communicator &comm_in) : 00337 LinearSolver<T>(comm_in), 00338 _restrict_solve_to_is(NULL), 00339 _restrict_solve_to_is_complement(NULL), 00340 _subset_solve_mode(SUBSET_ZERO) 00341 { 00342 if (this->n_processors() == 1) 00343 this->_preconditioner_type = ILU_PRECOND; 00344 else 00345 this->_preconditioner_type = BLOCK_JACOBI_PRECOND; 00346 } 00347 00348 00349 00350 template <typename T> 00351 inline 00352 PetscLinearSolver<T>::~PetscLinearSolver () 00353 { 00354 this->clear (); 00355 } 00356 00357 00358 00359 template <typename T> 00360 inline PetscInt 00361 PetscLinearSolver<T>:: 00362 _restrict_solve_to_is_local_size(void)const 00363 { 00364 libmesh_assert(_restrict_solve_to_is); 00365 00366 PetscInt s; 00367 int ierr = ISGetLocalSize(_restrict_solve_to_is,&s); 00368 LIBMESH_CHKERRABORT(ierr); 00369 00370 return s; 00371 } 00372 00373 00374 00375 template <typename T> 00376 void 00377 PetscLinearSolver<T>::_create_complement_is (const NumericVector<T> & 00378 #if PETSC_VERSION_LESS_THAN(3,0,0) 00379 // unnamed to avoid compiler "unused parameter" warning 00380 #else 00381 vec_in 00382 #endif 00383 ) 00384 { 00385 libmesh_assert(_restrict_solve_to_is); 00386 #if PETSC_VERSION_LESS_THAN(3,0,0) 00387 // No ISComplement in PETSc 2.3.3 00388 libmesh_not_implemented(); 00389 #else 00390 if(_restrict_solve_to_is_complement==NULL) 00391 { 00392 int ierr = ISComplement(_restrict_solve_to_is, 00393 vec_in.first_local_index(), 00394 vec_in.last_local_index(), 00395 &_restrict_solve_to_is_complement); 00396 LIBMESH_CHKERRABORT(ierr); 00397 } 00398 #endif 00399 } 00400 00401 00402 00403 } // namespace libMesh 00404 00405 00406 #endif // #ifdef LIBMESH_HAVE_PETSC 00407 #endif // LIBMESH_PETSC_LINEAR_SOLVER_H