https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
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
25using 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
69void
71{
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
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
155void
157{
160 "The chosen time integrator requires 'solve_type = LINEAR' in the Executioner block.");
161}
162
163void
167
168void
173
174void
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
198bool
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 }
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
249bool
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
268bool
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:
292 case DIVERGED_NAN:
296 return false;
297 default:
298 mooseError("Unknown convergence reason in ExplicitTimeIntegrator.");
299 }
300}
virtual TagID massMatrixTagID() const
virtual void meshChanged() override
Called on this object when the mesh changes.
virtual void init() override
Called only before the very first timestep (t_step = 0) Never called again (not even during recover/r...
virtual void initialSetup() override
Called to setup datastructures.
virtual bool performExplicitSolve(SparseMatrix< Number > &mass_matrix)
Solves a linear system using the chosen solve type.
bool checkLinearConvergence()
Check for the linear solver convergence.
MooseEnum _solve_type
Solve type for how mass matrix is handled.
NumericVector< Real > * _mass_matrix_diag_inverted
Diagonal of the lumped mass matrix (and its inversion)
ExplicitTimeIntegrator(const InputParameters &parameters)
virtual void preSolve() override
NumericVector< Real > * _ones
Vector of 1's to help with creating the lumped mass matrix.
static InputParameters validParams()
std::unique_ptr< LumpedPreconditioner > _preconditioner
For solving with lumped preconditioning.
TagID _Ke_time_tag
For computing the mass matrix.
NumericVector< Real > * _solution_update
Solution vector for the linear solve.
std::unique_ptr< libMesh::LinearSolver< Number > > _linear_solver
For solving with the consistent matrix.
NumericVector< Real > * _explicit_residual
Residual used for the RHS.
bool solveLinearSystem(SparseMatrix< Number > &mass_matrix)
Solves a linear system.
virtual libMesh::EquationSystems & es() override
SolverParams & solverParams(unsigned int solver_sys_num=0)
Get the solver parameters.
TheWarehouse & theWarehouse() const
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
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.
Interface for notifications that the mesh has changed.
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
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
MooseObjectWarehouse< T > & getMatrixTagObjectWarehouse(TagID tag_id, THREAD_ID tid)
Retrieve a moose object warehouse in which every moose object has the given matrix tag.
bool hasVariableObjects(unsigned int variable_id, THREAD_ID tid=0) const
Checks for whether this warehouse has objects for a given variable.
MooseObjectTagWarehouse< ResidualObject > & getKokkosKernelWarehouse()
MooseObjectTagWarehouse< ResidualObject > & getKokkosNodalKernelWarehouse()
const MooseObjectTagWarehouse< NodalKernelBase > & getNodalKernelWarehouse() const
MooseObjectTagWarehouse< KernelBase > & getKernelWarehouse()
Access functions to Warehouses from outside NonlinearSystemBase.
virtual libMesh::System & system() override
Get the reference to the libMesh system.
MooseObjectTagWarehouse< DGKernelBase > & getDGKernelWarehouse()
const MooseObjectTagWarehouse< ScalarKernelBase > & getScalarKernelWarehouse() const
NonlinearSystemBase * _nl
Pointer to the nonlinear system, can happen that we dont have any.
NumericVector< Number > * addVector(const std::string &name, const bool project, const libMesh::ParallelType type)
Wrapper around vector addition for nonlinear time integrators.
Moose::SolveType _type
virtual TagID getMatrixTagID(const TagName &tag_name) const
Get a TagID from a TagName.
Definition SubProblem.C:343
virtual unsigned int nVariables() const
Get the number of variables in this system.
Definition SystemBase.C:890
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
unsigned int number() const
Gets the number of this system.
virtual bool hasScalarVariable(const std::string &var_name) const
Definition SystemBase.C:875
virtual bool hasVariable(const std::string &var_name) const
Query a system for a variable.
Definition SystemBase.C:850
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse.
Base class for time integrators.
std::unordered_set< unsigned int > & _vars
The variables that this time integrator integrates.
unsigned int _n_linear_iterations
Total number of linear iterations over all stages of the time step.
static InputParameters validParams()
FEProblemBase & _fe_problem
Reference to the problem.
static std::unique_ptr< LinearSolver< T > > build(const libMesh::Parallel::Communicator &comm_in, const SolverPackage solver_package=libMesh::default_solver_package())
const Parallel::Communicator & comm() const
void vector_mult(NumericVector< T > &dest, const NumericVector< T > &arg) const
const std::string & variable_name(const unsigned int i) const
void dontAddCommonSNESOptions(FEProblemBase &fe_problem)
Function to ensure that common SNES options are not added to the PetscOptions storage object to be la...
void setLinearSolverDefaults(FEProblemBase &problem, libMesh::LinearSolver< T > &linear_solver)
Set the defaults for a libMesh LinearSolver.
void dontAddCommonKSPOptions(FEProblemBase &fe_problem)
Function to ensure that common KSP options are not added to the PetscOptions storage object to be lat...
@ ST_LINEAR
Solving a linear problem.
Definition MooseTypes.h:902
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
CONVERGED_HAPPY_BREAKDOWN
CONVERGED_CG_NEG_CURVE
CONVERGED_ATOL_NORMAL
DIVERGED_NONSYMMETRIC
CONVERGED_ITERATING
CONVERGED_CG_CONSTRAINED
DIVERGED_INDEFINITE_PC
CONVERGED_STEP_LENGTH
DIVERGED_PCSETUP_FAILED
CONVERGED_RTOL_NORMAL
DIVERGED_BREAKDOWN
DIVERGED_BREAKDOWN_BICG
DIVERGED_INDEFINITE_MAT