LCOV - code coverage report
Current view: top level - src/timeintegrators - ActuallyExplicitEuler.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 48 53 90.6 %
Date: 2025-07-17 01:28:37 Functions: 5 7 71.4 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14