https://mooseframework.inl.gov
ExplicitTimeIntegrator.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 "ExplicitTimeIntegrator.h"
12 #include "NonlinearSystem.h"
13 #include "FEProblem.h"
14 #include "PetscSupport.h"
15 #include "KernelBase.h"
16 #include "DGKernelBase.h"
17 #include "ScalarKernelBase.h"
18 #include "FVElementalKernel.h"
19 #include "FVFluxKernel.h"
20 #include "NodalKernelBase.h"
21 
22 // libMesh includes
23 #include "libmesh/enum_convergence_flags.h"
24 
25 using namespace libMesh;
26 
29 {
31 
32  MooseEnum solve_type("consistent lumped lump_preconditioned", "consistent");
33 
34  params.addParam<MooseEnum>(
35  "solve_type",
36  solve_type,
37  "The way to solve the system. A 'consistent' solve uses the full mass matrix and actually "
38  "needs to use a linear solver to solve the problem. 'lumped' uses a lumped mass matrix with "
39  "a simple inversion - incredibly fast but may be less accurate. 'lump_preconditioned' uses "
40  "the lumped mass matrix as a preconditioner for the 'consistent' solve");
41 
42  return params;
43 }
44 
46  : TimeIntegrator(parameters),
47  MeshChangedInterface(parameters),
48  _solve_type(getParam<MooseEnum>("solve_type")),
49  _explicit_residual(addVector("explicit_residual", false, PARALLEL)),
50  _solution_update(addVector("solution_update", true, PARALLEL)),
51  _mass_matrix_diag_inverted(addVector("mass_matrix_diag_inverted", true, GHOSTED)),
52  _ones(nullptr)
53 {
55 
56  // This effectively changes the default solve_type to LINEAR instead of PJFNK,
57  // so that it is valid to not supply solve_type in the Executioner block:
58  if (_nl)
60 
62  _ones = addVector("ones", true, PARALLEL);
63  // don't set any of the common SNES and KSP-related petsc options to prevent unused option
64  // warnings
67 }
68 
69 void
71 {
72  setupSolver();
73 
74  if (_nl)
75  {
76  std::unordered_set<unsigned int> vars_to_check;
77  if (!_vars.empty())
78  vars_to_check = _vars;
79  else
80  for (const auto i : make_range(_nl->nVariables()))
81  vars_to_check.insert(i);
82 
83  const auto mass_matrix_tag_id = massMatrixTagID();
84  std::set<TagID> matrix_tags = {mass_matrix_tag_id};
85  auto fv_object_starting_query = _fe_problem.theWarehouse()
86  .query()
87  .template condition<AttribMatrixTags>(matrix_tags)
88  .template condition<AttribSysNum>(_nl->number());
89 
90  for (const auto var_id : vars_to_check)
91  {
92  const auto & var_name = _nl->system().variable_name(var_id);
93  const bool field_var = _nl->hasVariable(var_name);
94  if (!field_var)
95  mooseAssert(_nl->hasScalarVariable(var_name),
96  var_name << " should be either a field or scalar variable");
97  if (field_var)
98  {
99  const auto & field_var = _nl->getVariable(/*tid=*/0, var_name);
100  if (field_var.isFV())
101  {
102  std::vector<FVElementalKernel *> fv_elemental_kernels;
103  auto var_query = fv_object_starting_query.clone().template condition<AttribVar>(var_id);
104  auto var_query_clone = var_query.clone();
105  var_query.template condition<AttribSystem>("FVElementalKernel")
106  .queryInto(fv_elemental_kernels);
107  if (fv_elemental_kernels.size())
108  continue;
109 
110  std::vector<FVFluxKernel *> fv_flux_kernels;
111  var_query_clone.template condition<AttribSystem>("FVFluxKernel")
112  .queryInto(fv_flux_kernels);
113  if (fv_flux_kernels.size())
114  continue;
115  }
116  else
117  {
118  // We are a finite element variable
119  if (_nl->getKernelWarehouse()
120  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
121  .hasVariableObjects(var_id))
122  continue;
124  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
125  .hasVariableObjects(var_id))
126  continue;
128  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
129  .hasVariableObjects(var_id))
130  continue;
131 #ifdef MOOSE_KOKKOS_ENABLED
133  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
134  .hasVariableObjects(var_id))
135  continue;
137  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
138  .hasVariableObjects(var_id))
139  continue;
140 #endif
141  }
142  }
143  else if (_nl->getScalarKernelWarehouse()
144  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
145  .hasVariableObjects(var_id))
146  continue;
147 
148  mooseError("No objects contributing to the mass matrix were found for variable '",
149  var_name,
150  "'. Did you, e.g., forget a time derivative term?");
151  }
152  }
153 }
154 
155 void
157 {
159  mooseError(
160  "The chosen time integrator requires 'solve_type = LINEAR' in the Executioner block.");
161 }
162 
163 void
165 {
166 }
167 
168 void
170 {
171  setupSolver();
172 }
173 
174 void
176 {
177  // Can only be done after the system is initialized
178  if (_ones)
179  {
181  *_ones = 1.;
182  }
183 
186 
188  {
189  _preconditioner = std::make_unique<LumpedPreconditioner>(*_mass_matrix_diag_inverted);
190  _linear_solver->attach_preconditioner(_preconditioner.get());
191  _linear_solver->init();
192  }
193 
196 }
197 
198 bool
200 {
201  bool converged = false;
202 
203  switch (_solve_type)
204  {
205  case CONSISTENT:
206  {
207  converged = solveLinearSystem(mass_matrix);
208 
209  break;
210  }
211  case LUMPED:
212  {
213  // Computes the sum of each row (lumping)
214  // Note: This is actually how PETSc does it
215  // It's not "perfectly optimal" - but it will be fast (and universal)
217 
218  // "Invert" the diagonal mass matrix
219  _mass_matrix_diag_inverted->reciprocal();
220 
221  // Multiply the inversion by the RHS
223 
224  // Check for convergence by seeing if there is a nan or inf
225  auto sum = _solution_update->sum();
226  converged = std::isfinite(sum);
227 
228  // The linear iteration count remains zero
230 
231  break;
232  }
233  case LUMP_PRECONDITIONED:
234  {
236  _mass_matrix_diag_inverted->reciprocal();
237 
238  converged = solveLinearSystem(mass_matrix);
239 
240  break;
241  }
242  default:
243  mooseError("Unknown solve_type in ExplicitTimeIntegrator.");
244  }
245 
246  return converged;
247 }
248 
249 bool
251 {
252  auto & es = _fe_problem.es();
253 
254  const auto num_its_and_final_tol =
255  _linear_solver->solve(mass_matrix,
258  es.parameters.get<Real>("linear solver tolerance"),
259  es.parameters.get<unsigned int>("linear solver maximum iterations"));
260 
261  _n_linear_iterations += num_its_and_final_tol.first;
262 
263  const bool converged = checkLinearConvergence();
264 
265  return converged;
266 }
267 
268 bool
270 {
271  auto reason = _linear_solver->get_converged_reason();
272 
273  switch (reason)
274  {
277  case CONVERGED_RTOL:
278  case CONVERGED_ATOL:
279  case CONVERGED_ITS:
284  return true;
285  case DIVERGED_NULL:
286  case DIVERGED_ITS:
287  case DIVERGED_DTOL:
288  case DIVERGED_BREAKDOWN:
292  case DIVERGED_NAN:
294  case CONVERGED_ITERATING:
296  return false;
297  default:
298  mooseError("Unknown convergence reason in ExplicitTimeIntegrator.");
299  }
300 }
bool checkLinearConvergence()
Check for the linear solver convergence.
NumericVector< Real > * _solution_update
Solution vector for the linear solve.
void setLinearSolverDefaults(FEProblemBase &problem, libMesh::LinearSolver< T > &linear_solver)
Set the defaults for a libMesh LinearSolver.
Definition: PetscSupport.h:98
MooseObjectTagWarehouse< ResidualObject > & getKokkosKernelWarehouse()
DIVERGED_DTOL
NumericVector< Real > * _ones
Vector of 1&#39;s to help with creating the lumped mass matrix.
virtual void initialSetup() override
Called to setup datastructures.
void vector_mult(NumericVector< T > &dest, const NumericVector< T > &arg) const
std::unordered_set< unsigned int > & _vars
The variables that this time integrator integrates.
FEProblemBase & _fe_problem
Reference to the problem.
CONVERGED_ITERATING
MooseObjectTagWarehouse< KernelBase > & getKernelWarehouse()
Access functions to Warehouses from outside NonlinearSystemBase.
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...
MooseObjectTagWarehouse< ResidualObject > & getKokkosNodalKernelWarehouse()
const Parallel::Communicator & comm() const
Solving a linear problem.
Definition: MooseTypes.h:897
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
DIVERGED_INDEFINITE_MAT
MooseEnum _solve_type
Solve type for how mass matrix is handled.
const MooseObjectTagWarehouse< ScalarKernelBase > & getScalarKernelWarehouse() const
DIVERGED_BREAKDOWN
static InputParameters validParams()
virtual unsigned int nVariables() const
Get the number of variables in this system.
Definition: SystemBase.C:892
DIVERGED_ITS
void dontAddCommonKSPOptions(FEProblemBase &fe_problem)
Function to ensure that common KSP options are not added to the PetscOptions storage object to be lat...
CONVERGED_ATOL_NORMAL
CONVERGED_CG_CONSTRAINED
CONVERGED_HAPPY_BREAKDOWN
Interface for notifications that the mesh has changed.
std::unique_ptr< libMesh::LinearSolver< Number > > _linear_solver
For solving with the consistent matrix.
TheWarehouse & theWarehouse() const
DIVERGED_NONSYMMETRIC
virtual TagID getMatrixTagID(const TagName &tag_name) const
Get a TagID from a TagName.
Definition: SubProblem.C:343
NumericVector< Real > * _explicit_residual
Residual used for the RHS.
virtual void preSolve() override
virtual libMesh::EquationSystems & es() override
unsigned int _n_linear_iterations
Total number of linear iterations over all stages of the time step.
MooseObjectWarehouse< T > & getMatrixTagObjectWarehouse(TagID tag_id, THREAD_ID tid)
Retrieve a moose object warehouse in which every moose object has the given matrix tag...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
const std::string & variable_name(const unsigned int i) const
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:1158
std::unique_ptr< LumpedPreconditioner > _preconditioner
For solving with lumped preconditioning.
virtual bool hasVariable(const std::string &var_name) const
Query a system for a variable.
Definition: SystemBase.C:852
CONVERGED_CG_NEG_CURVE
void dontAddCommonSNESOptions(FEProblemBase &fe_problem)
Function to ensure that common SNES options are not added to the PetscOptions storage object to be la...
NumericVector< Real > * _mass_matrix_diag_inverted
Diagonal of the lumped mass matrix (and its inversion)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Base class for time integrators.
DIVERGED_NAN
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse...
Definition: TheWarehouse.h:467
virtual void init() override
Called only before the very first timestep (t_step = 0) Never called again (not even during recover/r...
CONVERGED_RTOL_NORMAL
CONVERGED_STEP_LENGTH
IntRange< T > make_range(T beg, T end)
virtual TagID massMatrixTagID() const
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:281
SolverParams & solverParams(unsigned int solver_sys_num=0)
Get the solver parameters.
DIVERGED_INDEFINITE_PC
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
bool hasVariableObjects(unsigned int variable_id, THREAD_ID tid=0) const
Checks for whether this warehouse has objects for a given variable.
virtual void meshChanged() override
Called on this object when the mesh changes.
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
Definition: SystemBase.C:91
const MooseObjectTagWarehouse< NodalKernelBase > & getNodalKernelWarehouse() const
MooseObjectTagWarehouse< DGKernelBase > & getDGKernelWarehouse()
NumericVector< Number > * addVector(const std::string &name, const bool project, const libMesh::ParallelType type)
Wrapper around vector addition for nonlinear time integrators.
virtual bool hasScalarVariable(const std::string &var_name) const
Definition: SystemBase.C:877
bool solveLinearSystem(SparseMatrix< Number > &mass_matrix)
Solves a linear system.
DIVERGED_BREAKDOWN_BICG
static InputParameters validParams()
const std::string & _type
The type of this class.
Definition: MooseBase.h:388
ExplicitTimeIntegrator(const InputParameters &parameters)
virtual libMesh::System & system() override
Get the reference to the libMesh system.