10 #include "libmesh/libmesh_config.h" 25 #include "libmesh/system.h" 26 #include "libmesh/eigen_solver.h" 27 #include "libmesh/enum_eigen_solver_type.h" 39 params.
addParam<
bool>(
"negative_sign_eigen_kernel",
41 "Whether or not to use a negative sign for eigenvalue kernels. " 42 "Using a negative sign makes eigenvalue kernels consistent with " 43 "a nonlinear solver");
48 "Which eigenvector is used to compute residual and also associated to nonlinear variable");
49 params.
addParam<PostprocessorName>(
"bx_norm",
"A postprocessor describing the norm of Bx");
59 #ifdef LIBMESH_HAVE_SLEPC
62 _n_eigen_pairs_required(1),
63 _generalized_eigenvalue_problem(false),
64 _negative_sign_eigen_kernel(getParam<bool>(
"negative_sign_eigen_kernel")),
65 _active_eigen_index(getParam<unsigned
int>(
"active_eigen_index")),
66 _do_free_power_iteration(false),
67 _output_inverse_eigenvalue(false),
68 _on_linear_solver(false),
69 _matrices_formed(false),
70 _constant_matrices(false),
71 _has_normalization(false),
73 _first_solve(declareRestartableData<bool>(
"first_solve", true)),
74 _bx_norm_name(isParamValid(
"bx_norm")
75 ?
std::make_optional(getParam<PostprocessorName>(
"bx_norm"))
79 #ifdef LIBMESH_HAVE_SLEPC 82 "eigen problems do not currently support multiple nonlinear eigen systems");
84 paramError(
"linear_sys_names",
"EigenProblem only works with a single nonlinear eigen system");
90 nl = std::make_shared<NonlinearEigenSystem>(*
this, sys_name);
96 _aux = std::make_shared<AuxiliarySystem>(*
this,
"aux0");
104 mooseError(
"Need to install SLEPc to solve eigenvalue problems, please reconfigure\n");
108 #if PETSC_RELEASE_LESS_THAN(3, 13, 0) 110 "Please use SLEPc-3.13.0 or higher. Old versions of SLEPc likely produce bad convergence");
119 #ifdef LIBMESH_HAVE_SLEPC 123 switch (eigen_problem_type)
151 mooseError(
"libMesh does not support EPT_POS_GEN_NON_HERMITIAN currently \n");
179 TIME_SECTION(
"computeJacobianTag", 3);
183 _nl_eigen->disassociateDefaultMatrixTags();
191 for (
const auto & matrix_tag : matrix_tags)
192 if (
_nl_eigen->hasMatrix(matrix_tag.second))
197 _nl_eigen->associateMatrixToTag(jacobian, tag);
202 _nl_eigen->disassociateMatrixFromTag(jacobian, tag);
208 const std::set<TagID> & tags)
210 TIME_SECTION(
"computeMatricesTags", 3);
212 if (jacobians.size() != tags.size())
215 " does not equal the number of tags ",
220 _nl_eigen->disassociateDefaultMatrixTags();
227 for (
auto tag : tags)
228 _nl_eigen->associateMatrixToTag(*(jacobians[i++]), tag);
234 for (
auto tag : tags)
235 _nl_eigen->disassociateMatrixFromTag(*(jacobians[i++]), tag);
240 const unsigned int nl_sys_num)
242 TIME_SECTION(
"computeJacobianBlocks", 3);
264 TIME_SECTION(
"computeJacobianAB", 3);
268 _nl_eigen->disassociateDefaultMatrixTags();
277 for (
const auto & matrix_tag : matrix_tags)
278 if (
_nl_eigen->hasMatrix(matrix_tag.second))
283 _nl_eigen->associateMatrixToTag(jacobianA, tagA);
284 _nl_eigen->associateMatrixToTag(jacobianB, tagB);
289 _nl_eigen->disassociateMatrixFromTag(jacobianA, tagA);
290 _nl_eigen->disassociateMatrixFromTag(jacobianB, tagB);
298 TIME_SECTION(
"computeResidualTag", 3);
302 _nl_eigen->disassociateDefaultVectorTags();
305 mooseAssert(
_fe_vector_tags.empty(),
"This should be empty indicating a clean starting state");
310 for (
const auto & vector_tag : residual_vector_tags)
311 if (
_nl_eigen->hasVector(vector_tag._id))
314 _nl_eigen->associateVectorToTag(residual, tag);
322 _nl_eigen->disassociateVectorFromTag(residual, tag);
332 TIME_SECTION(
"computeResidualAB", 3);
336 _nl_eigen->disassociateDefaultVectorTags();
339 mooseAssert(
_fe_vector_tags.empty(),
"This should be empty indicating a clean starting state");
345 for (
const auto & vector_tag : residual_vector_tags)
346 if (
_nl_eigen->hasVector(vector_tag._id))
349 _nl_eigen->associateVectorToTag(residualA, tagA);
350 _nl_eigen->associateVectorToTag(residualB, tagB);
357 _nl_eigen->disassociateVectorFromTag(residualA, tagA);
358 _nl_eigen->disassociateVectorFromTag(residualB, tagB);
370 Real eigenvalue = 1.0;
372 if (_active_eigen_index < _nl_eigen->getNumConvergedEigenvalues())
376 _nl_eigen->residualVectorBX() *= eigenvalue;
384 return _nl_eigen->residualVectorAX().l2_norm();
391 for (
auto & vn : var_names)
400 for (
unsigned int vc = 0; vc < var->
count(); ++vc)
402 std::set<dof_id_type> var_indices;
403 _nl_eigen->system().local_dof_indices(var->
number() + vc, var_indices);
404 for (
const auto & dof : var_indices)
439 Real v =
std::sqrt(eig.first * eig.first + eig.second * eig.second);
456 mooseError(
"Number of converged eigenvalues ",
458 " but you required eigenvalue ",
464 v = 1 /
std::sqrt(eig.first * eig.first + eig.second * eig.second);
473 mooseAssert(v != 0.,
"normal factor can not be zero");
475 unsigned int itr = 0;
481 mooseError(
"Can not scale eigenvector to the required factor ",
483 " please check if postprocessor is defined on only eigen variables");
485 mooseAssert(c != 0.,
"postprocessor value used for scaling can not be zero");
507 paramWarning(
"bx_norm",
"This parameter is only used for nonlinear solve types");
510 pp.paramError(
"execute_on",
511 "If providing the Bx norm, this postprocessor must execute on linear e.g. " 512 "during residual evaluations");
534 mooseError(
"There is no executioner for this moose app");
542 #if !PETSC_RELEASE_LESS_THAN(3, 12, 0) 552 TIME_SECTION(
"solve", 1);
560 if (_active_eigen_index < _nl_eigen->getNumConvergedEigenvalues())
574 _console << std::endl <<
" -------------------------------" << std::endl;
575 _console <<
" Free power iteration starts ..." << std::endl;
576 _console <<
" -------------------------------" << std::endl << std::endl;
584 _console << std::endl <<
" --------------------------------------" << std::endl;
585 _console <<
" Extra Free power iteration starts ..." << std::endl;
586 _console <<
" --------------------------------------" << std::endl << std::endl;
594 _console << std::endl <<
" -------------------------------------" << std::endl;
597 _console <<
" Nonlinear Newton iteration starts ..." << std::endl;
599 _console <<
" Nonlinear power iteration starts ..." << std::endl;
601 _console <<
" -------------------------------------" << std::endl << std::endl;
615 #if !PETSC_RELEASE_LESS_THAN(3, 12, 0) 617 LibmeshPetscCall(PetscOptionsPop());
639 #if PETSC_RELEASE_LESS_THAN(3, 13, 0) 646 "We should have errored during construction if we had more than one nonlinear system");
648 "We should have errored during construction if we had any linear systems");
651 _nl_eigen->sys().assemble_before_solve =
false;
677 const auto & solver_params =
solverParams(eigen_sys_num);
695 "We should not get here unless a bx_norm postprocessor has been provided");
Nonlinear eigenvalue system to be solved.
Generalized Non-Hermitian.
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.
static InputParameters validParams()
void computeJacobianBlocks(std::vector< JacobianBlock *> &blocks)
Computes several Jacobian blocks simultaneously, summing their contributions into smaller preconditio...
bool _matrices_formed
Whether or not matrices had been formed.
Generalized Hermitian indefinite.
Newton-based eigensolver with an assembled Jacobian matrix (fully coupled by default) ...
bool isUltimateMaster() const
Whether or not this app is the ultimate master app.
virtual void initPetscOutputAndSomeSolverSettings() override
Hook up monitors for SNES and KSP.
PostprocessorName _normalization
Postprocessor used to compute a factor from eigenvector.
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
void mooseDeprecated(Args &&... args) const
virtual void computeJacobianBlocks(std::vector< JacobianBlock *> &blocks, const unsigned int nl_sys_num) override
Computes several Jacobian blocks simultaneously, summing their contributions into smaller preconditio...
virtual std::size_t numNonlinearSystems() const override
unsigned int number() const
Get variable number coming from libMesh.
bool _currently_computing_jacobian
Flag to determine whether the problem is currently computing Jacobian.
virtual void init() override
The same as PJFNK except that matrix-vector multiplication is employed to replace residual evaluation...
void initEigenvector(const Real initial_value)
For nonlinear eigen solver, a good initial value can help convergence.
void clearFreeNonlinearPowerIterations(const InputParameters ¶ms)
virtual void newAssemblyArray(std::vector< std::shared_ptr< SolverSystem >> &solver_systems)
bool _has_normalization
Whether or not we normalize eigenvector.
EigenProblem(const InputParameters ¶meters)
unsigned int count() const
Get the number of components Note: For standard and vector variables, the number is one...
virtual void execute(const ExecFlagType &exec_type) override
Convenience function for performing execution of MOOSE systems.
PetscOptions _petsc_option_data_base
void adjustEigenVector(const Real value, bool scaling)
Adjust eigen vector by either scaling the existing values or setting new values The operations are ap...
void doFreeNonlinearPowerIterations(unsigned int free_power_iterations)
Do some free/extra power iterations.
virtual bool hasScalarVariable(const std::string &var_name) const override
Returns a Boolean indicating whether any system contains a variable with the name provided...
std::vector< std::shared_ptr< SolverSystem > > _solver_systems
Combined container to base pointer of every solver system.
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.
use whatever SLPEC has by default
bool _negative_sign_eigen_kernel
Whether or not use negative sign for Bx.
bool isRestarting() const
Whether or not this is a "restart" calculation.
Generalized Non-Hermitian with positive (semi-)definite B.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
void preScaleEigenVector(const std::pair< Real, Real > &eig)
Eigenvector need to be scaled back if it was scaled in an earlier stage Scaling eigen vector does not...
MooseApp & getMooseApp() const
Get the MooseApp this class is associated with.
bool isNonlinearEigenvalueSolver(unsigned int eigen_sys_num) const
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
virtual void computeResidualTags(const std::set< TagID > &tags)
Form multiple residual vectors and each is associated with one tag.
auto max(const L &left, const R &right)
std::shared_ptr< NonlinearEigenSystem > _nl_eigen
bool eigen() const
Whether or not this variable operates on an eigen kernel.
bool _generalized_eigenvalue_problem
void update()
Update the system (doing libMesh magic)
Real formNorm()
Form the Bx norm.
bool & _first_solve
A flag to indicate if it is the first time calling the solve.
std::vector< std::shared_ptr< NonlinearSystemBase > > _nl
The nonlinear systems.
void createTagSolutions()
Create extra tagged solution vectors.
bool contains(const std::string &value) const
Methods for seeing if a value is set in the MultiMooseEnum.
virtual void execute(const ExecFlagType &exec_type)
Convenience function for performing execution of MOOSE systems.
virtual std::vector< VariableName > getVariableNames()
Returns a list of all the variables in the problem (both from the NL and Aux systems.
virtual Real computeResidualL2Norm() override
Compute the residual of Ax - Bx.
Preconditioned Jacobian-free Newton Krylov.
void setNormalization(const PostprocessorName &pp, const Real value=std::numeric_limits< Real >::max())
Set postprocessor and normalization factor 'Postprocessor' is often used to compute an integral of ph...
const bool & _solve
Whether or not to actually solve the nonlinear system.
NonlinearSystemBase * _current_nl_sys
The current nonlinear system that we are solving.
void setCurrentNonlinearSystem(const unsigned int nl_sys_num)
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
void createTagVectors()
Create extra tagged vectors and matrices.
virtual void init() override
const ExecFlagEnum & getExecuteOnEnum() const
Return the execute on MultiMooseEnum for this object.
virtual libMesh::EquationSystems & es() override
std::shared_ptr< AuxiliarySystem > _aux
The auxiliary system.
void computeResidualAB(const NumericVector< Number > &soln, NumericVector< Number > &residualA, NumericVector< Number > &residualB, TagID tagA, TagID tagB)
Form two vetors, where each is associated with one tag, through one element-loop. ...
virtual MooseVariableScalar & getScalarVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the scalar variable reference from whichever system contains it.
std::vector< VectorTag > getVectorTags(const std::set< TagID > &tag_ids) const
registerMooseObject("MooseApp", EigenProblem)
MooseApp & _app
The MOOSE application this is associated with.
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
void assemble_matrix(EquationSystems &es, const std::string &system_name)
const ExecFlagType EXEC_LINEAR
std::string stringify(const T &t)
conversion to string
virtual void checkProblemIntegrity()
Method called to perform a series of sanity checks before a simulation is run.
void computeMatricesTags(const NumericVector< Number > &soln, const std::vector< SparseMatrix< Number > *> &jacobians, const std::set< TagID > &tags)
Form several matrices simultaneously.
Real _initial_eigenvalue
A value used for initial normalization.
unsigned int _active_eigen_index
Which eigenvalue is used to compute residual.
const PostprocessorValue & getPostprocessorValueByName(const PostprocessorName &name, std::size_t t_index=0) const
Get a read-only reference to the value associated with a Postprocessor that exists.
virtual std::map< TagName, TagID > & getMatrixTags()
Return all matrix tags in the system, where a tag is represented by a map from name to ID...
virtual void initNullSpaceVectors(const InputParameters ¶meters, std::vector< std::shared_ptr< NonlinearSystemBase >> &nl)
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
virtual void solve() override=0
Solve the system (using libMesh magic)
void solveSetup()
Calls the timestepSetup function for each of the output objects.
const ExecFlagType EXEC_PRE_DISPLACE
const std::vector< NonlinearSystemName > _nl_sys_names
The nonlinear system names.
const ExecFlagType EXEC_NONLINEAR
std::set< TagID > _fe_matrix_tags
void scaleEigenvector(const Real scaling_factor)
Scale eigenvector.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Class for containing MooseEnum item information.
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
void setFreeNonlinearPowerIterations(unsigned int free_power_iterations)
Set SLEPc/PETSc options to trigger free power iteration.
void postScaleEigenVector()
Normalize eigen vector.
bool relativeFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within a relative tolerance.
T & set(const std::string &)
Jacobian-free Newton Krylov.
const std::vector< LinearSystemName > _linear_sys_names
The linear system names.
virtual std::string solverTypeString(unsigned int solver_sys_num=0) override
Return solver type as a human readable string.
std::set< TagID > _fe_vector_tags
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
SolverParams & solverParams(unsigned int solver_sys_num=0)
Get the solver parameters.
std::shared_ptr< DisplacedProblem > _displaced_problem
const InputParameters & parameters() const
Get the parameters of the object.
Real _normal_factor
Postprocessor target value.
static InputParameters validParams()
virtual std::size_t numLinearSystems() const override
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
std::optional< PostprocessorName > _bx_norm_name
The name of the Postprocessor providing the Bx norm.
void paramWarning(const std::string ¶m, Args... args) const
Emits a warning prefixed with the file and line number of the given param (from the input file) along...
const UserObject & getUserObjectBase(const std::string &name, const THREAD_ID tid=0) const
Get the user object by its name.
Problem for solving eigenvalue problems.
bool bxNormProvided() const
Whether a Bx norm postprocessor has been provided.
virtual void checkProblemIntegrity() override
Method called to perform a series of sanity checks before a simulation is run.
EigenProblemType
Type of the eigen problem.
bool doFreePowerIteration() const
Whether or not we are doing free power iteration.
void setEigenproblemType(Moose::EigenProblemType eigen_problem_type)
Set eigen problem type.
Number initial_value(const Point &, const Parameters &, const std::string &, const std::string &)
void ErrorVector unsigned int
virtual void solve(const unsigned int nl_sys_num) override
auto index_range(const T &sizable)
OutputWarehouse & getOutputWarehouse()
Get the OutputWarehouse objects.
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.
void computeSystems(const ExecFlagType &type)
Do generic system computations.
virtual void computeJacobianTags(const std::set< TagID > &tags)
Form multiple matrices, and each is associated with a tag.
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 bool solverSystemConverged(const unsigned int solver_sys_num) override
const ExecFlagType EXEC_INITIAL