$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 #include "libmesh/libmesh_common.h" 00021 00022 #if defined(LIBMESH_HAVE_LASPACK) 00023 00024 00025 // C++ includes 00026 00027 // Local Includes 00028 #include "libmesh/laspack_linear_solver.h" 00029 #include "libmesh/libmesh_logging.h" 00030 #include "libmesh/string_to_enum.h" 00031 00032 namespace libMesh 00033 { 00034 00035 // #ifndef LIBMESH_USE_COMPLEX_NUMBERS 00036 // extern "C" 00037 // { 00038 // #endif 00039 00040 // void print_iter_accuracy(int Iter, 00041 // _LPReal rNorm, 00042 // _LPReal bNorm, 00043 // IterIdType IterId) 00044 // /* put out accuracy reached after each solver iteration */ 00045 // { 00046 00047 // //FILE* out = fopen("residual.hist", "a"); 00048 // static int icall=0; 00049 00050 // if (!icall) 00051 // { 00052 // printf("Iter ||r||/||f||\n"); 00053 // printf("------------------\n"); 00054 // icall=1; 00055 // } 00056 00057 // if ( Iter%1==0 && (IterId == CGIterId || 00058 // IterId == CGNIterId || 00059 // IterId == GMRESIterId || 00060 // IterId == BiCGIterId || 00061 // IterId == QMRIterId || 00062 // IterId == CGSIterId || 00063 // IterId == BiCGSTABIterId) ) 00064 // { 00065 // if (!_LPIsZeroReal(bNorm)) 00066 // printf("%d \t %g\n", Iter, rNorm/bNorm); 00067 // else 00068 // printf("%d (fnorm == 0)\n", Iter); 00069 // } 00070 00071 // //fclose(out); 00072 // } 00073 00074 // #ifndef LIBMESH_USE_COMPLEX_NUMBERS 00075 // } 00076 // #endif 00077 00078 /*----------------------- functions ----------------------------------*/ 00079 template <typename T> 00080 void LaspackLinearSolver<T>::clear () 00081 { 00082 if (this->initialized()) 00083 { 00084 this->_is_initialized = false; 00085 00086 this->_solver_type = GMRES; 00087 this->_preconditioner_type = ILU_PRECOND; 00088 } 00089 } 00090 00091 00092 00093 template <typename T> 00094 void LaspackLinearSolver<T>::init (const char* /* name */) 00095 { 00096 // Initialize the data structures if not done so already. 00097 if (!this->initialized()) 00098 { 00099 this->_is_initialized = true; 00100 } 00101 00102 // SetRTCAuxProc (print_iter_accuracy); 00103 } 00104 00105 00106 00107 template <typename T> 00108 std::pair<unsigned int, Real> 00109 LaspackLinearSolver<T>::solve (SparseMatrix<T> &matrix_in, 00110 NumericVector<T> &solution_in, 00111 NumericVector<T> &rhs_in, 00112 const double tol, 00113 const unsigned int m_its) 00114 { 00115 START_LOG("solve()", "LaspackLinearSolver"); 00116 this->init (); 00117 00118 // Make sure the data passed in are really in Laspack types 00119 LaspackMatrix<T>* matrix = cast_ptr<LaspackMatrix<T>*>(&matrix_in); 00120 LaspackVector<T>* solution = cast_ptr<LaspackVector<T>*>(&solution_in); 00121 LaspackVector<T>* rhs = cast_ptr<LaspackVector<T>*>(&rhs_in); 00122 00123 // Zero-out the solution to prevent the solver from exiting in 0 00124 // iterations (?) 00125 //TODO:[BSK] Why does Laspack do this? Comment out this and try ex13... 00126 solution->zero(); 00127 00128 // Close the matrix and vectors in case this wasn't already done. 00129 matrix->close (); 00130 solution->close (); 00131 rhs->close (); 00132 00133 // Set the preconditioner type 00134 this->set_laspack_preconditioner_type (); 00135 00136 // Set the solver tolerance 00137 SetRTCAccuracy (tol); 00138 00139 // Solve the linear system 00140 switch (this->_solver_type) 00141 { 00142 // Conjugate-Gradient 00143 case CG: 00144 { 00145 CGIter (&matrix->_QMat, 00146 &solution->_vec, 00147 &rhs->_vec, 00148 m_its, 00149 _precond_type, 00150 1.); 00151 break; 00152 } 00153 00154 // Conjugate-Gradient Normalized 00155 case CGN: 00156 { 00157 CGNIter (&matrix->_QMat, 00158 &solution->_vec, 00159 &rhs->_vec, 00160 m_its, 00161 _precond_type, 00162 1.); 00163 break; 00164 } 00165 00166 // Conjugate-Gradient Squared 00167 case CGS: 00168 { 00169 CGSIter (&matrix->_QMat, 00170 &solution->_vec, 00171 &rhs->_vec, 00172 m_its, 00173 _precond_type, 00174 1.); 00175 break; 00176 } 00177 00178 // Bi-Conjugate Gradient 00179 case BICG: 00180 { 00181 BiCGIter (&matrix->_QMat, 00182 &solution->_vec, 00183 &rhs->_vec, 00184 m_its, 00185 _precond_type, 00186 1.); 00187 break; 00188 } 00189 00190 // Bi-Conjugate Gradient Stabilized 00191 case BICGSTAB: 00192 { 00193 BiCGSTABIter (&matrix->_QMat, 00194 &solution->_vec, 00195 &rhs->_vec, 00196 m_its, 00197 _precond_type, 00198 1.); 00199 break; 00200 } 00201 00202 // Quasi-Minimum Residual 00203 case QMR: 00204 { 00205 QMRIter (&matrix->_QMat, 00206 &solution->_vec, 00207 &rhs->_vec, 00208 m_its, 00209 _precond_type, 00210 1.); 00211 break; 00212 } 00213 00214 // Symmetric over-relaxation 00215 case SSOR: 00216 { 00217 SSORIter (&matrix->_QMat, 00218 &solution->_vec, 00219 &rhs->_vec, 00220 m_its, 00221 _precond_type, 00222 1.); 00223 break; 00224 } 00225 00226 // Jacobi Relaxation 00227 case JACOBI: 00228 { 00229 JacobiIter (&matrix->_QMat, 00230 &solution->_vec, 00231 &rhs->_vec, 00232 m_its, 00233 _precond_type, 00234 1.); 00235 break; 00236 } 00237 00238 // Generalized Minimum Residual 00239 case GMRES: 00240 { 00241 SetGMRESRestart (30); 00242 GMRESIter (&matrix->_QMat, 00243 &solution->_vec, 00244 &rhs->_vec, 00245 m_its, 00246 _precond_type, 00247 1.); 00248 break; 00249 } 00250 00251 // Unknown solver, use GMRES 00252 default: 00253 { 00254 libMesh::err << "ERROR: Unsupported LASPACK Solver: " 00255 << Utility::enum_to_string(this->_solver_type) << std::endl 00256 << "Continuing with GMRES" << std::endl; 00257 00258 this->_solver_type = GMRES; 00259 00260 return this->solve (*matrix, 00261 *solution, 00262 *rhs, 00263 tol, 00264 m_its); 00265 } 00266 } 00267 00268 // Check for an error 00269 if (LASResult() != LASOK) 00270 { 00271 WriteLASErrDescr(stdout); 00272 libmesh_error_msg("Exiting after LASPACK Error!"); 00273 } 00274 00275 STOP_LOG("solve()", "LaspackLinearSolver"); 00276 // Get the convergence step # and residual 00277 return std::make_pair(GetLastNoIter(), GetLastAccuracy()); 00278 } 00279 00280 00281 00282 template <typename T> 00283 std::pair<unsigned int, Real> 00284 LaspackLinearSolver<T>::adjoint_solve (SparseMatrix<T> &matrix_in, 00285 NumericVector<T> &solution_in, 00286 NumericVector<T> &rhs_in, 00287 const double tol, 00288 const unsigned int m_its) 00289 { 00290 START_LOG("adjoint_solve()", "LaspackLinearSolver"); 00291 this->init (); 00292 00293 // Make sure the data passed in are really in Laspack types 00294 LaspackMatrix<T>* matrix = cast_ptr<LaspackMatrix<T>*>(&matrix_in); 00295 LaspackVector<T>* solution = cast_ptr<LaspackVector<T>*>(&solution_in); 00296 LaspackVector<T>* rhs = cast_ptr<LaspackVector<T>*>(&rhs_in); 00297 00298 // Zero-out the solution to prevent the solver from exiting in 0 00299 // iterations (?) 00300 //TODO:[BSK] Why does Laspack do this? Comment out this and try ex13... 00301 solution->zero(); 00302 00303 // Close the matrix and vectors in case this wasn't already done. 00304 matrix->close (); 00305 solution->close (); 00306 rhs->close (); 00307 00308 // Set the preconditioner type 00309 this->set_laspack_preconditioner_type (); 00310 00311 // Set the solver tolerance 00312 SetRTCAccuracy (tol); 00313 00314 // Solve the linear system 00315 switch (this->_solver_type) 00316 { 00317 // Conjugate-Gradient 00318 case CG: 00319 { 00320 CGIter (Transp_Q(&matrix->_QMat), 00321 &solution->_vec, 00322 &rhs->_vec, 00323 m_its, 00324 _precond_type, 00325 1.); 00326 break; 00327 } 00328 00329 // Conjugate-Gradient Normalized 00330 case CGN: 00331 { 00332 CGNIter (Transp_Q(&matrix->_QMat), 00333 &solution->_vec, 00334 &rhs->_vec, 00335 m_its, 00336 _precond_type, 00337 1.); 00338 break; 00339 } 00340 00341 // Conjugate-Gradient Squared 00342 case CGS: 00343 { 00344 CGSIter (Transp_Q(&matrix->_QMat), 00345 &solution->_vec, 00346 &rhs->_vec, 00347 m_its, 00348 _precond_type, 00349 1.); 00350 break; 00351 } 00352 00353 // Bi-Conjugate Gradient 00354 case BICG: 00355 { 00356 BiCGIter (Transp_Q(&matrix->_QMat), 00357 &solution->_vec, 00358 &rhs->_vec, 00359 m_its, 00360 _precond_type, 00361 1.); 00362 break; 00363 } 00364 00365 // Bi-Conjugate Gradient Stabilized 00366 case BICGSTAB: 00367 { 00368 BiCGSTABIter (Transp_Q(&matrix->_QMat), 00369 &solution->_vec, 00370 &rhs->_vec, 00371 m_its, 00372 _precond_type, 00373 1.); 00374 break; 00375 } 00376 00377 // Quasi-Minimum Residual 00378 case QMR: 00379 { 00380 QMRIter (Transp_Q(&matrix->_QMat), 00381 &solution->_vec, 00382 &rhs->_vec, 00383 m_its, 00384 _precond_type, 00385 1.); 00386 break; 00387 } 00388 00389 // Symmetric over-relaxation 00390 case SSOR: 00391 { 00392 SSORIter (Transp_Q(&matrix->_QMat), 00393 &solution->_vec, 00394 &rhs->_vec, 00395 m_its, 00396 _precond_type, 00397 1.); 00398 break; 00399 } 00400 00401 // Jacobi Relaxation 00402 case JACOBI: 00403 { 00404 JacobiIter (Transp_Q(&matrix->_QMat), 00405 &solution->_vec, 00406 &rhs->_vec, 00407 m_its, 00408 _precond_type, 00409 1.); 00410 break; 00411 } 00412 00413 // Generalized Minimum Residual 00414 case GMRES: 00415 { 00416 SetGMRESRestart (30); 00417 GMRESIter (Transp_Q(&matrix->_QMat), 00418 &solution->_vec, 00419 &rhs->_vec, 00420 m_its, 00421 _precond_type, 00422 1.); 00423 break; 00424 } 00425 00426 // Unknown solver, use GMRES 00427 default: 00428 { 00429 libMesh::err << "ERROR: Unsupported LASPACK Solver: " 00430 << Utility::enum_to_string(this->_solver_type) << std::endl 00431 << "Continuing with GMRES" << std::endl; 00432 00433 this->_solver_type = GMRES; 00434 00435 return this->solve (*matrix, 00436 *solution, 00437 *rhs, 00438 tol, 00439 m_its); 00440 } 00441 } 00442 00443 // Check for an error 00444 if (LASResult() != LASOK) 00445 { 00446 WriteLASErrDescr(stdout); 00447 libmesh_error_msg("Exiting after LASPACK Error!"); 00448 } 00449 00450 STOP_LOG("adjoint_solve()", "LaspackLinearSolver"); 00451 // Get the convergence step # and residual 00452 return std::make_pair(GetLastNoIter(), GetLastAccuracy()); 00453 } 00454 00455 00456 00457 00458 template <typename T> 00459 std::pair<unsigned int, Real> 00460 LaspackLinearSolver<T>::solve (const ShellMatrix<T>& /*shell_matrix*/, 00461 NumericVector<T>& /*solution_in*/, 00462 NumericVector<T>& /*rhs_in*/, 00463 const double /*tol*/, 00464 const unsigned int /*m_its*/) 00465 { 00466 libmesh_not_implemented(); 00467 return std::make_pair(0,0.0); 00468 } 00469 00470 00471 00472 template <typename T> 00473 std::pair<unsigned int, Real> 00474 LaspackLinearSolver<T>::solve (const ShellMatrix<T>& /*shell_matrix*/, 00475 const SparseMatrix<T>& /*precond_matrix*/, 00476 NumericVector<T>& /*solution_in*/, 00477 NumericVector<T>& /*rhs_in*/, 00478 const double /*tol*/, 00479 const unsigned int /*m_its*/) 00480 { 00481 libmesh_not_implemented(); 00482 return std::make_pair(0,0.0); 00483 } 00484 00485 00486 00487 template <typename T> 00488 void LaspackLinearSolver<T>::set_laspack_preconditioner_type () 00489 { 00490 switch (this->_preconditioner_type) 00491 { 00492 case IDENTITY_PRECOND: 00493 _precond_type = NULL; return; 00494 00495 case ILU_PRECOND: 00496 _precond_type = ILUPrecond; return; 00497 00498 case JACOBI_PRECOND: 00499 _precond_type = JacobiPrecond; return; 00500 00501 case SSOR_PRECOND: 00502 _precond_type = SSORPrecond; return; 00503 00504 00505 default: 00506 libMesh::err << "ERROR: Unsupported LASPACK Preconditioner: " 00507 << this->_preconditioner_type << std::endl 00508 << "Continuing with ILU" << std::endl; 00509 this->_preconditioner_type = ILU_PRECOND; 00510 this->set_laspack_preconditioner_type(); 00511 } 00512 } 00513 00514 00515 00516 template <typename T> 00517 void LaspackLinearSolver<T>::print_converged_reason() const 00518 { 00519 libMesh::out << "print_converged_reason() is currently only supported" 00520 << "with Petsc 2.3.1 and later." << std::endl; 00521 } 00522 00523 00524 00525 template <typename T> 00526 LinearConvergenceReason LaspackLinearSolver<T>::get_converged_reason() const 00527 { 00528 libmesh_not_implemented(); 00529 } 00530 00531 00532 00533 //------------------------------------------------------------------ 00534 // Explicit instantiations 00535 template class LaspackLinearSolver<Number>; 00536 00537 } // namespace libMesh 00538 00539 00540 #endif // #ifdef LIBMESH_HAVE_LASPACK