Skip to content

Commit

Permalink
Ability to scale eigenvector in Eigenvalue executioner to postprocess…
Browse files Browse the repository at this point in the history
…or value idaholab#14500
  • Loading branch information
zachmprince committed Jan 8, 2020
1 parent b6997f2 commit cbd1fb8
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 1 deletion.
7 changes: 7 additions & 0 deletions framework/include/executioners/Eigenvalue.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ class Eigenvalue : public Steady

virtual void execute() override;

/**
* Here we scale the solution by the specified scalar and postprocessor value
*/
virtual void postSolve() override;

protected:
EigenProblem & _eigen_problem;
/// Postprocessor value that scales solution when eigensolve is finished
const PostprocessorValue * _normalization;
};
2 changes: 2 additions & 0 deletions framework/include/problems/EigenProblem.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class EigenProblem : public FEProblemBase
*/
bool negativeSignEigenKernel() { return _negative_sign_eigen_kernel; }

void scaleEigenvector(const Real scaling_factor);

#if LIBMESH_HAVE_SLEPC
void setEigenproblemType(Moose::EigenProblemType eigen_problem_type);

Expand Down
28 changes: 27 additions & 1 deletion framework/src/executioners/Eigenvalue.C
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ Eigenvalue::validParams()

params.addPrivateParam<bool>("_use_eigen_value", true);

params.addParam<PostprocessorName>("normalization", "To evaluate |x| for normalization");
params.addParam<Real>("normal_factor", 1.0, "Normalize x to make |x| equal to this factor");

// Add slepc options and eigen problems
#ifdef LIBMESH_HAVE_SLEPC
Moose::SlepcSupport::getSlepcValidParams(params);
Expand All @@ -40,7 +43,9 @@ Eigenvalue::validParams()
Eigenvalue::Eigenvalue(const InputParameters & parameters)
: Steady(parameters),
_eigen_problem(*getCheckedPointerParam<EigenProblem *>(
"_eigen_problem", "This might happen if you don't have a mesh"))
"_eigen_problem", "This might happen if you don't have a mesh")),
_normalization(isParamValid("normalization") ? &getPostprocessorValue("normalization")
: nullptr)
{
// Extract and store SLEPc options
#if LIBMESH_HAVE_SLEPC
Expand Down Expand Up @@ -71,3 +76,24 @@ Eigenvalue::execute()

Steady::execute();
}

void
Eigenvalue::postSolve()
{
Real val = getParam<Real>("normal_factor");
if (_normalization)
{
if (MooseUtils::absoluteFuzzyEqual(*_normalization, 0.0))
mooseError("Cannot normalize eigenvector by 0");
else
val /= *_normalization;
}

if (!MooseUtils::absoluteFuzzyEqual(val, 1.0))
{
_eigen_problem.scaleEigenvector(val);
// update all aux variables and user objects
for (const ExecFlagType & flag : _app.getExecuteOnEnum().items())
_problem.execute(flag);
}
}
24 changes: 24 additions & 0 deletions framework/src/problems/EigenProblem.C
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,27 @@ EigenProblem::isNonlinearEigenvalueSolver()
solverParams()._eigen_solve_type == Moose::EST_MONOLITH_NEWTON ||
solverParams()._eigen_solve_type == Moose::EST_MF_MONOLITH_NEWTON;
}

void
EigenProblem::scaleEigenvector(const Real scaling_factor)
{
// FIXME: This needs to be protected since NonlinearEigenSystem derives from ParallelObject (instead
// of NonlinearSystemBase) when SLEPc isn't installed
#if LIBMESH_HAVE_SLEPC
std::vector<VariableName> var_names = getVariableNames();
for (auto & vn : var_names)
{
MooseVariableFEBase & var = getVariable(0, vn);
if (var.parameters().get<bool>("eigen"))
for (unsigned int vc = 0; vc < var.count(); ++vc)
{
std::set<dof_id_type> var_indices;
_nl_eigen->system().local_dof_indices(var.number() + vc, var_indices);
for (const auto & dof : var_indices)
_nl_eigen->solution().set(dof, _nl_eigen->solution()(dof) * scaling_factor);
}
}
_nl_eigen->solution().close();
_nl_eigen->update();
#endif /* LIBMESH_HAVE_SLEPC */
}
Binary file not shown.
132 changes: 132 additions & 0 deletions test/tests/problems/eigen_problem/ne_coupled_scaled.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
[Mesh]
type = GeneratedMesh
dim = 2
xmin = 0
xmax = 10
ymin = 0
ymax = 10
elem_type = QUAD4
nx = 8
ny = 8
[]

[Variables]
[./u]
order = FIRST
family = LAGRANGE
# Make sure that system knows this is part of the eigenvector to be scaled
eigen = true
[../]

[./T]
order = FIRST
family = LAGRANGE
[../]
[]

[AuxVariables]
[./power]
order = FIRST
family = LAGRANGE
[../]
[]

[Kernels]
[./diff]
type = DiffMKernel
variable = u
mat_prop = diffusion
offset = 0.0
[../]

[./rhs]
type = CoefReaction
variable = u
coefficient = -1.0
extra_vector_tags = 'eigen'
[../]

[./diff_T]
type = Diffusion
variable = T
[../]
[./src_T]
type = CoupledForce
variable = T
v = power
[../]
[]

[AuxKernels]
[./power_ak]
type = NormalizationAux
variable = power
source_variable = u
normalization = unorm
# this coefficient will affect the eigenvalue.
normal_factor = 10
execute_on = linear
[../]
[]

[BCs]
[./homogeneous]
type = DirichletBC
variable = u
boundary = '0 1 2 3'
value = 0
[../]

[./eigenU]
type = EigenDirichletBC
variable = u
boundary = '0 1 2 3'
[../]

[./homogeneousT]
type = DirichletBC
variable = T
boundary = '0 1 2 3'
value = 0
[../]

[./eigenT]
type = EigenDirichletBC
variable = T
boundary = '0 1 2 3'
[../]
[]

[Materials]
[./dc]
type = VarCouplingMaterial
var = T
block = 0
base = 1.0
coef = 1.0
[../]
[]

[Executioner]
type = Eigenvalue
solve_type = MF_MONOLITH_NEWTON
eigen_problem_type = GEN_NON_HERMITIAN

# Postprocessor value to normalize
normalization = unorm
# Value to set normilization to
normal_factor = 17
[]

[Postprocessors]
[./unorm]
type = ElementIntegralVariablePostprocessor
variable = u
execute_on = linear
[../]
[]

[Outputs]
exodus = true
execute_on = 'timestep_end'
[]
9 changes: 9 additions & 0 deletions test/tests/problems/eigen_problem/tests
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,13 @@
requirement = "Eigenvalue system shall support Picard iteration using eigenvalue executioner as a sub app"
[]

[./scaled_eigenvector]
type = 'Exodiff'
input = 'ne_coupled_scaled.i'
exodiff = 'ne_coupled_scaled_out.e'
slepc_version = '>=3.8.0'
issues = '#14500'
requirement = "Eigenvalue system should be able scale eigenvector such that postprocessor is a certain value"
[]

[]

0 comments on commit cbd1fb8

Please sign in to comment.