petsc_dm_nonlinear_solver.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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 #include "libmesh/petsc_macro.h" 00020 00021 // This only works with petsc-3.3 and above. 00022 #if !PETSC_VERSION_LESS_THAN(3,3,0) 00023 00024 // Local Includes 00025 #include "libmesh/libmesh_common.h" 00026 #include "libmesh/nonlinear_implicit_system.h" 00027 #include "libmesh/petsc_dm_nonlinear_solver.h" 00028 #include "libmesh/petsc_linear_solver.h" 00029 #include "libmesh/petsc_vector.h" 00030 #include "libmesh/petsc_matrix.h" 00031 #include "libmesh/dof_map.h" 00032 #include "libmesh/preconditioner.h" 00033 00034 // PETSc extern definition 00035 EXTERN_C_BEGIN 00036 PetscErrorCode DMCreate_libMesh(DM); 00037 EXTERN_C_END 00038 00039 #include <libmesh/petscdmlibmesh.h> 00040 00041 namespace libMesh { 00042 PetscBool PetscDMRegistered = PETSC_FALSE; 00043 void PetscDMRegister() 00044 { 00045 if (PetscDMRegistered) 00046 return; 00047 00048 PetscErrorCode ierr; 00049 ierr = DMRegister(DMLIBMESH, PETSC_NULL, "DMCreate_libMesh", DMCreate_libMesh); CHKERRABORT(libMesh::COMM_WORLD, ierr); 00050 PetscDMRegistered = PETSC_TRUE; 00051 } 00052 00053 00054 template <typename T> 00055 PetscDMNonlinearSolver<T>::PetscDMNonlinearSolver(sys_type& system_in) : 00056 PetscNonlinearSolver<T>(system_in) 00057 { 00058 PetscDMRegister(); 00059 } 00060 00061 template <typename T> 00062 inline 00063 PetscDMNonlinearSolver<T>::~PetscDMNonlinearSolver () 00064 { 00065 this->clear (); 00066 } 00067 00068 00069 00070 template <typename T> 00071 void PetscDMNonlinearSolver<T>::init() 00072 { 00073 PetscErrorCode ierr; 00074 DM dm; 00075 this->PetscNonlinearSolver<T>::init(); 00076 00077 // Attaching a DM with the function and Jacobian callbacks to SNES. 00078 ierr = DMCreateLibMesh(libMesh::COMM_WORLD, this->system(), &dm); CHKERRABORT(libMesh::COMM_WORLD, ierr); 00079 ierr = DMSetFromOptions(dm); CHKERRABORT(libMesh::COMM_WORLD, ierr); 00080 ierr = DMSetUp(dm); CHKERRABORT(libMesh::COMM_WORLD, ierr); 00081 ierr = SNESSetDM(this->_snes, dm); CHKERRABORT(libMesh::COMM_WORLD, ierr); 00082 // SNES now owns the reference to dm. 00083 ierr = DMDestroy(&dm); CHKERRABORT(libMesh::COMM_WORLD, ierr); 00084 KSP ksp; 00085 ierr = SNESGetKSP (this->_snes, &ksp); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00086 00087 // Set the tolerances for the iterative solver. Use the user-supplied 00088 // tolerance for the relative residual & leave the others at default values 00089 ierr = KSPSetTolerances (ksp, this->initial_linear_tolerance, PETSC_DEFAULT,PETSC_DEFAULT, this->max_linear_iterations); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00090 00091 // Set the tolerances for the non-linear solver. 00092 ierr = SNESSetTolerances(this->_snes, 00093 this->absolute_residual_tolerance, 00094 this->relative_residual_tolerance, 00095 this->absolute_step_tolerance, 00096 this->max_nonlinear_iterations, 00097 this->max_function_evaluations); 00098 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00099 00100 //Pull in command-line options 00101 KSPSetFromOptions(ksp); 00102 SNESSetFromOptions(this->_snes); 00103 } 00104 00105 00106 template <typename T> 00107 std::pair<unsigned int, Real> 00108 PetscDMNonlinearSolver<T>::solve (SparseMatrix<T>& jac_in, // System Jacobian Matrix 00109 NumericVector<T>& x_in, // Solution vector 00110 NumericVector<T>& r_in, // Residual vector 00111 const double, // Stopping tolerance 00112 const unsigned int) 00113 { 00114 START_LOG("solve()", "PetscNonlinearSolver"); 00115 this->init (); 00116 00117 // Make sure the data passed in are really of Petsc types 00118 libmesh_cast_ptr<PetscMatrix<T>*>(&jac_in); 00119 libmesh_cast_ptr<PetscVector<T>*>(&r_in); 00120 00121 // Extract solution vector 00122 PetscVector<T>* x = libmesh_cast_ptr<PetscVector<T>*>(&x_in); 00123 00124 int ierr=0; 00125 int n_iterations =0; 00126 00127 // Should actually be a PetscReal, but I don't know which version of PETSc first introduced PetscReal 00128 Real final_residual_norm=0.; 00129 00130 if (this->user_presolve) 00131 this->user_presolve(this->system()); 00132 00133 //Set the preconditioning matrix 00134 if (this->_preconditioner) 00135 this->_preconditioner->set_matrix(jac_in); 00136 00137 ierr = SNESSolve (this->_snes, PETSC_NULL, x->vec()); 00138 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00139 00140 ierr = SNESGetIterationNumber(this->_snes,&n_iterations); 00141 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00142 00143 ierr = SNESGetLinearSolveIterations(this->_snes, &this->_n_linear_iterations); 00144 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00145 00146 ierr = SNESGetFunctionNorm(this->_snes,&final_residual_norm); 00147 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00148 00149 // Get and store the reason for convergence 00150 SNESGetConvergedReason(this->_snes, &this->_reason); 00151 00152 //Based on Petsc 2.3.3 documentation all diverged reasons are negative 00153 this->converged = (this->_reason >= 0); 00154 00155 this->clear(); 00156 00157 STOP_LOG("solve()", "PetscNonlinearSolver"); 00158 00159 // return the # of its. and the final residual norm. 00160 return std::make_pair(n_iterations, final_residual_norm); 00161 } 00162 00163 00164 //------------------------------------------------------------------ 00165 // Explicit instantiations 00166 template class PetscDMNonlinearSolver<Number>; 00167 00168 } // namespace libMesh 00169 00170 00171 #endif // #if !PETSC_VERSION_LESS_THAN(3,3,0)
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:48 UTC
Hosted By: