25#include "libmesh/id_types.h"
26#include "libmesh/nonlinear_solver.h"
27#include "libmesh/sparse_matrix.h"
29#include "libmesh/vector_value.h"
36 DirectCentralDifference,
46 "Implementation of explicit time integration without invoking any of the nonlinear solver.");
48 params.
addParam<
bool>(
"use_constant_mass",
50 "If set to true, will only compute the mass matrix in the first time step, "
51 "and keep using it throughout the simulation.");
54 "recompute_mass_matrix_after_mesh_change",
56 "If set to true, the mass matrix will be recomputed when the mesh changes (e.g. through "
57 "adaptivity). If use_constant_mass is set to true, adadaptivity is used, and this parameter "
58 "is not set to true, the simulation will error out when the mesh changes.");
60 params.
addParam<TagName>(
"mass_matrix_tag",
"mass",
"The tag for the mass matrix");
62 params.
addParam<std::vector<VariableName>>(
65 "A subset of variables that require second-order integration (velocity and acceleration) to "
66 "be applied by this time integrator.");
68 params.
addParam<std::vector<VariableName>>(
71 "A subset of variables that require first-order integration (velocity only) to be applied by "
72 "this time integrator.");
77 MooseEnum solve_type(
"consistent lumped lump_preconditioned",
"lumped");
85 _constant_mass(getParam<bool>(
"use_constant_mass")),
86 _recompute_mass_matrix_on_mesh_change(
87 getParam<bool>(
"recompute_mass_matrix_after_mesh_change")),
89 _mass_matrix_name(getParam<TagName>(
"mass_matrix_tag")),
90 _mass_matrix_lumped(addVector(
"mass_matrix_lumped", true, GHOSTED)),
91 _solution_older(_sys.solutionState(2)),
92 _vars_first(declareRestartableData<
std::unordered_set<unsigned
int>>(
"first_order_vars")),
93 _local_first_order_indices(
94 declareRestartableData<
std::vector<dof_id_type>>(
"first_local_indices")),
95 _vars_second(declareRestartableData<
std::unordered_set<unsigned
int>>(
"second_order_vars")),
96 _local_second_order_indices(
97 declareRestartableData<
std::vector<dof_id_type>>(
"second_local_indices"))
120 paramError(
"recompute_mass_matrix_after_mesh_change",
121 "Must be set to true explicitly by the user to support adaptivity with "
122 "`use_constant_mass`.");
219 bool converged =
false;
227 const std::unique_ptr<NumericVector<Number>> mass_inv_first(
229 const std::unique_ptr<NumericVector<Real>> exp_res_first(
238 vel_first->pointwise_mult(*mass_inv_first, *exp_res_first);
245 const std::unique_ptr<NumericVector<Real>> mass_inv_second(
247 const std::unique_ptr<NumericVector<Real>> exp_res_second(
259 accel_second->pointwise_mult(*mass_inv_second, *exp_res_second);
262 auto accel_scaled = accel_second->clone();
266 *vel_second += *accel_scaled;
279 converged = std::isfinite(sum);
299 const auto & var_names_first = getParam<std::vector<VariableName>>(
"first_order_vars");
300 const auto & var_names_second = getParam<std::vector<VariableName>>(
"second_order_vars");
301 std::vector<unsigned int> var_num_vec;
305 std::unordered_set<unsigned int> var_nums(var_num_vec.begin(), var_num_vec.end());
307 for (
const auto & var_name : var_names_first)
308 if (lm_sys.has_variable(var_name))
310 const auto var_num = lm_sys.variable_number(var_name);
312 var_nums.erase(var_num);
315 for (
const auto & var_name : var_names_second)
316 if (lm_sys.has_variable(var_name))
318 const auto var_num = lm_sys.variable_number(var_name);
320 var_nums.erase(var_num);
324 if (!var_nums.empty())
325 mooseError(
"Not all nonlinear variables have their order specified.");
333 std::vector<dof_id_type> var_dof_indices, work_vec;
338 lm_sys.get_dof_map().local_variable_indices(var_dof_indices, lm_sys.get_mesh(), var_num);
339 std::merge(work_vec.begin(),
341 var_dof_indices.begin(),
342 var_dof_indices.end(),
347 var_dof_indices.clear();
353 lm_sys.get_dof_map().local_variable_indices(var_dof_indices, lm_sys.get_mesh(), var_num);
354 std::merge(work_vec.begin(),
356 var_dof_indices.begin(),
357 var_dof_indices.end(),
379 mooseError(
"Time order sets are both empty.");
386 " does not exist in time order sets.");
registerMooseObjectRenamed("SolidMechanicsApp", DirectCentralDifference, "10/14/2025 00:00", ExplicitMixedOrder)
registerMooseObject("SolidMechanicsApp", ExplicitMixedOrder)
void ErrorVector unsigned int
Implements a form of the central difference time integrator that calculates acceleration directly fro...
std::unordered_set< unsigned int > & _vars_second
TimeOrder findVariableTimeOrder(unsigned int var_num) const
Retrieve the order of the highest time derivative of a variable.
virtual void meshChanged() override
const bool & _recompute_mass_matrix_on_mesh_change
Must be set to true to use adaptivity with a constant mass matrix.
ExplicitMixedOrder(const InputParameters ¶meters)
virtual void evaluateRHSResidual()
Evaluate the RHS residual.
NumericVector< Real > * _mass_matrix_lumped
Lumped mass matrix.
virtual void postResidual(NumericVector< Number > &residual) override
const TagName & _mass_matrix_name
Mass matrix name.
virtual void solve() override
virtual TagID massMatrixTagID() const override
std::unordered_set< unsigned int > & _vars_first
const bool & _constant_mass
Whether we are reusing the mass matrix.
bool _mesh_changed
Whether the mesh changed just before the current solve.
void updateDOFIndices()
compile the dof indices for first and second order in time variables
std::vector< dof_id_type > & _local_second_order_indices
virtual void init() override
static InputParameters validParams()
std::vector< dof_id_type > & _local_first_order_indices
virtual bool performExplicitSolve(SparseMatrix< Number > &mass_matrix) override
virtual void computeTimeDerivatives() override
virtual void meshChanged() override
virtual void init() override
NumericVector< Real > * _mass_matrix_diag_inverted
NumericVector< Real > * _ones
static InputParameters validParams()
NumericVector< Real > * _solution_update
NumericVector< Real > * _explicit_residual
virtual void setUDotOldRequested(const bool u_dot_old_requested)
virtual void setUDotDotRequested(const bool u_dotdot_requested)
void computeResidual(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual)
virtual Real & timeOld() const
virtual Real & time() const
virtual void setUDotRequested(const bool u_dot_requested)
virtual void computeJacobianTag(const NumericVector< libMesh::Number > &soln, libMesh::SparseMatrix< libMesh::Number > &jacobian, TagID tag)
void paramError(const std::string ¶m, Args... args) const
void mooseError(Args &&... args) const
void overwriteNodeFace(NumericVector< Number > &soln)
NonlinearSystemBase * _nl
NumericVector< Number > * _Re_non_time
NumericVector< Number > * _Re_time
libMesh::NonlinearImplicitSystem * _nonlinear_implicit_system
void setSolution(const NumericVector< Number > &soln)
virtual TagID getMatrixTagID(const TagName &tag_name) const
virtual NumericVector< Number > * solutionUDot()
unsigned int number() const
NumericVector< Number > & solutionOld()
SubProblem & subproblem()
virtual libMesh::System & system()=0
virtual NumericVector< Number > * solutionUDotDot()
const NumericVector< Number > *const & _solution
unsigned int _n_linear_iterations
unsigned int _n_nonlinear_iterations
FEProblemBase & _fe_problem
const NumericVector< Number > & _solution_old
const SparseMatrix< Number > & get_system_matrix() const
std::unique_ptr< NonlinearSolver< Number > > nonlinear_solver
const Parallel::Communicator & _communicator
std::unique_ptr< NumericVector< Number > > current_local_solution
void get_all_variable_numbers(std::vector< unsigned int > &all_variable_numbers) const
std::unique_ptr< NumericVector< Number > > solution
const std::string & variable_name(const unsigned int i) const
SolverPackage default_solver_package()