$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 #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