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