https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ExplicitSSPRungeKutta.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10// MOOSE includes
12#include "NonlinearSystem.h"
13#include "FEProblem.h"
14
15// libMesh includes
16#include "libmesh/nonlinear_solver.h"
17
18using namespace libMesh;
19
21
24{
26
27 MooseEnum orders("1=1 2 3");
28 params.addRequiredParam<MooseEnum>("order", orders, "Order of time integration");
29 params.addClassDescription("Explicit strong stability preserving Runge-Kutta methods");
30 return params;
31}
32
34 : ExplicitTimeIntegrator(parameters),
35 _order(getParam<MooseEnum>("order")),
36 _stage(0),
37 _solution_intermediate_stage(addVector("solution_intermediate_stage", false, GHOSTED)),
38 _tmp_solution(addVector("tmp_solution", false, GHOSTED)),
39 _tmp_mass_solution_product(addVector("tmp_mass_solution_product", false, GHOSTED))
40{
41 // For SSPRK methods up to order 3, the number of stages equals the order
43
44 if (_order == 1)
45 {
46 _a = {{1.0}};
47 _b = {1.0};
48 _c = {0.0};
49 }
50 else if (_order == 2)
51 {
52 _a = {{1.0, 0.0}, {0.5, 0.5}};
53 _b = {1.0, 0.5};
54 _c = {0.0, 1.0};
55 }
56 else if (_order == 3)
57 {
58 _a = {{1.0, 0.0, 0.0}, {0.75, 0.25, 0.0}, {1.0 / 3.0, 0.0, 2.0 / 3.0}};
59 _b = {1.0, 0.25, 2.0 / 3.0};
60 _c = {0.0, 1.0, 0.5};
61 }
62 else
63 mooseError("Invalid time integration order.");
64
65 _solution_stage.resize(_n_stages + 1, nullptr);
66}
67
68void
70{
71 // Only the Jacobian needs to be computed, since the mass matrix needs it
73}
74
75void
77 const dof_id_type & dof,
78 ADReal & /*ad_u_dotdot*/) const
79{
80 // Note that if the solution for the current stage is not a nullptr, then neither
81 // are the previous stages.
83 {
84 for (unsigned int k = 0; k <= _stage; k++)
85 ad_u_dot -= _a[_stage][k] * (*(_solution_stage[k]))(dof);
86 ad_u_dot *= 1.0 / (_b[_stage] * _dt);
87 }
88 else
89 {
90 // We must be outside the solve loop in order to meet this criterion. In that case are we at
91 // timestep_begin or timestep_end? We don't know, so I don't think it's meaningful to compute
92 // derivatives here. Let's put in a quiet NaN which will only signal if we try to do something
93 // meaningful with it (and then we do want to signal because time derivatives may not be
94 // meaningful right now)
95 ad_u_dot = std::numeric_limits<typename ADReal::value_type>::quiet_NaN();
96 }
97}
98
99void
101{
102 // Reset iteration counts
105
107 const Real time_old = _fe_problem.timeOld();
108 const Real dt = _current_time - time_old;
109
110 bool converged = false;
111
113 for (_stage = 0; _stage < _n_stages; _stage++)
114 {
115 if (_stage == 0)
116 {
117 // Nothing needs to be done
118 }
119 else if (_stage == _n_stages - 1)
120 {
122 }
123 else
124 {
125 // Else must be the intermediate stage of the 3-stage method
129 }
130
131 // Set stage time for residual evaluation
132 _fe_problem.time() = time_old + _c[_stage] * dt;
134
135 converged = solveStage();
136 if (!converged)
137 return;
138 }
139
140 if (_stage == _n_stages)
141 // We made it to the end of the solve. We may call functions like computeTimeDerivatives later
142 // for postprocessing purposes in which case we need to ensure we're accessing our data
143 // correctly (e.g. not out-of-bounds)
144 --_stage;
145}
146
147bool
149{
150 // Compute the mass matrix
152 auto & mass_matrix = _nonlinear_implicit_system->get_system_matrix();
155
156 // Compute RHS vector using previous stage solution in steady-state residual
157 _explicit_residual->zero();
160
161 // Move the residual to the RHS
162 *_explicit_residual *= -1.0;
163
164 // Perform the linear solve
165 bool converged = performExplicitSolve(mass_matrix);
166
167 // Update the solution: u^(s) = u^(s-1) + du^(s)
171
172 // Enforce contraints on the solution
177
179
180 _nonlinear_implicit_system->nonlinear_solver->converged = converged;
181
182 return converged;
183}
184
185void
187{
188 // The time residual is not included in the steady-state residual
189 residual += *_Re_non_time;
190
191 // Compute \sum_{k=0}^{s-1} a_{s,k} u^(k) - u^(s-1)
193 for (unsigned int k = 0; k <= _stage; k++)
197
198 // Perform mass matrix product with the above vector
199 auto & mass_matrix = _nonlinear_implicit_system->get_system_matrix();
201
202 // Finish computing residual vector (before modification by nodal BCs)
203 residual -= *_tmp_mass_solution_product;
204
205 residual.close();
206
207 // Set time at which to evaluate nodal BCs
209}
210
211Real
213{
214 return Real(1) / _b[_stage];
215}
DualNumber< Real, DNDerivativeType, true > ADReal
registerMooseObject("MooseApp", ExplicitSSPRungeKutta)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
Explicit strong stability preserving Runge-Kutta methods.
ExplicitSSPRungeKutta(const InputParameters &parameters)
unsigned int _n_stages
Number of stages.
virtual void solve() override
Solves the time step and sets the number of nonlinear and linear iterations.
NumericVector< Number > * _tmp_solution
Temporary solution vector.
virtual Real duDotDuCoeff() const override
virtual void computeADTimeDerivatives(ADReal &ad_u_dot, const dof_id_type &dof, ADReal &ad_u_dotdot) const override
method for computing local automatic differentiation time derivatives
virtual void postResidual(NumericVector< Number > &residual) override
Callback to the NonLinearTimeIntegratorInterface called immediately after the residuals are computed ...
std::vector< std::vector< Real > > _a
Runge-Kutta "a" coefficient matrix.
NumericVector< Number > * _solution_intermediate_stage
Solution vector for intermediate stage.
std::vector< Real > _b
Runge-Kutta "b" coefficient vector.
std::vector< Real > _c
Runge-Kutta "c" coefficient vector.
NumericVector< Number > * _tmp_mass_solution_product
Temporary mass-matrix/solution vector product.
unsigned int _stage
Current stage.
bool solveStage()
Solves a stage of the time integrator.
std::vector< const NumericVector< Number > * > _solution_stage
Pointer to solution vector for each stage.
static InputParameters validParams()
virtual void computeTimeDerivatives() override
Computes the time derivative and the Jacobian of the time derivative.
const MooseEnum & _order
Order of time integration.
Base class for explicit time integrators that are implemented without using a nonlinear solver.
virtual bool performExplicitSolve(SparseMatrix< Number > &mass_matrix)
Solves a linear system using the chosen solve type.
Real _current_time
Save off current time to reset it back and forth.
static InputParameters validParams()
TagID _Ke_time_tag
For computing the mass matrix.
NumericVector< Real > * _solution_update
Solution vector for the linear solve.
NumericVector< Real > * _explicit_residual
Residual used for the RHS.
void computeResidual(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual)
This function is called by Libmesh to form a residual.
virtual Real & timeOld() const
virtual Real & time() const
virtual void computeJacobianTag(const NumericVector< libMesh::Number > &soln, libMesh::SparseMatrix< libMesh::Number > &jacobian, TagID tag)
Form a Jacobian matrix for a given tag.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
NonlinearSystemBase * _nl
Pointer to the nonlinear system, can happen that we dont have any.
NumericVector< Number > * _Re_non_time
residual vector for non-time contributions
libMesh::NonlinearImplicitSystem * _nonlinear_implicit_system
libMesh nonlinear implicit system, if applicable; otherwise, nullptr
void setSolution(const NumericVector< Number > &soln)
Set the solution to a given vector.
unsigned int number() const
Gets the number of this system.
const Real & dt() const
Returns the time step size.
void computeDuDotDu()
Compute _du_dot_du.
const NumericVector< Number > *const & _solution
unsigned int _n_linear_iterations
Total number of linear iterations over all stages of the time step.
unsigned int _n_nonlinear_iterations
Total number of nonlinear iterations over all stages of the time step.
FEProblemBase & _fe_problem
Reference to the problem.
Real & _dt
The current time step size.
const NumericVector< Number > & _solution_old
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
const SparseMatrix< Number > & get_system_matrix() const
std::unique_ptr< NonlinearSolver< Number > > nonlinear_solver
virtual void close()=0
virtual void zero()=0
virtual void add(const numeric_index_type i, const T value)=0
void vector_mult(NumericVector< T > &dest, const NumericVector< T > &arg) const
std::unique_ptr< NumericVector< Number > > current_local_solution
std::unique_ptr< NumericVector< Number > > solution
const DofMap & get_dof_map() const
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
const Number zero
uint8_t dof_id_type
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real