https://mooseframework.inl.gov
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
11 #include "ExplicitSSPRungeKutta.h"
12 #include "NonlinearSystem.h"
13 #include "FEProblem.h"
14 
15 // libMesh includes
16 #include "libmesh/nonlinear_solver.h"
17 
18 using 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
42  _n_stages = _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 
68 void
70 {
71  // Only the Jacobian needs to be computed, since the mass matrix needs it
73 }
74 
75 void
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 
99 void
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 
147 bool
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 
185 void
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)
192  _tmp_solution->zero();
193  for (unsigned int k = 0; k <= _stage; k++)
196  _tmp_solution->close();
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 
211 Real
213 {
214  return Real(1) / _b[_stage];
215 }
virtual void computeJacobianTag(const NumericVector< libMesh::Number > &soln, libMesh::SparseMatrix< libMesh::Number > &jacobian, TagID tag)
Form a Jacobian matrix for a given tag.
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
std::vector< Real > _c
Runge-Kutta "c" coefficient vector.
unsigned int _n_stages
Number of stages.
std::unique_ptr< NonlinearSolver< Number > > nonlinear_solver
virtual void solve() override
Solves the time step and sets the number of nonlinear and linear iterations.
virtual Real & time() const
NumericVector< Real > * _solution_update
Solution vector for the linear solve.
Real _current_time
Save off current time to reset it back and forth.
std::vector< Real > _b
Runge-Kutta "b" coefficient vector.
NumericVector< Number > * _solution_intermediate_stage
Solution vector for intermediate stage.
void vector_mult(NumericVector< T > &dest, const NumericVector< T > &arg) const
FEProblemBase & _fe_problem
Reference to the problem.
virtual Real duDotDuCoeff() const override
virtual void computeTimeDerivatives() override
Computes the time derivative and the Jacobian of the time derivative.
NonlinearSystemBase * _nl
Pointer to the nonlinear system, can happen that we dont have any.
TagID _Ke_time_tag
For computing the mass matrix.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
void setSolution(const NumericVector< Number > &soln)
Set the solution to a given vector.
Definition: SolverSystem.C:67
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
const Number zero
DualNumber< Real, DNDerivativeType, true > ADReal
Definition: ADRealForward.h:46
Real & _dt
The current time step size.
const MooseEnum & _order
Order of time integration.
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...
virtual void zero()=0
bool solveStage()
Solves a stage of the time integrator.
libMesh::NonlinearImplicitSystem * _nonlinear_implicit_system
libMesh nonlinear implicit system, if applicable; otherwise, nullptr
static InputParameters validParams()
std::vector< std::vector< Real > > _a
Runge-Kutta "a" coefficient matrix.
virtual void postResidual(NumericVector< Number > &residual) override
Callback to the NonLinearTimeIntegratorInterface called immediately after the residuals are computed ...
const Real & dt() const
Returns the time step size.
NumericVector< Real > * _explicit_residual
Residual used for the RHS.
std::unique_ptr< NumericVector< Number > > solution
unsigned int _n_linear_iterations
Total number of linear iterations over all stages of the time step.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
virtual bool performExplicitSolve(SparseMatrix< Number > &mass_matrix)
Solves a linear system using the chosen solve type.
unsigned int number() const
Gets the number of this system.
Definition: SystemBase.C:1149
virtual void close()=0
void computeResidual(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual)
This function is called by Libmesh to form a residual.
ExplicitSSPRungeKutta(const InputParameters &parameters)
const NumericVector< Number > *const & _solution
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:267
std::unique_ptr< NumericVector< Number > > current_local_solution
static InputParameters validParams()
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...
virtual Real & timeOld() const
const NumericVector< Number > & _solution_old
NumericVector< Number > * _tmp_mass_solution_product
Temporary mass-matrix/solution vector product.
unsigned int _n_nonlinear_iterations
Total number of nonlinear iterations over all stages of the time step.
unsigned int _stage
Current stage.
NumericVector< Number > * _tmp_solution
Temporary solution vector.
Explicit strong stability preserving Runge-Kutta methods.
virtual void add(const numeric_index_type i, const T value)=0
NumericVector< Number > * _Re_non_time
residual vector for non-time contributions
const DofMap & get_dof_map() const
const SparseMatrix< Number > & get_system_matrix() const
Base class for explicit time integrators that are implemented without using a nonlinear solver...
std::vector< const NumericVector< Number > * > _solution_stage
Pointer to solution vector for each stage.
registerMooseObject("MooseApp", ExplicitSSPRungeKutta)
uint8_t dof_id_type
void computeDuDotDu()
Compute _du_dot_du.
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const