libMesh
Loading...
Searching...
No Matches
condensed_eigen_system.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18#include "libmesh/libmesh_config.h"
19
20// Currently, the EigenSystem should only be available
21// if SLEPc support is enabled.
22#if defined(LIBMESH_HAVE_SLEPC)
23
24#include "libmesh/condensed_eigen_system.h"
25
26#include "libmesh/dof_map.h"
27#include "libmesh/equation_systems.h"
28#include "libmesh/int_range.h"
29#include "libmesh/libmesh_logging.h"
30#include "libmesh/numeric_vector.h"
31#include "libmesh/parallel.h"
32
33namespace libMesh
34{
35
37 const std::string & name_in,
38 const unsigned int number_in)
39 : Parent(es, name_in, number_in),
40 _condensed_dofs_initialized(false),
41 _have_condensed_dofs(false),
42 _create_submatrices_in_solve(true)
43{
44}
45
47
48void
49CondensedEigenSystem::initialize_condensed_dofs(const std::set<dof_id_type> & global_dirichlet_dofs_set)
50{
51 const DofMap & dof_map = this->get_dof_map();
52 if (global_dirichlet_dofs_set.empty() && !dof_map.n_constrained_dofs())
53 {
56 return;
57 }
58
59 // First, put all unconstrained local dofs into non_dirichlet_dofs_set
60 std::set<dof_id_type> local_non_condensed_dofs_set;
61 for (auto i : make_range(dof_map.first_dof(), dof_map.end_dof()))
62#if LIBMESH_ENABLE_CONSTRAINTS
63 if (!dof_map.is_constrained_dof(i))
64#endif
65 local_non_condensed_dofs_set.insert(i);
66
67 // Now erase the condensed dofs
68 for (const auto dof : global_dirichlet_dofs_set)
69 if ((dof_map.first_dof() <= dof) && (dof < dof_map.end_dof()))
70 local_non_condensed_dofs_set.erase(dof);
71
72 // Finally, move local_non_condensed_dofs_set over to a vector for convenience in solve()
74
75 for (const auto dof : local_non_condensed_dofs_set)
76 this->local_non_condensed_dofs_vector.push_back(dof);
77
80}
81
82void
88
89void
91{
94
96 return;
97
98 const auto m = cast_int<numeric_index_type>(this->local_non_condensed_dofs_vector.size());
99 auto M = m;
101 if (this->has_condensed_matrix_A())
102 {
103 this->get_condensed_matrix_A().init(M, M, m, m);
104 // A bit ludicrously MatCopy requires the matrix being copied to to be assembled
106 }
107 if (this->has_condensed_matrix_B())
108 {
109 this->get_condensed_matrix_B().init(M, M, m, m);
111 }
113 {
114 this->get_condensed_precond_matrix().init(M, M, m, m);
116 }
117}
118
120{
122 return this->n_dofs();
123 else
124 {
126 cast_int<dof_id_type>(local_non_condensed_dofs_vector.size());
127 this->comm().sum(n_global_non_condensed_dofs);
128
130 }
131}
132
133void
141
142void
144{
146
147 if (!this->use_shell_matrices())
148 {
153
154 // When not using shell matrices we use A for P as well so we don't need to add P
155 }
156 // we *are* using shell matrices but we might not be using a shell matrix for P
157 else if (!this->use_shell_precond_matrix())
158 {
161 }
162}
163
165{
166 LOG_SCOPE("solve()", "CondensedEigenSystem");
167
168 // If we haven't initialized any condensed dofs,
169 // just use the default eigen_system
171 {
173 return;
174 }
175
176 // check that necessary parameters have been set
178 this->get_equation_systems().parameters.have_parameter<unsigned int>("eigenpairs"));
180 this->get_equation_systems().parameters.have_parameter<unsigned int>("basis vectors"));
181
182 if (this->assemble_before_solve)
183 {
184 // Assemble the linear system
185 this->assemble();
186
187 // And close the assembled matrices; using a non-closed matrix
188 // with create_submatrix() is deprecated.
189 if (matrix_A)
190 matrix_A->close();
191 if (generalized() && matrix_B)
192 matrix_B->close();
193 if (precond_matrix)
195 }
196
197 // If we reach here, then there should be some non-condensed dofs
199
201 {
202 if (matrix_A)
205 if (generalized() && matrix_B)
208 if (precond_matrix)
212 }
213
216}
217
219{
220 LOG_SCOPE("get_eigenpair()", "CondensedEigenSystem");
221
222 // If we haven't initialized any condensed dofs,
223 // just use the default eigen_system
225 return Parent::get_eigenpair(i);
226
227 // If we reach here, then there should be some non-condensed dofs
229
230 // This function assumes that condensed_solve has just been called.
231 // If this is not the case, then we will trip an asset in get_eigenpair
232 std::unique_ptr<NumericVector<Number>> temp = NumericVector<Number>::build(this->comm());
233 const dof_id_type n_local =
234 cast_int<dof_id_type>(local_non_condensed_dofs_vector.size());
235 dof_id_type n = n_local;
236 this->comm().sum(n);
237
238 temp->init (n, n_local, false, PARALLEL);
239
240 std::pair<Real, Real> eval = eigen_solver->get_eigenpair (i, *temp);
241
242 // Now map temp to solution. Loop over local entries of local_non_condensed_dofs_vector
243 libmesh_assert(this->comm().verify(this->solution->closed()));
244 if (!this->solution->closed())
245 this->solution->close();
246 this->solution->zero();
247 for (auto j : make_range(n_local))
248 {
250 solution->set(index,(*temp)(temp->first_local_index()+j));
251 }
252
253 // Enforcing constraints requires creating a ghosted version of the solution, which requires the
254 // solution be assembled
255 solution->close();
257 this->update();
258
259 return eval;
260}
261
262
263
269
275
281
282void
284 NumericVector<Number> & super)
285{
286 libmesh_assert_equal_to(sub.local_size(), local_non_condensed_dofs_vector.size());
287 libmesh_assert_equal_to(sub.local_size() + this->get_dof_map().n_local_constrained_dofs(),
288 super.local_size());
289 auto super_sub_view = super.get_subvector(local_non_condensed_dofs_vector);
290 *super_sub_view = sub;
291 super.restore_subvector(std::move(super_sub_view), local_non_condensed_dofs_vector);
292}
293
294void
297{
298 libmesh_assert_equal_to(sub.local_size(), local_non_condensed_dofs_vector.size());
299 libmesh_assert_equal_to(sub.local_size() + this->get_dof_map().n_local_constrained_dofs(),
300 super.local_size());
301 auto super_sub_view = super.get_subvector(local_non_condensed_dofs_vector);
302 sub = *super_sub_view;
303 super.restore_subvector(std::move(super_sub_view), local_non_condensed_dofs_vector);
304}
305
306void
309{
310 parallel_object_only();
311
312 libmesh_assert_equal_to(sub.local_m(), local_non_condensed_dofs_vector.size());
313 libmesh_assert_equal_to(sub.local_m() + this->get_dof_map().n_local_constrained_dofs(),
314 super.local_m());
315 auto super_sub_view = SparseMatrix<Number>::build(super.comm());
316 super.create_submatrix(
318 sub = *super_sub_view;
319}
320
321} // namespace libMesh
322
323
324#endif // LIBMESH_HAVE_SLEPC
virtual void add_matrices() override
Adds the necessary matrices and shell matrices.
void copy_super_to_sub(NumericVector< Number > &super, NumericVector< Number > &sub)
Copy a logically super-vector into a sub-vector.
bool _have_condensed_dofs
Whether there are any condensed degrees of freedom.
std::vector< dof_id_type > local_non_condensed_dofs_vector
Vector storing the local dof indices that will not be condensed.
bool _condensed_dofs_initialized
A private flag to indicate whether the condensed dofs have been initialized.
virtual void solve() override
Override to solve the condensed eigenproblem with the dofs in local_non_condensed_dofs_vector strippe...
bool _create_submatrices_in_solve
Denotes whether to create the condensed submatrices from the global matrices in the solve.
void copy_sub_to_super(const NumericVector< Number > &sub, NumericVector< Number > &super)
Copy a logically sub-vector into a super-vector.
void initialize_condensed_dofs(const std::set< dof_id_type > &global_condensed_dofs_set=std::set< dof_id_type >())
Loop over the dofs on each processor to initialize the list of non-condensed dofs.
SparseMatrix< Number > & get_condensed_matrix_B()
std::unique_ptr< SparseMatrix< Number > > _condensed_matrix_A
The (condensed) system matrix for standard eigenvalue problems.
virtual void clear() override
Clear all the data structures associated with the system.
void initialize_condensed_matrices()
Initializes the condensed matrices.
std::unique_ptr< SparseMatrix< Number > > _condensed_precond_matrix
The condensed preconditioning matrix.
virtual std::pair< Real, Real > get_eigenpair(dof_id_type i) override
Override get_eigenpair() to retrieve the eigenpair for the condensed eigensolve.
std::unique_ptr< SparseMatrix< Number > > _condensed_matrix_B
A second (condensed) system matrix for generalized eigenvalue problems.
SparseMatrix< Number > & get_condensed_precond_matrix()
CondensedEigenSystem(EquationSystems &es, const std::string &name_in, const unsigned int number_in)
Constructor.
dof_id_type n_global_non_condensed_dofs() const
virtual void reinit() override
Reinitializes the member data fields associated with the system, so that, e.g., assemble() may be use...
SparseMatrix< Number > & get_condensed_matrix_A()
dof_id_type first_dof(const processor_id_type proc) const
dof_id_type end_dof(const processor_id_type proc) const
This class handles the numbering of degrees of freedom on a mesh.
Definition dof_map.h:181
dof_id_type n_constrained_dofs() const
bool is_constrained_dof(const dof_id_type dof) const
Definition dof_map.h:2426
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
Constrains the numeric vector v, which represents a solution defined on the mesh.
Definition dof_map.h:2518
Manages consistently variables, degrees of freedom, and coefficient vectors for eigenvalue problems.
SparseMatrix< Number > * matrix_A
The system matrix for standard eigenvalue problems.
SparseMatrix< Number > * matrix_B
A second system matrix for generalized eigenvalue problems.
bool use_shell_matrices() const
virtual void clear() override
Clear all the data structures associated with the system.
virtual void solve() override
Assembles & solves the eigen system.
virtual std::pair< Real, Real > get_eigenpair(dof_id_type i)
bool generalized() const
SparseMatrix< Number > * precond_matrix
A preconditioning matrix.
bool use_shell_precond_matrix() const
void solve_helper(SparseMatrix< Number > *const A, SparseMatrix< Number > *const B, SparseMatrix< Number > *const P)
std::unique_ptr< EigenSolver< Number > > eigen_solver
The EigenSolver, defining which interface, i.e solver package to use.
virtual void reinit() override
Reinitializes the member data fields associated with the system, so that, e.g., assemble() may be use...
virtual void add_matrices() override
Adds the necessary matrices and shell matrices.
This is the EquationSystems class.
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
virtual std::unique_ptr< NumericVector< T > > get_subvector(const std::vector< numeric_index_type > &)
Creates a view into this vector using the indices in rows.
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
virtual void restore_subvector(std::unique_ptr< NumericVector< T > >, const std::vector< numeric_index_type > &)
Restores a view into this vector using the indices in rows.
virtual numeric_index_type local_size() const =0
const Parallel::Communicator & _communicator
const Parallel::Communicator & comm() const
bool have_parameter(std::string_view) const
Definition parameters.h:420
Generic sparse matrix.
virtual void init(const numeric_index_type m, const numeric_index_type n, const numeric_index_type m_l, const numeric_index_type n_l, const numeric_index_type nnz=30, const numeric_index_type noz=10, const numeric_index_type blocksize=1)=0
Initialize SparseMatrix with the specified sizes.
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
static std::unique_ptr< SparseMatrix< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package(), const MatrixBuildType matrix_build_type=MatrixBuildType::AUTOMATIC)
Builds a SparseMatrix<T> using the linear solver package specified by solver_package.
virtual numeric_index_type local_m() const
Get the number of rows owned by this process.
virtual void create_submatrix(SparseMatrix< T > &submatrix, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols) const
This function creates a matrix called "submatrix" which is defined by the row and column indices give...
dof_id_type n_dofs() const
Definition system.C:118
bool assemble_before_solve
Flag which tells the system to whether or not to call the user assembly function during each call to ...
Definition system.h:1609
virtual void assemble()
Prepares matrix and _dof_map for matrix assembly.
Definition system.C:554
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition system.h:1655
virtual void update()
Update the local values to reflect the solution on neighboring processors.
Definition system.C:498
Parameters parameters
Parameters for the system. If a parameter is not provided, it should be retrieved from the EquationSy...
Definition system.h:1588
const DofMap & get_dof_map() const
Definition system.h:2417
const EquationSystems & get_equation_systems() const
Definition system.h:767
The libMesh namespace provides an interface to certain functionality in the library.
libmesh_assert(ctx)
uint8_t dof_id_type
Definition id_types.h:67
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176