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"
36#ifdef LIBMESH_HAVE_SLEPC
57#if PETSC_RELEASE_LESS_THAN(3, 13, 0)
58 if (eigen_system.has_matrix_B())
60 eigen_system.get_matrix_B(),
61 eigen_nl.eigenMatrixTag());
66#if !PETSC_RELEASE_LESS_THAN(3, 13, 0)
69 if (eigen_system.use_shell_matrices() && !eigen_system.use_shell_precond_matrix())
72 eigen_system.get_precond_matrix(),
73 eigen_nl.precondMatrixTag());
79 if (eigen_system.generalized())
82 eigen_system.get_matrix_A(),
83 eigen_system.get_matrix_B(),
84 eigen_nl.nonEigenMatrixTag(),
85 eigen_nl.eigenMatrixTag());
90 MatScale(cast_ref<PetscMatrix<Number> &>(eigen_system.get_matrix_B()).mat(), -1.0));
98 eigen_system.get_matrix_A(),
99 eigen_nl.nonEigenMatrixTag());
108 eigen_problem, eigen_problem.es().add_system<
libMesh::CondensedEigenSystem>(name), name),
109 _eigen_sys(eigen_problem.es().get_system<
libMesh::CondensedEigenSystem>(name)),
110 _eigen_problem(eigen_problem),
111 _solver_configuration(nullptr),
112 _n_eigen_pairs_required(eigen_problem.getNEigenPairsRequired()),
113 _work_rhs_vector_AX(addVector(
"work_rhs_vector_Ax", false, PARALLEL)),
114 _work_rhs_vector_BX(addVector(
"work_rhs_vector_Bx", false, PARALLEL)),
115 _precond_matrix_includes_eigen(false),
116 _preconditioner(nullptr),
117 _num_constrained_dofs(0)
123 mooseError(
"A slepc eigen solver is required");
127 std::make_unique<SlepcEigenSolverConfiguration>(eigen_problem, *solver, *
this);
159 auto & vtags =
object.getVectorTags({});
160 auto & mtags =
object.getMatrixTags({});
162 const bool eigen = (vtags.find(
_Bx_tag) != vtags.end()) || (mtags.find(
_B_tag) != mtags.end());
165 object.
mooseError(
"This object has been marked as contributing to B or Bx but the eigen "
166 "problem type is not a generalized one");
173 auto vname =
object.variable().
name();
175 sys->getScalarVariable(0, vname).eigen(
true);
177 sys->getVariable(0, vname).eigen(
true);
181 object.useMatrixTag(
_B_tag, {});
182 object.useVectorTag(
_Bx_tag, {});
187 object.useVectorTag(
_Ax_tag, {});
189 object.useMatrixTag(
_A_tag, {});
240 const bool presolve_succeeded =
preSolve();
241 if (!presolve_succeeded)
244 std::unique_ptr<NumericVector<Number>> subvec;
260 [](
auto & ti) { return ti->overridesSolve(); });
261 if (time_integrator_solve)
263 "If solve is overridden, then there must be only one time integrator");
265 if (time_integrator_solve)
272 if (!ti->overridesSolve())
273 ti->setNumIterationsLastSolve();
294 LibmeshPetscCall(SNESGetFunctionNorm(snes, &norm));
307 for (
unsigned int n = 0; n < n_converged_eigenvalues; n++)
311 if (n_converged_eigenvalues)
322 mooseError(
"Not implemented for time integrators.");
324 mooseError(
"Only implemented for nonlinear eigenvalue solvers.");
333 mooseError(
"Not implemented for time integrators.");
335 mooseError(
"Only implemented for nonlinear eigenvalue solvers.");
344 mooseError(
"Only implemented for nonlinear eigenvalue solvers.");
466NumericVector<Number> &
472NumericVector<Number> &
478NumericVector<Number> &
503 mooseError(
"There is no SNES in linear eigen solver");
513 mooseError(
"Unable to retrieve eigen solver");
515 return solver->
eps();
524 for (
const auto & nodal_bc : nodal_bcs)
527 auto nbc = std::dynamic_pointer_cast<DirichletBC>(nodal_bc);
529 auto eigen_nbc = std::dynamic_pointer_cast<EigenDirichletBC>(nodal_bc);
531 auto anbc = std::dynamic_pointer_cast<ArrayDirichletBC>(nodal_bc);
533 auto aeigen_nbc = std::dynamic_pointer_cast<EigenArrayDirichletBC>(nodal_bc);
535 if (nbc && nbc->variable().eigen() && nbc->getParam<Real>(
"value"))
537 "Can't set an inhomogeneous Dirichlet boundary condition for eigenvalue problems.");
541 auto &
values = anbc->getParam<RealEigenVector>(
"values");
545 mooseError(
"Can't set an inhomogeneous array Dirichlet boundary condition for "
546 "eigenvalue problems.");
549 else if (!nbc && !eigen_nbc && !anbc && !aeigen_nbc)
551 "Invalid NodalBC for eigenvalue problems, please use homogeneous (array) Dirichlet.");
560 if (n >= n_converged_eigenvalues)
561 mooseError(n,
" not in [0, ", n_converged_eigenvalues,
")");
570 if (n >= n_converged_eigenvalues)
571 mooseError(n,
" not in [0, ", n_converged_eigenvalues,
")");
602 "NonlinearEigenSystem::residualAndJacobianTogether is not implemented. It might even be "
603 "nonsensical. If it is sensical and you want this capability, please contact a MOOSE "
640 const std::string & )
641 :
libMesh::ParallelObject(eigen_problem)
643 mooseError(
"Need to install SLEPc to solve eigenvalue problems, please reconfigure libMesh\n");
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
std::array< Real, 2 > values
Boundary condition of a Dirichlet type for the eigen side.
Set Dirichlet boundary condition for eigenvalue problems.
Problem for solving eigenvalue problems.
bool negativeSignEigenKernel() const
A flag indicates if a negative sign is used in eigen kernels.
NonlinearEigenSystem & getNonlinearEigenSystem(const unsigned int nl_sys_num)
unsigned int activeEigenvalueIndex() const
Which eigenvalue is active.
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.
unsigned int getNEigenPairsRequired() const
bool isNonlinearEigenvalueSolver(unsigned int eigen_sys_num) const
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 computeResidualTag(const NumericVector< Number > &soln, NumericVector< Number > &residual, TagID tag) override
Form a vector for all kernels and BCs with a given tag.
SolverParams & solverParams(unsigned int solver_sys_num=0)
Get the solver parameters.
const InputParameters & parameters() const
Get the parameters of the object.
Class for containing MooseEnum item information.
bool hasActiveObjects(THREAD_ID tid=0) 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.
Nonlinear eigenvalue system to be solved.
TagID eigenVectorTag() const
Vector tag ID of right hand side.
virtual bool converged() override
Returns the convergence state.
virtual void postAddResidualObject(ResidualObject &object) override
Called after any ResidualObject-derived objects are added to the system.
NumericVector< Number > & residualVectorAX()
dof_id_type _num_constrained_dofs
The number of degrees of freedom constrained at the libMesh level, e.g.
TagID nonEigenVectorTag() const
Vector tag ID of left hand side.
unsigned int _n_eigen_pairs_required
virtual unsigned int getCurrentNonlinearIterationNumber() override
Returns the current nonlinear iteration number.
void computeScalingJacobian() override
Compute a "Jacobian" for automatic scaling purposes.
void computeScalingResidual() override
Compute a "residual" for automatic scaling purposes.
std::set< TagID > defaultMatrixTags() const override
Get the default matrix tags associted with this system.
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver() override
virtual unsigned int nLinearIterations() const override
Return the number of linear iterations.
libMesh::CondensedEigenSystem & _eigen_sys
EigenProblem & _eigen_problem
NonlinearEigenSystem(EigenProblem &problem, const std::string &name)
void attachSLEPcCallbacks()
virtual SNES getSNES() override
Retrieve snes from slepc eigen solver.
void checkIntegrity()
For eigenvalue problems (including standard and generalized), inhomogeneous (Dirichlet or Neumann) bo...
virtual void postInit() override
virtual Real finalNonlinearResidual() const override
Return the final nonlinear residual.
virtual void turnOffJacobian() override
Turn off the Jacobian (must be called before equation system initialization)
virtual void attachPreconditioner(libMesh::Preconditioner< Number > *preconditioner) override
Attach a customized preconditioner that requires physics knowledge.
virtual NumericVector< Number > & RHS() override
NumericVector< Number > & residualVectorBX()
std::set< TagID > defaultVectorTags() const override
Get the default vector tags associated with this system.
TagID precondMatrixTag() const
libMesh::Preconditioner< Number > * preconditioner() const
void residualAndJacobianTogether() override
Call this method if you want the residual and Jacobian to be computed simultaneously.
virtual void solve() override
Solve the system (using libMesh magic)
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.
virtual void stopSolve(const ExecFlagType &exec_flag, const std::set< TagID > &vector_tags_to_close) override
Quit the current solve as soon as possible.
libMesh::Preconditioner< Number > * _preconditioner
TagID nonEigenMatrixTag() const
Matrix tag ID of left hand side.
TagID eigenMatrixTag() const
Matrix tag ID of right hand side.
NumericVector< Number > & _work_rhs_vector_BX
std::pair< Real, Real > getConvergedEigenvalue(dof_id_type n) const
Return the Nth converged eigenvalue.
unsigned int getNumConvergedEigenvalues() const
Get the number of converged eigenvalues.
virtual unsigned int nNonlinearIterations() const override
Return the number of non-linear iterations.
virtual void setupFiniteDifferencedPreconditioner() override
void initializeCondensedMatrices()
Initialize the condensed matrices.
bool _precond_matrix_includes_eigen
std::unique_ptr< SlepcEigenSolverConfiguration > _solver_configuration
libMesh::CondensedEigenSystem & sys()
virtual void reinit() override
Reinitialize the system when the degrees of freedom in this system have changed.
virtual EPS getEPS()
Retrieve EPS (SLEPc eigen solver)
NumericVector< Number > & _work_rhs_vector_AX
std::vector< std::pair< Real, Real > > _eigen_values
Nonlinear system to be solved.
bool preSolve()
Perform some steps to get ready for the solver.
unsigned int _n_linear_iters
MooseObjectTagWarehouse< NodalBCBase > _nodal_bcs
std::unique_ptr< libMesh::DiagonalMatrix< Number > > _scaling_matrix
A diagonal matrix used for computing scaling.
virtual libMesh::System & system() override
Get the reference to the libMesh system.
This is the common base class for objects that give residual contributions.
bool _customized_pc_for_eigen
const NumericVector< Number > * _current_solution
solution vector from solver
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL)
Create a Tag.
virtual TagID addMatrixTag(TagName tag_name)
Create a Tag.
Base class for a system (of equations)
virtual std::set< TagID > defaultMatrixTags() const
Get the default matrix tags associted with this system.
std::vector< std::shared_ptr< TimeIntegrator > > _time_integrators
Time integrator.
unsigned int number() const
Gets the number of this system.
virtual bool hasScalarVariable(const std::string &var_name) const
virtual const std::string & name() const
virtual libMesh::DofMap & dofMap()
Gets writeable reference to the dof map.
NumericVector< Number > & solution()
virtual std::set< TagID > defaultVectorTags() const
Get the default vector tags associated with this system.
virtual void reinit()
Reinitialize the system when the degrees of freedom in this system have changed.
void dont_create_submatrices_in_solve()
std::vector< dof_id_type > local_non_condensed_dofs_vector
void initialize_condensed_dofs(const std::set< dof_id_type > &global_condensed_dofs_set=std::set< dof_id_type >())
SparseMatrix< Number > & get_condensed_matrix_B()
virtual std::pair< Real, Real > get_eigenpair(dof_id_type i) override
bool has_condensed_matrix_B() const
SparseMatrix< Number > & get_condensed_precond_matrix()
bool has_condensed_precond_matrix() const
bool has_condensed_matrix_A() const
SparseMatrix< Number > & get_condensed_matrix_A()
void set_solver_configuration(SolverConfiguration &solver_configuration)
void set_initial_space(NumericVector< Number > &initial_space_in)
virtual std::pair< Real, Real > get_eigenvalue(dof_id_type i)
bool has_precond_matrix() const
bool has_matrix_A() const
const SparseMatrix< Number > & get_matrix_B() const
const SparseMatrix< Number > & get_precond_matrix() const
const ShellMatrix< Number > & get_shell_matrix_A() const
unsigned int get_n_converged() const
const ShellMatrix< Number > & get_shell_precond_matrix() const
bool has_matrix_B() const
bool has_shell_precond_matrix() const
const ShellMatrix< Number > & get_shell_matrix_B() const
const SparseMatrix< Number > & get_matrix_A() const
std::unique_ptr< EigenSolver< Number > > eigen_solver
bool has_shell_matrix_A() const
const EigenSolver< Number > & get_eigen_solver() const
bool has_shell_matrix_B() const
virtual std::unique_ptr< NumericVector< T > > get_subvector(const std::vector< numeric_index_type > &)
virtual void restore_subvector(std::unique_ptr< NumericVector< T > >, const std::vector< numeric_index_type > &)
const Parallel::Communicator & _communicator
const Parallel::Communicator & comm() const
const T & get(std::string_view) const
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
PETSC_EXTERN PetscErrorCode registerPCToPETSc()
Let PETSc know there is a preconditioner.
PetscErrorCode mooseSlepcEPSGetSNES(EPS eps, SNES *snes)
Retrieve SNES from EPS.
void setOperationsForShellMat(EigenProblem &eigen_problem, Mat mat, bool eigen)
Set operations to shell mat.
void attachCallbacksToMat(EigenProblem &eigen_problem, Mat mat, bool eigen)
Attach call backs to mat.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
@ ST_JFNK
Jacobian-Free Newton Krylov.
void assemble_matrix(EquationSystems &es, const std::string &system_name)
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...