$extrastylesheet
petsc_linear_solver.h
Go to the documentation of this file.
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