condensed_eigen_system.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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, 00036 const unsigned int number) 00037 : Parent(es, name, number), 00038 condensed_matrix_A(SparseMatrix<Number>::build()), 00039 condensed_matrix_B(SparseMatrix<Number>::build()), 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 CommWorld.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 matrix_B->create_submatrix(*condensed_matrix_B, 00130 local_non_condensed_dofs_vector, 00131 local_non_condensed_dofs_vector); 00132 00133 // Get the tolerance for the solver and the maximum 00134 // number of iterations. Here, we simply adopt the linear solver 00135 // specific parameters. 00136 const Real tol = 00137 es.parameters.get<Real>("linear solver tolerance"); 00138 00139 const unsigned int maxits = 00140 es.parameters.get<unsigned int>("linear solver maximum iterations"); 00141 00142 const unsigned int nev = 00143 es.parameters.get<unsigned int>("eigenpairs"); 00144 00145 const unsigned int ncv = 00146 es.parameters.get<unsigned int>("basis vectors"); 00147 00148 std::pair<unsigned int, unsigned int> solve_data; 00149 00150 // call the solver depending on the type of eigenproblem 00151 if ( generalized() ) 00152 { 00153 //in case of a generalized eigenproblem 00154 solve_data = eigen_solver->solve_generalized 00155 (*condensed_matrix_A,*condensed_matrix_B, nev, ncv, tol, maxits); 00156 } 00157 00158 else 00159 { 00160 libmesh_assert (!matrix_B); 00161 00162 //in case of a standard eigenproblem 00163 solve_data = eigen_solver->solve_standard (*condensed_matrix_A, nev, ncv, tol, maxits); 00164 } 00165 00166 set_n_converged(solve_data.first); 00167 set_n_iterations(solve_data.second); 00168 00169 STOP_LOG("solve()", "CondensedEigenSystem"); 00170 } 00171 00172 00173 00174 std::pair<Real, Real> CondensedEigenSystem::get_eigenpair(unsigned int i) 00175 { 00176 START_LOG("get_eigenpair()", "CondensedEigenSystem"); 00177 00178 // If we haven't initialized any condensed dofs, 00179 // just use the default eigen_system 00180 if(!condensed_dofs_initialized) 00181 { 00182 STOP_LOG("get_eigenpair()", "CondensedEigenSystem"); 00183 return Parent::get_eigenpair(i); 00184 } 00185 00186 // If we reach here, then there should be some non-condensed dofs 00187 libmesh_assert(!local_non_condensed_dofs_vector.empty()); 00188 00189 // This function assumes that condensed_solve has just been called. 00190 // If this is not the case, then we will trip an asset in get_eigenpair 00191 AutoPtr< NumericVector<Number> > temp = NumericVector<Number>::build(); 00192 unsigned int n_local = local_non_condensed_dofs_vector.size(); 00193 unsigned int n = n_local; 00194 CommWorld.sum(n); 00195 00196 temp->init (n, n_local, false, libMeshEnums::PARALLEL); 00197 00198 std::pair<Real, Real> eval = eigen_solver->get_eigenpair (i, *temp); 00199 00200 // Now map temp to solution. Loop over local entries of local_non_condensed_dofs_vector 00201 this->solution->zero(); 00202 for(unsigned int i=0; i<local_non_condensed_dofs_vector.size(); i++) 00203 { 00204 unsigned int index = local_non_condensed_dofs_vector[i]; 00205 solution->set(index,(*temp)(temp->first_local_index()+i)); 00206 } 00207 00208 solution->close(); 00209 this->update(); 00210 00211 STOP_LOG("get_eigenpair()", "CondensedEigenSystem"); 00212 00213 return eval; 00214 } 00215 00216 00217 00218 00219 } // namespace libMesh 00220 00221 00222 #endif // LIBMESH_HAVE_SLEPC
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:45 UTC
Hosted By: