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