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 
49  _solve_type(getParam<MooseEnum>("solve_type")),
50  _explicit_residual(addVector("explicit_residual", false, PARALLEL)),
51  _solution_update(addVector("solution_update", true, PARALLEL)),
52  _mass_matrix_diag_inverted(addVector("mass_matrix_diag_inverted", true, GHOSTED))
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-related petsc options to prevent unused option warnings
65 }
66 
67 void
69 {
70  meshChanged();
71 
72  if (_nl)
73  {
74  std::unordered_set<unsigned int> vars_to_check;
75  if (!_vars.empty())
76  vars_to_check = _vars;
77  else
78  for (const auto i : make_range(_nl->nVariables()))
79  vars_to_check.insert(i);
80 
81  const auto mass_matrix_tag_id = massMatrixTagID();
82  std::set<TagID> matrix_tags = {mass_matrix_tag_id};
83  auto fv_object_starting_query = _fe_problem.theWarehouse()
84  .query()
85  .template condition<AttribMatrixTags>(matrix_tags)
86  .template condition<AttribSysNum>(_nl->number());
87 
88  for (const auto var_id : vars_to_check)
89  {
90  const auto & var_name = _nl->system().variable_name(var_id);
91  const bool field_var = _nl->hasVariable(var_name);
92  if (!field_var)
93  mooseAssert(_nl->hasScalarVariable(var_name),
94  var_name << " should be either a field or scalar variable");
95  if (field_var)
96  {
97  const auto & field_var = _nl->getVariable(/*tid=*/0, var_name);
98  if (field_var.isFV())
99  {
100  std::vector<FVElementalKernel *> fv_elemental_kernels;
101  auto var_query = fv_object_starting_query.clone().template condition<AttribVar>(var_id);
102  auto var_query_clone = var_query.clone();
103  var_query.template condition<AttribSystem>("FVElementalKernel")
104  .queryInto(fv_elemental_kernels);
105  if (fv_elemental_kernels.size())
106  continue;
107 
108  std::vector<FVFluxKernel *> fv_flux_kernels;
109  var_query_clone.template condition<AttribSystem>("FVFluxKernel")
110  .queryInto(fv_flux_kernels);
111  if (fv_flux_kernels.size())
112  continue;
113  }
114  else
115  {
116  // We are a finite element variable
117  if (_nl->getKernelWarehouse()
118  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
119  .hasVariableObjects(var_id))
120  continue;
122  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
123  .hasVariableObjects(var_id))
124  continue;
126  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
127  .hasVariableObjects(var_id))
128  continue;
129 #ifdef MOOSE_KOKKOS_ENABLED
131  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
132  .hasVariableObjects(var_id))
133  continue;
135  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
136  .hasVariableObjects(var_id))
137  continue;
138 #endif
139  }
140  }
141  else if (_nl->getScalarKernelWarehouse()
142  .getMatrixTagObjectWarehouse(mass_matrix_tag_id, 0)
143  .hasVariableObjects(var_id))
144  continue;
145 
146  mooseError("No objects contributing to the mass matrix were found for variable '",
147  var_name,
148  "'. Did you, e.g., forget a time derivative term?");
149  }
150  }
151 }
152 
153 void
155 {
157  mooseError(
158  "The chosen time integrator requires 'solve_type = LINEAR' in the Executioner block.");
159 }
160 
161 void
163 {
164 }
165 
166 void
168 {
169  // Can only be done after the system is initialized
171  *_ones = 1.;
172 
175 
177  {
178  _preconditioner = std::make_unique<LumpedPreconditioner>(*_mass_matrix_diag_inverted);
179  _linear_solver->attach_preconditioner(_preconditioner.get());
180  _linear_solver->init();
181  }
182 
185 }
186 
187 bool
189 {
190  bool converged = false;
191 
192  switch (_solve_type)
193  {
194  case CONSISTENT:
195  {
196  converged = solveLinearSystem(mass_matrix);
197 
198  break;
199  }
200  case LUMPED:
201  {
202  // Computes the sum of each row (lumping)
203  // Note: This is actually how PETSc does it
204  // It's not "perfectly optimal" - but it will be fast (and universal)
206 
207  // "Invert" the diagonal mass matrix
208  _mass_matrix_diag_inverted->reciprocal();
209 
210  // Multiply the inversion by the RHS
212 
213  // Check for convergence by seeing if there is a nan or inf
214  auto sum = _solution_update->sum();
215  converged = std::isfinite(sum);
216 
217  // The linear iteration count remains zero
219 
220  break;
221  }
222  case LUMP_PRECONDITIONED:
223  {
225  _mass_matrix_diag_inverted->reciprocal();
226 
227  converged = solveLinearSystem(mass_matrix);
228 
229  break;
230  }
231  default:
232  mooseError("Unknown solve_type in ExplicitTimeIntegrator.");
233  }
234 
235  return converged;
236 }
237 
238 bool
240 {
241  auto & es = _fe_problem.es();
242 
243  const auto num_its_and_final_tol =
244  _linear_solver->solve(mass_matrix,
247  es.parameters.get<Real>("linear solver tolerance"),
248  es.parameters.get<unsigned int>("linear solver maximum iterations"));
249 
250  _n_linear_iterations += num_its_and_final_tol.first;
251 
252  const bool converged = checkLinearConvergence();
253 
254  return converged;
255 }
256 
257 bool
259 {
260  auto reason = _linear_solver->get_converged_reason();
261 
262  switch (reason)
263  {
266  case CONVERGED_RTOL:
267  case CONVERGED_ATOL:
268  case CONVERGED_ITS:
273  return true;
274  case DIVERGED_NULL:
275  case DIVERGED_ITS:
276  case DIVERGED_DTOL:
277  case DIVERGED_BREAKDOWN:
281  case DIVERGED_NAN:
283  case CONVERGED_ITERATING:
285  return false;
286  default:
287  mooseError("Unknown convergence reason in ExplicitTimeIntegrator.");
288  }
289 }
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:849
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:891
DIVERGED_ITS
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:33
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:1157
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:851
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:466
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:271
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:90
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:876
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:360
ExplicitTimeIntegrator(const InputParameters &parameters)
virtual libMesh::System & system() override
Get the reference to the libMesh system.