$extrastylesheet
condensed_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 #include "libmesh/libmesh_config.h"
00019 
00020 // Currently, the EigenSystem should only be available
00021 // if SLEPc support is enabled.
00022 #if defined(LIBMESH_HAVE_SLEPC)
00023 
00024 #include "libmesh/condensed_eigen_system.h"
00025 #include "libmesh/libmesh_logging.h"
00026 #include "libmesh/numeric_vector.h"
00027 #include "libmesh/equation_systems.h"
00028 #include "libmesh/dof_map.h"
00029 #include "libmesh/parallel.h"
00030 
00031 namespace libMesh
00032 {
00033 
00034 CondensedEigenSystem::CondensedEigenSystem (EquationSystems& es,
00035                                             const std::string& name_in,
00036                                             const unsigned int number_in)
00037   : Parent(es, name_in, number_in),
00038     condensed_matrix_A(SparseMatrix<Number>::build(es.comm())),
00039     condensed_matrix_B(SparseMatrix<Number>::build(es.comm())),
00040     condensed_dofs_initialized(false)
00041 {
00042 }
00043 
00044 void CondensedEigenSystem::initialize_condensed_dofs(std::set<unsigned int>& global_dirichlet_dofs_set)
00045 {
00046   // First, put all local dofs into non_dirichlet_dofs_set and
00047   std::set<unsigned int> local_non_condensed_dofs_set;
00048   for(unsigned int i=this->get_dof_map().first_dof(); i<this->get_dof_map().end_dof(); i++)
00049     local_non_condensed_dofs_set.insert(i);
00050 
00051   // Now erase the condensed dofs
00052   std::set<unsigned int>::iterator iter     = global_dirichlet_dofs_set.begin();
00053   std::set<unsigned int>::iterator iter_end = global_dirichlet_dofs_set.end();
00054 
00055   for ( ; iter != iter_end ; ++iter)
00056     {
00057       unsigned int condensed_dof_index = *iter;
00058       if ( (this->get_dof_map().first_dof() <= condensed_dof_index) &&
00059            (condensed_dof_index < this->get_dof_map().end_dof()) )
00060         {
00061           local_non_condensed_dofs_set.erase(condensed_dof_index);
00062         }
00063     }
00064 
00065   // Finally, move local_non_condensed_dofs_set over to a vector for convenience in solve()
00066   iter     = local_non_condensed_dofs_set.begin();
00067   iter_end = local_non_condensed_dofs_set.end();
00068 
00069   this->local_non_condensed_dofs_vector.clear();
00070 
00071   for ( ; iter != iter_end; ++iter)
00072     {
00073       unsigned int non_condensed_dof_index = *iter;
00074 
00075       this->local_non_condensed_dofs_vector.push_back(non_condensed_dof_index);
00076     }
00077 
00078   condensed_dofs_initialized = true;
00079 }
00080 
00081 unsigned int CondensedEigenSystem::n_global_non_condensed_dofs() const
00082 {
00083   if(!condensed_dofs_initialized)
00084     {
00085       return this->n_dofs();
00086     }
00087   else
00088     {
00089       unsigned int n_global_non_condensed_dofs = local_non_condensed_dofs_vector.size();
00090       this->comm().sum(n_global_non_condensed_dofs);
00091 
00092       return n_global_non_condensed_dofs;
00093     }
00094 }
00095 
00096 
00097 void CondensedEigenSystem::solve()
00098 {
00099   START_LOG("solve()", "CondensedEigenSystem");
00100 
00101   // If we haven't initialized any condensed dofs,
00102   // just use the default eigen_system
00103   if(!condensed_dofs_initialized)
00104     {
00105       STOP_LOG("solve()", "CondensedEigenSystem");
00106       Parent::solve();
00107       return;
00108     }
00109 
00110   // A reference to the EquationSystems
00111   EquationSystems& es = this->get_equation_systems();
00112 
00113   // check that necessary parameters have been set
00114   libmesh_assert (es.parameters.have_parameter<unsigned int>("eigenpairs"));
00115   libmesh_assert (es.parameters.have_parameter<unsigned int>("basis vectors"));
00116 
00117   if (this->assemble_before_solve)
00118     // Assemble the linear system
00119     this->assemble ();
00120 
00121   // If we reach here, then there should be some non-condensed dofs
00122   libmesh_assert(!local_non_condensed_dofs_vector.empty());
00123 
00124   // Now condense the matrices
00125   matrix_A->create_submatrix(*condensed_matrix_A,
00126                              local_non_condensed_dofs_vector,
00127                              local_non_condensed_dofs_vector);
00128 
00129   if(generalized())
00130     {
00131       matrix_B->create_submatrix(*condensed_matrix_B,
00132                                  local_non_condensed_dofs_vector,
00133                                  local_non_condensed_dofs_vector);
00134     }
00135 
00136 
00137   // Get the tolerance for the solver and the maximum
00138   // number of iterations. Here, we simply adopt the linear solver
00139   // specific parameters.
00140   const Real tol            =
00141     es.parameters.get<Real>("linear solver tolerance");
00142 
00143   const unsigned int maxits =
00144     es.parameters.get<unsigned int>("linear solver maximum iterations");
00145 
00146   const unsigned int nev    =
00147     es.parameters.get<unsigned int>("eigenpairs");
00148 
00149   const unsigned int ncv    =
00150     es.parameters.get<unsigned int>("basis vectors");
00151 
00152   std::pair<unsigned int, unsigned int> solve_data;
00153 
00154   // call the solver depending on the type of eigenproblem
00155   if ( generalized() )
00156     {
00157       //in case of a generalized eigenproblem
00158       solve_data = eigen_solver->solve_generalized
00159         (*condensed_matrix_A,*condensed_matrix_B, nev, ncv, tol, maxits);
00160     }
00161 
00162   else
00163     {
00164       libmesh_assert (!matrix_B);
00165 
00166       //in case of a standard eigenproblem
00167       solve_data = eigen_solver->solve_standard (*condensed_matrix_A, nev, ncv, tol, maxits);
00168     }
00169 
00170   set_n_converged(solve_data.first);
00171   set_n_iterations(solve_data.second);
00172 
00173   STOP_LOG("solve()", "CondensedEigenSystem");
00174 }
00175 
00176 
00177 
00178 std::pair<Real, Real> CondensedEigenSystem::get_eigenpair(unsigned int i)
00179 {
00180   START_LOG("get_eigenpair()", "CondensedEigenSystem");
00181 
00182   // If we haven't initialized any condensed dofs,
00183   // just use the default eigen_system
00184   if(!condensed_dofs_initialized)
00185     {
00186       STOP_LOG("get_eigenpair()", "CondensedEigenSystem");
00187       return Parent::get_eigenpair(i);
00188     }
00189 
00190   // If we reach here, then there should be some non-condensed dofs
00191   libmesh_assert(!local_non_condensed_dofs_vector.empty());
00192 
00193   // This function assumes that condensed_solve has just been called.
00194   // If this is not the case, then we will trip an asset in get_eigenpair
00195   UniquePtr< NumericVector<Number> > temp = NumericVector<Number>::build(this->comm());
00196   unsigned int n_local = local_non_condensed_dofs_vector.size();
00197   unsigned int n       = n_local;
00198   this->comm().sum(n);
00199 
00200   temp->init (n, n_local, false, PARALLEL);
00201 
00202   std::pair<Real, Real> eval = eigen_solver->get_eigenpair (i, *temp);
00203 
00204   // Now map temp to solution. Loop over local entries of local_non_condensed_dofs_vector
00205   this->solution->zero();
00206   for (unsigned int j=0; j<local_non_condensed_dofs_vector.size(); j++)
00207     {
00208       unsigned int index = local_non_condensed_dofs_vector[j];
00209       solution->set(index,(*temp)(temp->first_local_index()+j));
00210     }
00211 
00212   solution->close();
00213   this->update();
00214 
00215   STOP_LOG("get_eigenpair()", "CondensedEigenSystem");
00216 
00217   return eval;
00218 }
00219 
00220 
00221 
00222 
00223 } // namespace libMesh
00224 
00225 
00226 #endif // LIBMESH_HAVE_SLEPC