$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 #include "libmesh/libmesh_config.h" 00020 00021 // Currently, the EigenSystem should only be available 00022 // if SLEPc support is enabled. 00023 #if defined(LIBMESH_HAVE_SLEPC) 00024 00025 // C++ includes 00026 00027 // Local includes 00028 #include "libmesh/eigen_system.h" 00029 #include "libmesh/equation_systems.h" 00030 #include "libmesh/sparse_matrix.h" 00031 #include "libmesh/eigen_solver.h" 00032 #include "libmesh/dof_map.h" 00033 #include "libmesh/mesh_base.h" 00034 00035 namespace libMesh 00036 { 00037 00038 00039 // ------------------------------------------------------------ 00040 // EigenSystem implementation 00041 EigenSystem::EigenSystem (EquationSystems& es, 00042 const std::string& name_in, 00043 const unsigned int number_in 00044 ) : 00045 Parent (es, name_in, number_in), 00046 matrix_A (NULL), 00047 matrix_B (NULL), 00048 eigen_solver (EigenSolver<Number>::build(es.comm())), 00049 _n_converged_eigenpairs (0), 00050 _n_iterations (0), 00051 _is_generalized_eigenproblem (false), 00052 _eigen_problem_type (NHEP) 00053 { 00054 } 00055 00056 00057 00058 EigenSystem::~EigenSystem () 00059 { 00060 // clear data 00061 this->clear(); 00062 } 00063 00064 00065 00066 void EigenSystem::clear () 00067 { 00068 // Clear the parent data 00069 Parent::clear(); 00070 00071 // delete the matricies 00072 delete matrix_A; 00073 delete matrix_B; 00074 00075 // NULL-out the matricies. 00076 matrix_A = NULL; 00077 matrix_B = NULL; 00078 00079 // clear the solver 00080 eigen_solver->clear(); 00081 00082 } 00083 00084 00085 void EigenSystem::set_eigenproblem_type (EigenProblemType ept) 00086 { 00087 _eigen_problem_type = ept; 00088 00089 eigen_solver->set_eigenproblem_type(ept); 00090 00091 // libMesh::out << "The Problem type is set to be: " << std::endl; 00092 00093 switch (_eigen_problem_type) 00094 { 00095 case HEP: 00096 // libMesh::out << "Hermitian" << std::endl; 00097 break; 00098 00099 case NHEP: 00100 // libMesh::out << "Non-Hermitian" << std::endl; 00101 break; 00102 00103 case GHEP: 00104 // libMesh::out << "Gerneralized Hermitian" << std::endl; 00105 break; 00106 00107 case GNHEP: 00108 // libMesh::out << "Generalized Non-Hermitian" << std::endl; 00109 break; 00110 00111 case GHIEP: 00112 // libMesh::out << "Generalized indefinite Hermitian" << std::endl; 00113 break; 00114 00115 default: 00116 // libMesh::out << "not properly specified" << std::endl; 00117 libmesh_error_msg("Unrecognized _eigen_problem_type = " << _eigen_problem_type); 00118 } 00119 } 00120 00121 00122 00123 00124 void EigenSystem::init_data () 00125 { 00126 // initialize parent data 00127 Parent::init_data(); 00128 00129 // define the type of eigenproblem 00130 if (_eigen_problem_type == GNHEP || 00131 _eigen_problem_type == GHEP || 00132 _eigen_problem_type == GHIEP) 00133 _is_generalized_eigenproblem = true; 00134 00135 // build the system matrix 00136 matrix_A = SparseMatrix<Number>::build(this->comm()).release(); 00137 00138 this->init_matrices(); 00139 } 00140 00141 00142 00143 void EigenSystem::init_matrices () 00144 { 00145 DofMap& dof_map = this->get_dof_map(); 00146 00147 dof_map.attach_matrix(*matrix_A); 00148 00149 // build matrix_B only in case of a 00150 // generalized problem 00151 if (_is_generalized_eigenproblem) 00152 { 00153 matrix_B = SparseMatrix<Number>::build(this->comm()).release(); 00154 dof_map.attach_matrix(*matrix_B); 00155 } 00156 00157 dof_map.compute_sparsity(this->get_mesh()); 00158 00159 // initialize and zero system matrix 00160 matrix_A->init(); 00161 matrix_A->zero(); 00162 00163 // eventually initialize and zero system matrix_B 00164 if (_is_generalized_eigenproblem) 00165 { 00166 matrix_B->init(); 00167 matrix_B->zero(); 00168 } 00169 } 00170 00171 00172 00173 void EigenSystem::reinit () 00174 { 00175 // initialize parent data 00176 Parent::reinit(); 00177 00178 // Clear the matrices 00179 matrix_A->clear(); 00180 00181 if (_is_generalized_eigenproblem) 00182 matrix_B->clear(); 00183 00184 DofMap& dof_map = this->get_dof_map(); 00185 00186 // Clear the sparsity pattern 00187 dof_map.clear_sparsity(); 00188 00189 // Compute the sparsity pattern for the current 00190 // mesh and DOF distribution. This also updates 00191 // both matrices, \p DofMap now knows them 00192 dof_map.compute_sparsity(this->get_mesh()); 00193 00194 matrix_A->init(); 00195 matrix_A->zero(); 00196 00197 if (_is_generalized_eigenproblem) 00198 { 00199 matrix_B->init(); 00200 matrix_B->zero(); 00201 } 00202 } 00203 00204 00205 00206 void EigenSystem::solve () 00207 { 00208 00209 // A reference to the EquationSystems 00210 EquationSystems& es = this->get_equation_systems(); 00211 00212 // check that necessary parameters have been set 00213 libmesh_assert (es.parameters.have_parameter<unsigned int>("eigenpairs")); 00214 libmesh_assert (es.parameters.have_parameter<unsigned int>("basis vectors")); 00215 00216 if (this->assemble_before_solve) 00217 // Assemble the linear system 00218 this->assemble (); 00219 00220 // Get the tolerance for the solver and the maximum 00221 // number of iterations. Here, we simply adopt the linear solver 00222 // specific parameters. 00223 const Real tol = 00224 es.parameters.get<Real>("linear solver tolerance"); 00225 00226 const unsigned int maxits = 00227 es.parameters.get<unsigned int>("linear solver maximum iterations"); 00228 00229 const unsigned int nev = 00230 es.parameters.get<unsigned int>("eigenpairs"); 00231 00232 const unsigned int ncv = 00233 es.parameters.get<unsigned int>("basis vectors"); 00234 00235 std::pair<unsigned int, unsigned int> solve_data; 00236 00237 // call the solver depending on the type of eigenproblem 00238 if (_is_generalized_eigenproblem) 00239 { 00240 //in case of a generalized eigenproblem 00241 solve_data = eigen_solver->solve_generalized (*matrix_A,*matrix_B, nev, ncv, tol, maxits); 00242 00243 } 00244 00245 else 00246 { 00247 libmesh_assert (!matrix_B); 00248 00249 //in case of a standard eigenproblem 00250 solve_data = eigen_solver->solve_standard (*matrix_A, nev, ncv, tol, maxits); 00251 00252 } 00253 00254 this->_n_converged_eigenpairs = solve_data.first; 00255 this->_n_iterations = solve_data.second; 00256 00257 } 00258 00259 00260 void EigenSystem::assemble () 00261 { 00262 00263 // Assemble the linear system 00264 Parent::assemble (); 00265 00266 } 00267 00268 00269 std::pair<Real, Real> EigenSystem::get_eigenpair (unsigned int i) 00270 { 00271 // call the eigen_solver get_eigenpair method 00272 return eigen_solver->get_eigenpair (i, *solution); 00273 } 00274 00275 } // namespace libMesh 00276 00277 #endif // LIBMESH_HAVE_SLEPC