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`.");
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;
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.");
virtual void computeJacobianTag(const NumericVector< libMesh::Number > &soln, libMesh::SparseMatrix< libMesh::Number > &jacobian, TagID tag)
virtual TagID massMatrixTagID() const override
const TagName & _mass_matrix_name
Mass matrix name.
std::unique_ptr< NonlinearSolver< Number > > nonlinear_solver
void overwriteNodeFace(NumericVector< Number > &soln)
virtual Real & time() const
NumericVector< Real > * _solution_update
void paramError(const std::string ¶m, Args... args) const
virtual void setUDotDotRequested(const bool u_dotdot_requested)
NumericVector< Real > * _ones
std::unordered_set< unsigned int > & _vars_second
FEProblemBase & _fe_problem
NonlinearSystemBase * _nl
const bool & _constant_mass
Whether we are reusing the mass matrix.
virtual libMesh::System & system()=0
void setSolution(const NumericVector< Number > &soln)
void get_all_variable_numbers(std::vector< unsigned int > &all_variable_numbers) const
TimeOrder findVariableTimeOrder(unsigned int var_num) const
Retrieve the order of the highest time derivative of a variable.
virtual void postResidual(NumericVector< Number > &residual) override
Implements a form of the central difference time integrator that calculates acceleration directly fro...
const Parallel::Communicator & _communicator
NumericVector< Number > * _Re_time
NumericVector< Real > * _mass_matrix_lumped
Lumped mass matrix.
virtual void setUDotOldRequested(const bool u_dot_old_requested)
bool converged(const std::vector< std::pair< unsigned int, Real >> &residuals, const std::vector< Real > &abs_tolerances)
Based on the residuals, determine if the iterative process converged or not.
libMesh::NonlinearImplicitSystem * _nonlinear_implicit_system
static InputParameters validParams()
SolverPackage default_solver_package()
std::unordered_set< unsigned int > & _vars_first
std::vector< dof_id_type > & _local_second_order_indices
virtual TagID getMatrixTagID(const TagName &tag_name) const
registerMooseObject("SolidMechanicsApp", ExplicitMixedOrder)
virtual void setUDotRequested(const bool u_dot_requested)
NumericVector< Real > * _explicit_residual
virtual NumericVector< Number > * solutionUDot()
SubProblem & subproblem()
std::unique_ptr< NumericVector< Number > > solution
static InputParameters validParams()
unsigned int _n_linear_iterations
const bool & _recompute_mass_matrix_on_mesh_change
Must be set to true to use adaptivity with a constant mass matrix.
virtual void computeTimeDerivatives() override
const std::string & variable_name(const unsigned int i) const
unsigned int number() const
void computeResidual(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual)
registerMooseObjectRenamed("SolidMechanicsApp", DirectCentralDifference, "10/14/2025 00:00", ExplicitMixedOrder)
const NumericVector< Number > *const & _solution
NumericVector< Real > * _mass_matrix_diag_inverted
virtual void init() override
virtual void meshChanged() override
virtual bool performExplicitSolve(SparseMatrix< Number > &mass_matrix) override
virtual void init() override
static std::unique_ptr< NumericVector< Number > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
void mooseError(Args &&... args) const
void updateDOFIndices()
compile the dof indices for first and second order in time variables
std::unique_ptr< NumericVector< Number > > current_local_solution
virtual Real & timeOld() const
const NumericVector< Number > & _solution_old
unsigned int _n_nonlinear_iterations
virtual void meshChanged() override
virtual void solve() override
ExplicitMixedOrder(const InputParameters ¶meters)
virtual void evaluateRHSResidual()
Evaluate the RHS residual.
virtual NumericVector< Number > * solutionUDotDot()
NumericVector< Number > * _Re_non_time
NumericVector< Number > & solutionOld()
bool _mesh_changed
Whether the mesh changed just before the current solve.
const SparseMatrix< Number > & get_system_matrix() const
std::vector< dof_id_type > & _local_first_order_indices
void ErrorVector unsigned int