trilinos_aztec_linear_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 00020 #include "libmesh/libmesh_common.h" 00021 00022 #ifdef LIBMESH_HAVE_AZTECOO 00023 00024 00025 // C++ includes 00026 00027 // Local Includes 00028 #include "libmesh/libmesh_logging.h" 00029 #include "libmesh/trilinos_aztec_linear_solver.h" 00030 #include "libmesh/trilinos_epetra_matrix.h" 00031 #include "libmesh/trilinos_epetra_vector.h" 00032 00033 namespace libMesh 00034 { 00035 00036 00037 /*----------------------- functions ----------------------------------*/ 00038 template <typename T> 00039 void AztecLinearSolver<T>::clear () 00040 { 00041 if (this->initialized()) 00042 { 00043 this->_is_initialized = false; 00044 00045 // Mimic PETSc default solver and preconditioner 00046 this->_solver_type = GMRES; 00047 00048 if (libMesh::n_processors() == 1) 00049 this->_preconditioner_type = ILU_PRECOND; 00050 else 00051 this->_preconditioner_type = BLOCK_JACOBI_PRECOND; 00052 } 00053 } 00054 00055 00056 00057 template <typename T> 00058 void AztecLinearSolver<T>::init () 00059 { 00060 // Initialize the data structures if not done so already. 00061 if (!this->initialized()) 00062 { 00063 this->_is_initialized = true; 00064 00065 _linear_solver = new AztecOO(); 00066 00067 set_solver_type(); 00068 00069 switch(this->_preconditioner_type) 00070 { 00071 case ILU_PRECOND: 00072 _linear_solver->SetAztecOption(AZ_precond,AZ_dom_decomp); 00073 _linear_solver->SetAztecOption(AZ_subdomain_solve,AZ_ilu); 00074 break; 00075 00076 case BLOCK_JACOBI_PRECOND: 00077 _linear_solver->SetAztecOption(AZ_precond,AZ_Jacobi); 00078 break; 00079 00080 case ICC_PRECOND: 00081 _linear_solver->SetAztecOption(AZ_precond,AZ_dom_decomp); 00082 _linear_solver->SetAztecOption(AZ_subdomain_solve,AZ_icc); 00083 break; 00084 00085 case LU_PRECOND: 00086 _linear_solver->SetAztecOption(AZ_precond,AZ_dom_decomp); 00087 _linear_solver->SetAztecOption(AZ_subdomain_solve,AZ_lu); 00088 break; 00089 00090 default: 00091 _linear_solver->SetAztecOption(AZ_precond,AZ_dom_decomp); 00092 _linear_solver->SetAztecOption(AZ_subdomain_solve,AZ_ilu); 00093 } 00094 } 00095 } 00096 00097 00098 00099 00100 template <typename T> 00101 std::pair<unsigned int, Real> 00102 AztecLinearSolver<T>::solve (SparseMatrix<T>& matrix_in, 00103 SparseMatrix<T>& precond_in, 00104 NumericVector<T>& solution_in, 00105 NumericVector<T>& rhs_in, 00106 const double tol, 00107 const unsigned int m_its) 00108 { 00109 START_LOG("solve()", "AztecLinearSolver"); 00110 00111 // Make sure the data passed in are really of Epetra types 00112 EpetraMatrix<T>* matrix = libmesh_cast_ptr<EpetraMatrix<T>*>(&matrix_in); 00113 EpetraMatrix<T>* precond = libmesh_cast_ptr<EpetraMatrix<T>*>(&precond_in); 00114 EpetraVector<T>* solution = libmesh_cast_ptr<EpetraVector<T>*>(&solution_in); 00115 EpetraVector<T>* rhs = libmesh_cast_ptr<EpetraVector<T>*>(&rhs_in); 00116 00117 this->init(); 00118 00119 // Close the matrices and vectors in case this wasn't already done. 00120 matrix->close (); 00121 precond->close (); 00122 solution->close (); 00123 rhs->close (); 00124 00125 _linear_solver->SetAztecOption(AZ_max_iter,m_its); 00126 _linear_solver->SetAztecParam(AZ_tol,tol); 00127 00128 Epetra_FECrsMatrix * emat = matrix->mat(); 00129 Epetra_Vector * esol = solution->vec(); 00130 Epetra_Vector * erhs = rhs->vec(); 00131 00132 _linear_solver->Iterate(emat, esol, erhs, m_its, tol); 00133 00134 STOP_LOG("solve()", "AztecLinearSolver"); 00135 00136 // return the # of its. and the final residual norm. 00137 return std::make_pair(_linear_solver->NumIters(), _linear_solver->TrueResidual()); 00138 } 00139 00140 00141 00142 template <typename T> 00143 std::pair<unsigned int, Real> 00144 AztecLinearSolver<T>::solve (const ShellMatrix<T>&, 00145 NumericVector<T>&, 00146 NumericVector<T>&, 00147 const double, 00148 const unsigned int) 00149 //AztecLinearSolver<T>::solve (const ShellMatrix<T>& shell_matrix, 00150 // NumericVector<T>& solution_in, 00151 // NumericVector<T>& rhs_in, 00152 // const double tol, 00153 // const unsigned int m_its) 00154 { 00155 libmesh_not_implemented(); 00156 } 00157 00158 00159 00160 template <typename T> 00161 std::pair<unsigned int, Real> 00162 AztecLinearSolver<T>::solve (const ShellMatrix<T>&, 00163 const SparseMatrix<T>&, 00164 NumericVector<T> &, 00165 NumericVector<T> &, 00166 const double, 00167 const unsigned int) 00168 //AztecLinearSolver<T>::solve (const ShellMatrix<T>& shell_matrix, 00169 // const SparseMatrix<T>& precond_matrix, 00170 // NumericVector<T> &solution_in, 00171 // NumericVector<T> &rhs_in, 00172 // const double tol, 00173 // const unsigned int m_its) 00174 { 00175 libmesh_not_implemented(); 00176 } 00177 00178 00179 00180 template <typename T> 00181 void AztecLinearSolver<T>::get_residual_history(std::vector<double>& /* hist */) 00182 { 00183 libmesh_not_implemented(); 00184 00185 // int ierr = 0; 00186 // int its = 0; 00187 00188 // // Fill the residual history vector with the residual norms 00189 // // Note that GetResidualHistory() does not copy any values, it 00190 // // simply sets the pointer p. Note that for some Krylov subspace 00191 // // methods, the number of residuals returned in the history 00192 // // vector may be different from what you are expecting. For 00193 // // example, TFQMR returns two residual values per iteration step. 00194 // PetscReal* p; 00195 // ierr = KSPGetResidualHistory(_ksp, &p, &its); 00196 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00197 00198 // // Check for early return 00199 // if (its == 0) return; 00200 00201 // // Create space to store the result 00202 // hist.resize(its); 00203 00204 // // Copy history into the vector provided by the user. 00205 // for (int i=0; i<its; ++i) 00206 // { 00207 // hist[i] = *p; 00208 // p++; 00209 // } 00210 } 00211 00212 00213 00214 00215 template <typename T> 00216 Real AztecLinearSolver<T>::get_initial_residual() 00217 { 00218 return _linear_solver->TrueResidual(); 00219 } 00220 00221 00222 00223 template <typename T> 00224 void AztecLinearSolver<T>::print_converged_reason() 00225 { 00226 libmesh_not_implemented(); 00227 00228 // #if PETSC_VERSION_LESS_THAN(2,3,1) 00229 // libMesh::out << "This method is currently not supported " 00230 // << "(but may work!) for Petsc 2.3.0 and earlier." << std::endl; 00231 // #else 00232 // KSPConvergedReason reason; 00233 // KSPGetConvergedReason(_ksp, &reason); 00234 00235 // // KSP_CONVERGED_RTOL (residual 2-norm decreased by a factor of rtol, from 2-norm of right hand side) 00236 // // KSP_CONVERGED_ATOL (residual 2-norm less than abstol) 00237 // // KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration) 00238 // // KSP_CONVERGED_STEP_LENGTH 00239 // // KSP_DIVERGED_ITS (required more than its to reach convergence) 00240 // // KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol) 00241 // // KSP_DIVERGED_NAN (residual norm became Not-a-number likely do to 0/0) 00242 // // KSP_DIVERGED_BREAKDOWN (generic breakdown in method) 00243 00244 // switch (reason) 00245 // { 00246 // case KSP_CONVERGED_RTOL: 00247 // { 00248 // libMesh::out << "Linear solver converged, relative tolerance reached." << std::endl; 00249 // break; 00250 // } 00251 // case KSP_CONVERGED_ATOL: 00252 // { 00253 // libMesh::out << "Linear solver converged, absolute tolerance reached." << std::endl; 00254 // break; 00255 // } 00256 00257 // // Divergence 00258 // case KSP_DIVERGED_ITS: 00259 // { 00260 // libMesh::out << "Linear solver diverged, max no. of iterations reached." << std::endl; 00261 // break; 00262 // } 00263 // case KSP_DIVERGED_DTOL: 00264 // { 00265 // libMesh::out << "Linear solver diverged, residual norm increase by dtol (default 1.e5)." << std::endl; 00266 // break; 00267 // } 00268 // case KSP_DIVERGED_NAN: 00269 // { 00270 // libMesh::out << "Linear solver diverged, residual norm is NaN." << std::endl; 00271 // break; 00272 // } 00273 // case KSP_DIVERGED_BREAKDOWN: 00274 // { 00275 // libMesh::out << "Linear solver diverged, generic breakdown in the method." << std::endl; 00276 // break; 00277 // } 00278 // default: 00279 // { 00280 // libMesh::out << "Unknown/unsupported con(di)vergence reason: " << reason << std::endl; 00281 // } 00282 // } 00283 // #endif 00284 } 00285 00286 template <typename T> 00287 void AztecLinearSolver<T>::set_solver_type() 00288 { 00289 switch (this->_solver_type) 00290 { 00291 case CG: 00292 _linear_solver->SetAztecOption(AZ_solver, AZ_cg); return; 00293 00294 case CGS: 00295 _linear_solver->SetAztecOption(AZ_solver, AZ_cgs); return; 00296 00297 case TFQMR: 00298 _linear_solver->SetAztecOption(AZ_solver, AZ_tfqmr); return; 00299 00300 case BICGSTAB: 00301 _linear_solver->SetAztecOption(AZ_solver, AZ_bicgstab); return; 00302 00303 case GMRES: 00304 _linear_solver->SetAztecOption(AZ_solver, AZ_gmres); return; 00305 00306 default: 00307 libMesh::err << "ERROR: Unsupported AztecOO Solver: " 00308 << this->_solver_type << std::endl 00309 << "Continuing with AztecOO defaults" << std::endl; 00310 } 00311 } 00312 00313 //------------------------------------------------------------------ 00314 // Explicit instantiations 00315 template class AztecLinearSolver<Number>; 00316 00317 } // namespace libMesh 00318 00319 00320 00321 #endif // #ifdef LIBMESH_HAVE_AZTECOO
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:49 UTC
Hosted By: