$extrastylesheet
laspack_linear_solver.C
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 #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