$extrastylesheet
eigen_sparse_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 #ifdef LIBMESH_HAVE_EIGEN
00023 
00024 
00025 // C++ includes
00026 
00027 // Local Includes
00028 #include "libmesh/eigen_sparse_linear_solver.h"
00029 #include "libmesh/libmesh_logging.h"
00030 #include "libmesh/string_to_enum.h"
00031 
00032 namespace libMesh
00033 {
00034 
00035 /*----------------------- functions ----------------------------------*/
00036 template <typename T>
00037 void EigenSparseLinearSolver<T>::clear ()
00038 {
00039   if (this->initialized())
00040     {
00041       this->_is_initialized = false;
00042 
00043       this->_solver_type         = BICGSTAB;
00044       this->_preconditioner_type = ILU_PRECOND;
00045     }
00046 }
00047 
00048 
00049 
00050 template <typename T>
00051 void EigenSparseLinearSolver<T>::init (const char* /*name*/)
00052 {
00053   // Initialize the data structures if not done so already.
00054   if (!this->initialized())
00055     {
00056       this->_is_initialized = true;
00057     }
00058 }
00059 
00060 
00061 
00062 template <typename T>
00063 std::pair<unsigned int, Real>
00064 EigenSparseLinearSolver<T>::solve (SparseMatrix<T> &matrix_in,
00065                                    NumericVector<T> &solution_in,
00066                                    NumericVector<T> &rhs_in,
00067                                    const double tol,
00068                                    const unsigned int m_its)
00069 {
00070   START_LOG("solve()", "EigenSparseLinearSolver");
00071   this->init ();
00072 
00073   // Make sure the data passed in are really Eigen types
00074   EigenSparseMatrix<T>& matrix   = cast_ref<EigenSparseMatrix<T>&>(matrix_in);
00075   EigenSparseVector<T>& solution = cast_ref<EigenSparseVector<T>&>(solution_in);
00076   EigenSparseVector<T>& rhs      = cast_ref<EigenSparseVector<T>&>(rhs_in);
00077 
00078   // Close the matrix and vectors in case this wasn't already done.
00079   matrix.close();
00080   solution.close();
00081   rhs.close();
00082 
00083   std::pair<unsigned int, Real> retval(0,0.);
00084 
00085   // Solve the linear system
00086   switch (this->_solver_type)
00087     {
00088       // Conjugate-Gradient
00089     case CG:
00090       {
00091         Eigen::ConjugateGradient<EigenSM> solver (matrix._mat);
00092         solver.setMaxIterations(m_its);
00093         solver.setTolerance(tol);
00094         solution._vec = solver.solveWithGuess(rhs._vec,solution._vec);
00095         libMesh::out << "#iterations: " << solver.iterations() << std::endl;
00096         libMesh::out << "estimated error: " << solver.error() << std::endl;
00097         retval = std::make_pair(solver.iterations(), solver.error());
00098         break;
00099       }
00100 
00101       // Bi-Conjugate Gradient Stabilized
00102     case BICGSTAB:
00103       {
00104         Eigen::BiCGSTAB<EigenSM> solver (matrix._mat);
00105         solver.setMaxIterations(m_its);
00106         solver.setTolerance(tol);
00107         solution._vec = solver.solveWithGuess(rhs._vec,solution._vec);
00108         libMesh::out << "#iterations: " << solver.iterations() << std::endl;
00109         libMesh::out << "estimated error: " << solver.error() << std::endl;
00110         retval = std::make_pair(solver.iterations(), solver.error());
00111         break;
00112       }
00113 
00114       //   // Generalized Minimum Residual
00115       // case GMRES:
00116       //   {
00117       // libmesh_not_implemented();
00118       // break;
00119       //   }
00120 
00121       // Unknown solver, use BICGSTAB
00122     default:
00123       {
00124         libMesh::err << "ERROR:  Unsupported Eigen Solver: "
00125                      << Utility::enum_to_string(this->_solver_type) << std::endl
00126                      << "Continuing with BICGSTAB" << std::endl;
00127 
00128         this->_solver_type = BICGSTAB;
00129 
00130         STOP_LOG("solve()", "EigenSparseLinearSolver");
00131 
00132         return this->solve (matrix,
00133                             solution,
00134                             rhs,
00135                             tol,
00136                             m_its);
00137       }
00138     }
00139 
00140   STOP_LOG("solve()", "EigenSparseLinearSolver");
00141   return retval;
00142 }
00143 
00144 
00145 
00146 template <typename T>
00147 std::pair<unsigned int, Real>
00148 EigenSparseLinearSolver<T>::adjoint_solve (SparseMatrix<T> &matrix_in,
00149                                            NumericVector<T> &solution_in,
00150                                            NumericVector<T> &rhs_in,
00151                                            const double tol,
00152                                            const unsigned int m_its)
00153 {
00154 
00155   START_LOG("adjoint_solve()", "EigenSparseLinearSolver");
00156 
00157   libmesh_experimental();
00158   EigenSparseMatrix<T> mat_trans(this->comm());
00159   matrix_in.get_transpose(mat_trans);
00160 
00161   std::pair<unsigned int, Real> retval = this->solve (mat_trans,
00162                                                       solution_in,
00163                                                       rhs_in,
00164                                                       tol,
00165                                                       m_its);
00166 
00167   STOP_LOG("adjoint_solve()", "EigenSparseLinearSolver");
00168 
00169   return retval;
00170 }
00171 
00172 
00173 
00174 
00175 template <typename T>
00176 std::pair<unsigned int, Real>
00177 EigenSparseLinearSolver<T>::solve (const ShellMatrix<T>& /*shell_matrix*/,
00178                                    NumericVector<T>& /*solution_in*/,
00179                                    NumericVector<T>& /*rhs_in*/,
00180                                    const double /*tol*/,
00181                                    const unsigned int /*m_its*/)
00182 {
00183   libmesh_not_implemented();
00184   return std::make_pair(0,0.0);
00185 }
00186 
00187 
00188 
00189 template <typename T>
00190 std::pair<unsigned int, Real>
00191 EigenSparseLinearSolver<T>::solve (const ShellMatrix<T>& /*shell_matrix*/,
00192                                    const SparseMatrix<T>& /*precond_matrix*/,
00193                                    NumericVector<T>& /*solution_in*/,
00194                                    NumericVector<T>& /*rhs_in*/,
00195                                    const double /*tol*/,
00196                                    const unsigned int /*m_its*/)
00197 {
00198   libmesh_not_implemented();
00199   return std::make_pair(0,0.0);
00200 }
00201 
00202 
00203 
00204 template <typename T>
00205 void EigenSparseLinearSolver<T>::set_eigen_preconditioner_type ()
00206 {
00207   libmesh_not_implemented();
00208 
00209   // switch (this->_preconditioner_type)
00210   //   {
00211   //   case IDENTITY_PRECOND:
00212   //     _precond_type = NULL; return;
00213 
00214   //   case ILU_PRECOND:
00215   //     _precond_type = ILUPrecond; return;
00216 
00217   //   case JACOBI_PRECOND:
00218   //     _precond_type = JacobiPrecond; return;
00219 
00220   //   case SSOR_PRECOND:
00221   //     _precond_type = SSORPrecond; return;
00222 
00223 
00224   //   default:
00225   //     libMesh::err << "ERROR:  Unsupported LASPACK Preconditioner: "
00226   //     << this->_preconditioner_type << std::endl
00227   //     << "Continuing with ILU"      << std::endl;
00228   //     this->_preconditioner_type = ILU_PRECOND;
00229   //     this->set_laspack_preconditioner_type();
00230   //   }
00231 }
00232 
00233 
00234 
00235 template <typename T>
00236 void EigenSparseLinearSolver<T>::print_converged_reason() const
00237 {
00238   libMesh::out << "print_converged_reason() is currently only supported"
00239                << "with Petsc 2.3.1 and later." << std::endl;
00240 }
00241 
00242 
00243 
00244 template <typename T>
00245 LinearConvergenceReason EigenSparseLinearSolver<T>::get_converged_reason() const
00246 {
00247   libmesh_not_implemented();
00248 }
00249 
00250 
00251 
00252 //------------------------------------------------------------------
00253 // Explicit instantiations
00254 template class EigenSparseLinearSolver<Number>;
00255 
00256 } // namespace libMesh
00257 
00258 
00259 #endif // #ifdef LIBMESH_HAVE_EIGEN