Line data Source code
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 "ActuallyExplicitEuler.h" 12 : #include "NonlinearSystem.h" 13 : #include "FEProblem.h" 14 : 15 : // libMesh includes 16 : #include "libmesh/nonlinear_solver.h" 17 : 18 : using namespace libMesh; 19 : 20 : registerMooseObject("MooseApp", ActuallyExplicitEuler); 21 : 22 : InputParameters 23 29349 : ActuallyExplicitEuler::validParams() 24 : { 25 29349 : InputParameters params = ExplicitTimeIntegrator::validParams(); 26 : 27 29349 : params.addClassDescription( 28 : "Implementation of Explicit/Forward Euler without invoking any of the nonlinear solver"); 29 : 30 88047 : params.addParam<bool>("use_constant_mass", 31 58698 : false, 32 : "If set to true, will only compute the mass matrix in the first time step, " 33 : "and keep using it throughout the simulation."); 34 : 35 29349 : return params; 36 0 : } 37 : 38 546 : ActuallyExplicitEuler::ActuallyExplicitEuler(const InputParameters & parameters) 39 546 : : ExplicitTimeIntegrator(parameters), _constant_mass(getParam<bool>("use_constant_mass")) 40 : { 41 546 : } 42 : 43 : void 44 4007 : ActuallyExplicitEuler::computeTimeDerivatives() 45 : { 46 4007 : if (!_sys.solutionUDot()) 47 0 : mooseError("ActuallyExplicitEuler: Time derivative of solution (`u_dot`) is not stored. Please " 48 : "set uDotRequested() to true in FEProblemBase before requesting `u_dot`."); 49 : 50 4007 : NumericVector<Number> & u_dot = *_sys.solutionUDot(); 51 4007 : u_dot = *_solution; 52 4007 : computeTimeDerivativeHelper(u_dot, _solution_old); 53 4007 : u_dot.close(); 54 4007 : computeDuDotDu(); 55 4007 : } 56 : 57 : void 58 0 : ActuallyExplicitEuler::computeADTimeDerivatives(ADReal & ad_u_dot, 59 : const dof_id_type & dof, 60 : ADReal & /*ad_u_dotdot*/) const 61 : { 62 0 : computeTimeDerivativeHelper(ad_u_dot, _solution_old(dof)); 63 0 : } 64 : 65 : void 66 4136 : ActuallyExplicitEuler::solve() 67 : { 68 : // Reset iteration counts 69 4136 : _n_nonlinear_iterations = 0; 70 4136 : _n_linear_iterations = 0; 71 : 72 4136 : _current_time = _fe_problem.time(); 73 : 74 : // Set time to the time at which to evaluate the residual 75 4136 : _fe_problem.time() = _fe_problem.timeOld(); 76 4136 : _nonlinear_implicit_system->update(); 77 : 78 : // Compute the residual 79 4136 : _explicit_residual->zero(); 80 4136 : _fe_problem.computeResidual( 81 4136 : *_nonlinear_implicit_system->current_local_solution, *_explicit_residual, _nl->number()); 82 : 83 : // Move the residual to the RHS 84 4136 : *_explicit_residual *= -1.0; 85 : 86 : // Compute the mass matrix 87 4136 : auto & mass_matrix = _nonlinear_implicit_system->get_system_matrix(); 88 4136 : if (!_constant_mass || (_constant_mass && _t_step == 1)) 89 4136 : _fe_problem.computeJacobianTag( 90 4136 : *_nonlinear_implicit_system->current_local_solution, mass_matrix, _Ke_time_tag); 91 : 92 : // Perform the linear solve 93 4136 : bool converged = performExplicitSolve(mass_matrix); 94 : 95 : // Update the solution 96 4136 : *_nonlinear_implicit_system->solution = _nl->solutionOld(); 97 4136 : *_nonlinear_implicit_system->solution += *_solution_update; 98 : 99 : // Constraints may be solved in an uncoupled way. For example, momentum-balance equations may be 100 : // solved node-wise and then the solution (e.g. velocities or positions)can be applied to those 101 : // nodes without solving for such constraints on a system level. This strategy is being used for 102 : // node-face contact in explicit dynamics. 103 4136 : _nl->overwriteNodeFace(*_nonlinear_implicit_system->solution); 104 : 105 : // Enforce contraints on the solution 106 4136 : DofMap & dof_map = _nonlinear_implicit_system->get_dof_map(); 107 4136 : dof_map.enforce_constraints_exactly(*_nonlinear_implicit_system, 108 4136 : _nonlinear_implicit_system->solution.get()); 109 4136 : _nonlinear_implicit_system->update(); 110 : 111 4136 : _nl->setSolution(*_nonlinear_implicit_system->current_local_solution); 112 : 113 4136 : _nonlinear_implicit_system->nonlinear_solver->converged = converged; 114 4136 : } 115 : 116 : void 117 4136 : ActuallyExplicitEuler::postResidual(NumericVector<Number> & residual) 118 : { 119 4136 : residual += *_Re_time; 120 4136 : residual += *_Re_non_time; 121 4136 : residual.close(); 122 : 123 : // Reset time to the time at which to evaluate nodal BCs, which comes next 124 4136 : _fe_problem.time() = _current_time; 125 4136 : }