/
InversePowerMethod.C
118 lines (102 loc) · 3.82 KB
/
InversePowerMethod.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html
#include "InversePowerMethod.h"
registerMooseObject("MooseApp", InversePowerMethod);
template <>
InputParameters
validParams<InversePowerMethod>()
{
InputParameters params = validParams<EigenExecutionerBase>();
params.addClassDescription("Inverse power method for Eigen value problems.");
params.addParam<PostprocessorName>(
"xdiff", "", "To evaluate |x-x_previous| for power iterations");
params.addParam<unsigned int>(
"max_power_iterations", 300, "The maximum number of power iterations");
params.addParam<unsigned int>("min_power_iterations", 1, "Minimum number of power iterations");
params.addParam<Real>("eig_check_tol", 1e-6, "Eigenvalue convergence tolerance");
params.addParam<Real>("sol_check_tol",
std::numeric_limits<Real>::max(),
"Convergence tolerance on |x-x_previous| when provided");
params.addParam<Real>("pfactor", 1e-2, "Reduce residual norm per power iteration by this factor");
params.addParam<bool>(
"Chebyshev_acceleration_on", true, "If Chebyshev acceleration is turned on");
params.addParam<Real>("k0", 1.0, "Initial guess of the eigenvalue");
return params;
}
InversePowerMethod::InversePowerMethod(const InputParameters & parameters)
: EigenExecutionerBase(parameters),
_solution_diff_name(getParam<PostprocessorName>("xdiff")),
_min_iter(getParam<unsigned int>("min_power_iterations")),
_max_iter(getParam<unsigned int>("max_power_iterations")),
_eig_check_tol(getParam<Real>("eig_check_tol")),
_sol_check_tol(getParam<Real>("sol_check_tol")),
_pfactor(getParam<Real>("pfactor")),
_cheb_on(getParam<bool>("Chebyshev_acceleration_on"))
{
if (!_app.isRecovering() && !_app.isRestarting())
_eigenvalue = getParam<Real>("k0");
addAttributeReporter("eigenvalue", _eigenvalue, "initial timestep_end");
if (_max_iter < _min_iter)
mooseError("max_power_iterations<min_power_iterations!");
if (_eig_check_tol < 0.0)
mooseError("eig_check_tol<0!");
if (_pfactor < 0.0)
mooseError("pfactor<0!");
}
void
InversePowerMethod::init()
{
if (_app.isRecovering())
{
_console << "\nCannot recover InversePowerMethod solves!\nExiting...\n" << std::endl;
return;
}
EigenExecutionerBase::init();
// Write the initial.
// Note: We need to tempararily change the system time to make the output system work properly.
_problem.timeStep() = 0;
Real t = _problem.time();
_problem.time() = _problem.timeStep();
_problem.outputStep(EXEC_INITIAL);
_problem.time() = t;
}
void
InversePowerMethod::execute()
{
if (_app.isRecovering())
return;
preExecute();
takeStep();
postExecute();
}
void
InversePowerMethod::takeStep()
{
// save the initial guess and mark a new time step
_problem.advanceState();
preSolve();
Real initial_res;
_last_solve_converged = inversePowerIteration(_min_iter,
_max_iter,
_pfactor,
_cheb_on,
_eig_check_tol,
true,
_solution_diff_name,
_sol_check_tol,
_eigenvalue,
initial_res);
postSolve();
if (lastSolveConverged())
{
printEigenvalue();
_problem.onTimestepEnd();
_problem.execute(EXEC_TIMESTEP_END);
}
}