28 #include "libmesh/libmesh_config.h" 29 #include "libmesh/petsc_matrix.h" 30 #include "libmesh/sparse_matrix.h" 31 #include "libmesh/diagonal_matrix.h" 32 #include "libmesh/petsc_shell_matrix.h" 33 #include "libmesh/petsc_solver_exception.h" 34 #include "libmesh/slepc_eigen_solver.h" 38 #ifdef LIBMESH_HAVE_SLEPC 59 #if PETSC_RELEASE_LESS_THAN(3, 13, 0) 60 if (eigen_system.has_matrix_B())
62 eigen_system.get_matrix_B(),
63 eigen_nl.eigenMatrixTag());
68 #if !PETSC_RELEASE_LESS_THAN(3, 13, 0) 71 if (eigen_system.use_shell_matrices() && !eigen_system.use_shell_precond_matrix())
74 eigen_system.get_precond_matrix(),
75 eigen_nl.precondMatrixTag());
81 if (eigen_system.generalized())
84 eigen_system.get_matrix_A(),
85 eigen_system.get_matrix_B(),
86 eigen_nl.nonEigenMatrixTag(),
87 eigen_nl.eigenMatrixTag());
88 #if LIBMESH_HAVE_SLEPC 100 eigen_system.get_matrix_A(),
101 eigen_nl.nonEigenMatrixTag());
112 _eigen_problem(eigen_problem),
113 _solver_configuration(nullptr),
114 _n_eigen_pairs_required(eigen_problem.getNEigenPairsRequired()),
115 _work_rhs_vector_AX(addVector(
"work_rhs_vector_Ax", false,
PARALLEL)),
116 _work_rhs_vector_BX(addVector(
"work_rhs_vector_Bx", false,
PARALLEL)),
117 _precond_matrix_includes_eigen(false),
118 _preconditioner(nullptr),
119 _num_constrained_dofs(0)
125 mooseError(
"A slepc eigen solver is required");
129 std::make_unique<SlepcEigenSolverConfiguration>(eigen_problem, *solver, *
this);
133 _Ax_tag = eigen_problem.addVectorTag(
"Ax_tag");
135 _Bx_tag = eigen_problem.addVectorTag(
"Eigen");
137 _A_tag = eigen_problem.addMatrixTag(
"A_tag");
139 _B_tag = eigen_problem.addMatrixTag(
"Eigen");
145 _precond_tag = eigen_problem.addMatrixTag(
"Eigen_precond");
158 !dynamic_cast<EigenArrayDirichletBC *>(&
object))
161 auto & vtags =
object.getVectorTags({});
162 auto & mtags =
object.getMatrixTags({});
164 const bool eigen = (vtags.find(
_Bx_tag) != vtags.end()) || (mtags.find(
_B_tag) != mtags.end());
167 object.
mooseError(
"This object has been marked as contributing to B or Bx but the eigen " 168 "problem type is not a generalized one");
175 auto vname =
object.variable().
name();
177 sys->getScalarVariable(0, vname).eigen(
true);
179 sys->getVariable(0, vname).eigen(
true);
183 object.useMatrixTag(
_B_tag, {});
184 object.useVectorTag(
_Bx_tag, {});
189 object.useVectorTag(
_Ax_tag, {});
191 object.useMatrixTag(
_A_tag, {});
242 const bool presolve_succeeded =
preSolve();
243 if (!presolve_succeeded)
246 std::unique_ptr<NumericVector<Number>> subvec;
262 [](
auto & ti) {
return ti->overridesSolve(); });
263 if (time_integrator_solve)
265 "If solve is overridden, then there must be only one time integrator");
267 if (time_integrator_solve)
274 if (!ti->overridesSolve())
275 ti->setNumIterationsLastSolve();
288 for (
unsigned int n = 0; n < n_converged_eigenvalues; n++)
292 if (n_converged_eigenvalues)
452 mooseError(
"There is no SNES in linear eigen solver");
462 mooseError(
"Unable to retrieve eigen solver");
464 return solver->
eps();
473 for (
const auto & nodal_bc : nodal_bcs)
484 if (nbc && nbc->variable().eigen() && nbc->getParam<
Real>(
"value"))
486 "Can't set an inhomogeneous Dirichlet boundary condition for eigenvalue problems.");
491 for (MooseIndex(values) i = 0; i < values.size(); i++)
494 mooseError(
"Can't set an inhomogeneous array Dirichlet boundary condition for " 495 "eigenvalue problems.");
498 else if (!nbc && !eigen_nbc && !anbc && !aeigen_nbc)
500 "Invalid NodalBC for eigenvalue problems, please use homogeneous (array) Dirichlet.");
505 std::pair<Real, Real>
509 if (n >= n_converged_eigenvalues)
510 mooseError(n,
" not in [0, ", n_converged_eigenvalues,
")");
514 std::pair<Real, Real>
519 if (n >= n_converged_eigenvalues)
520 mooseError(n,
" not in [0, ", n_converged_eigenvalues,
")");
551 "NonlinearEigenSystem::residualAndJacobianTogether is not implemented. It might even be " 552 "nonsensical. If it is sensical and you want this capability, please contact a MOOSE " 589 const std::string & )
592 mooseError(
"Need to install SLEPc to solve eigenvalue problems, please reconfigure libMesh\n");
std::string name(const ElemQuality q)
Nonlinear eigenvalue system to be solved.
std::vector< std::shared_ptr< TimeIntegrator > > _time_integrators
Time integrator.
virtual void computeResidualTag(const NumericVector< Number > &soln, NumericVector< Number > &residual, TagID tag) override
Form a vector for all kernels and BCs with a given tag.
const SparseMatrix< Number > & get_precond_matrix() const
NumericVector< Number > & residualVectorAX()
int eps(unsigned int i, unsigned int j)
2D version
std::unique_ptr< SlepcEigenSolverConfiguration > _solver_configuration
bool has_condensed_matrix_A() const
unsigned int activeEigenvalueIndex() const
Which eigenvalue is active.
NumericVector< Number > & solution()
const SparseMatrix< Number > & get_matrix_A() const
SparseMatrix< Number > & get_condensed_precond_matrix()
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
virtual void postAddResidualObject(ResidualObject &object) override
Called after any ResidualObject-derived objects are added to the system.
TagID nonEigenVectorTag() const
Vector tag ID of left hand side.
const SparseMatrix< Number > & get_matrix_B() const
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver() override
bool has_matrix_A() const
virtual void reinit() override
Reinitialize the system when the degrees of freedom in this system have changed.
TagID eigenVectorTag() const
Vector tag ID of right hand side.
void initializeCondensedMatrices()
Initialize the condensed matrices.
bool has_condensed_precond_matrix() const
MooseObjectTagWarehouse< NodalBCBase > _nodal_bcs
std::set< TagID > defaultVectorTags() const override
Get the default vector tags associated with this system.
bool has_shell_matrix_A() const
bool negativeSignEigenKernel() const
A flag indicates if a negative sign is used in eigen kernels.
const Parallel::Communicator & comm() const
NumericVector< Number > & _work_rhs_vector_AX
virtual void postInit() override
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
std::unique_ptr< libMesh::DiagonalMatrix< Number > > _scaling_matrix
A diagonal matrix used for computing scaling.
bool _customized_pc_for_eigen
const Parallel::Communicator & _communicator
void set_initial_space(NumericVector< Number > &initial_space_in)
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
const EigenSolver< Number > & get_eigen_solver() const
Base class for a system (of equations)
const T_sys & get_system(std::string_view name) const
void dont_create_submatrices_in_solve()
NonlinearEigenSystem(EigenProblem &problem, const std::string &name)
NumericVector< Number > & _work_rhs_vector_BX
const ShellMatrix< Number > & get_shell_matrix_A() const
bool isNonlinearEigenvalueSolver(unsigned int eigen_sys_num) const
EigenProblem & _eigen_problem
unsigned int getNumConvergedEigenvalues() const
Get the number of converged eigenvalues.
Nonlinear system to be solved.
virtual const std::string & name() const
unsigned int getNEigenPairsRequired() const
SparseMatrix< Number > & get_condensed_matrix_A()
virtual libMesh::DofMap & dofMap()
Gets writeable reference to the dof map.
virtual EPS getEPS()
Retrieve EPS (SLEPc eigen solver)
libMesh::Preconditioner< Number > * _preconditioner
const T & get(std::string_view) const
const std::vector< std::shared_ptr< T > > & getActiveObjects(THREAD_ID tid=0) const
Retrieve complete vector to the active all/block/boundary restricted objects for a given thread...
virtual void stopSolve(const ExecFlagType &exec_flag, const std::set< TagID > &vector_tags_to_close) override
Quit the current solve as soon as possible.
void attachCallbacksToMat(EigenProblem &eigen_problem, Mat mat, bool eigen)
Attach call backs to mat.
NumericVector< Number > & residualVectorBX()
virtual void turnOffJacobian() override
Turn off the Jacobian (must be called before equation system initialization)
bool has_matrix_B() const
std::pair< Real, Real > getConvergedEigenpair(dof_id_type n) const
Return the Nth converged eigenvalue and copies the respective eigen vector to the solution vector...
bool has_precond_matrix() const
Jacobian-Free Newton Krylov.
virtual bool converged() override
Returns the convergence state.
Boundary condition of a Dirichlet type.
bool has_shell_matrix_B() const
const ShellMatrix< Number > & get_shell_precond_matrix() const
bool _precond_matrix_includes_eigen
void initialize_condensed_dofs(const std::set< dof_id_type > &global_condensed_dofs_set=std::set< dof_id_type >())
unsigned int number() const
Gets the number of this system.
void assemble_matrix(EquationSystems &es, const std::string &system_name)
virtual std::unique_ptr< NumericVector< T > > get_subvector(const std::vector< numeric_index_type > &)
Set Dirichlet boundary condition for eigenvalue problems.
virtual void setupFiniteDifferencedPreconditioner() override
bool has_shell_precond_matrix() const
virtual std::pair< Real, Real > get_eigenvalue(dof_id_type i)
const NumericVector< Number > * _current_solution
solution vector from solver
virtual std::set< TagID > defaultMatrixTags() const
Get the default matrix tags associted with this system.
void computeScalingResidual() override
Compute a "residual" for automatic scaling purposes.
dof_id_type _num_constrained_dofs
The number of degrees of freedom constrained at the libMesh level, e.g.
virtual unsigned int getCurrentNonlinearIterationNumber() override
Returns the current nonlinear iteration number.
NonlinearEigenSystem & getNonlinearEigenSystem(const unsigned int nl_sys_num)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
This is the common base class for objects that give residual contributions.
PetscErrorCode mooseSlepcEPSGetSNES(EPS eps, SNES *snes)
Retrieve SNES from EPS.
Class for containing MooseEnum item information.
bool hasActiveObjects(THREAD_ID tid=0) const
std::unique_ptr< EigenSolver< Number > > eigen_solver
const ShellMatrix< Number > & get_shell_matrix_B() const
libMesh::CondensedEigenSystem & sys()
void residualAndJacobianTogether() override
Call this method if you want the residual and Jacobian to be computed simultaneously.
virtual std::set< TagID > defaultVectorTags() const
Get the default vector tags associated with this system.
virtual SNES getSNES() override
Retrieve snes from slepc eigen solver.
virtual std::pair< Real, Real > get_eigenpair(dof_id_type i) override
TagID eigenMatrixTag() const
Matrix tag ID of right hand side.
std::vector< dof_id_type > local_non_condensed_dofs_vector
void computeScalingJacobian() override
Compute a "Jacobian" for automatic scaling purposes.
virtual void reinit()
Reinitialize the system when the degrees of freedom in this system have changed.
SolverParams & solverParams(unsigned int solver_sys_num=0)
Get the solver parameters.
Boundary condition of a Dirichlet type for the eigen side.
bool has_condensed_matrix_B() const
void setOperationsForShellMat(EigenProblem &eigen_problem, Mat mat, bool eigen)
Set operations to shell mat.
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
void attachSLEPcCallbacks()
std::pair< Real, Real > getConvergedEigenvalue(dof_id_type n) const
Return the Nth converged eigenvalue.
TagID nonEigenMatrixTag() const
Matrix tag ID of left hand side.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
SparseMatrix< Number > & get_condensed_matrix_B()
unsigned int get_n_converged() const
bool preSolve()
Perform some steps to get ready for the solver.
Problem for solving eigenvalue problems.
std::vector< std::pair< Real, Real > > _eigen_values
TagID precondMatrixTag() const
PETSC_EXTERN PetscErrorCode registerPCToPETSc()
Let PETSc know there is a preconditioner.
virtual NumericVector< Number > & RHS() override
unsigned int _n_eigen_pairs_required
virtual void solve() override
Solve the system (using libMesh magic)
virtual bool hasScalarVariable(const std::string &var_name) const
libMesh::CondensedEigenSystem & _eigen_sys
Boundary condition of a Dirichlet type.
std::set< TagID > defaultMatrixTags() const override
Get the default matrix tags associted with this system.
libMesh::Preconditioner< Number > * preconditioner() const
void checkIntegrity()
For eigenvalue problems (including standard and generalized), inhomogeneous (Dirichlet or Neumann) bo...
virtual void attachPreconditioner(libMesh::Preconditioner< Number > *preconditioner) override
Attach a customized preconditioner that requires physics knowledge.
void computeJacobianAB(const NumericVector< Number > &soln, SparseMatrix< Number > &jacobianA, SparseMatrix< Number > &jacobianB, TagID tagA, TagID tagB)
Form two Jacobian matrices, where each is associated with one tag, through one element-loop.
virtual void computeJacobianTag(const NumericVector< Number > &soln, SparseMatrix< Number > &jacobian, TagID tag) override
Form a Jacobian matrix for all kernels and BCs with a given tag.
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
virtual void restore_subvector(std::unique_ptr< NumericVector< T >>, const std::vector< numeric_index_type > &)
virtual libMesh::System & system() override
Get the reference to the libMesh system.