LCOV - code coverage report
Current view: top level - src/nodalkernels - NodalTranslationalInertia.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #32971 (54bef8) with base c6cf66 Lines: 98 104 94.2 %
Date: 2026-05-29 20:40:07 Functions: 4 4 100.0 %
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             : #include "NodalTranslationalInertia.h"
      11             : #include "MooseVariable.h"
      12             : #include "AuxiliarySystem.h"
      13             : #include "MooseUtils.h"
      14             : #include "DelimitedFileReader.h"
      15             : #include "TimeIntegrator.h"
      16             : #include "FEProblemBase.h"
      17             : 
      18             : registerMooseObject("SolidMechanicsApp", NodalTranslationalInertia);
      19             : 
      20             : InputParameters
      21         359 : NodalTranslationalInertia::validParams()
      22             : {
      23         359 :   InputParameters params = TimeNodalKernel::validParams();
      24         359 :   params.addClassDescription("Computes the inertial forces and mass proportional damping terms "
      25             :                              "corresponding to nodal mass.");
      26         718 :   params.addCoupledVar("velocity", "velocity variable");
      27         718 :   params.addCoupledVar("acceleration", "acceleration variable");
      28         718 :   params.addRangeCheckedParam<Real>(
      29             :       "beta", "beta>0.0", "beta parameter for Newmark Time integration");
      30         718 :   params.addRangeCheckedParam<Real>(
      31             :       "gamma", "gamma>0.0", "gamma parameter for Newmark Time integration");
      32        1077 :   params.addRangeCheckedParam<Real>("eta",
      33         718 :                                     0.0,
      34             :                                     "eta>=0.0",
      35             :                                     "Constant real number defining the eta parameter for "
      36             :                                     "Rayleigh damping.");
      37        1077 :   params.addRangeCheckedParam<Real>("alpha",
      38         718 :                                     0.0,
      39             :                                     "alpha >= -0.3333 & alpha <= 0.0",
      40             :                                     "Alpha parameter for mass dependent numerical damping induced "
      41             :                                     "by HHT time integration scheme");
      42         718 :   params.addParam<Real>("mass", "Mass associated with the node");
      43         718 :   params.addParam<FileName>(
      44             :       "nodal_mass_file",
      45             :       "The file containing the nodal positions and the corresponding nodal masses.");
      46         359 :   return params;
      47           0 : }
      48             : 
      49         176 : NodalTranslationalInertia::NodalTranslationalInertia(const InputParameters & parameters)
      50             :   : TimeNodalKernel(parameters),
      51         176 :     _has_mass(isParamValid("mass")),
      52         352 :     _has_beta(isParamValid("beta")),
      53         352 :     _has_gamma(isParamValid("gamma")),
      54         352 :     _has_velocity(isParamValid("velocity")),
      55         352 :     _has_acceleration(isParamValid("acceleration")),
      56         352 :     _has_nodal_mass_file(isParamValid("nodal_mass_file")),
      57         289 :     _mass(_has_mass ? getParam<Real>("mass") : 0.0),
      58         292 :     _beta(_has_beta ? getParam<Real>("beta") : 0.1),
      59         292 :     _gamma(_has_gamma ? getParam<Real>("gamma") : 0.1),
      60         352 :     _eta(getParam<Real>("eta")),
      61         352 :     _alpha(getParam<Real>("alpha")),
      62         352 :     _time_integrator(_sys.getTimeIntegrator(_var.number()))
      63             : {
      64         176 :   if (_has_beta && _has_gamma && _has_velocity && _has_acceleration)
      65             :   {
      66         116 :     _u_old = &(_var.dofValuesOld());
      67         116 :     _aux_sys = &(_fe_problem.getAuxiliarySystem());
      68             : 
      69         232 :     MooseVariable * vel_variable = getVar("velocity", 0);
      70         116 :     _vel_num = vel_variable->number();
      71         232 :     MooseVariable * accel_variable = getVar("acceleration", 0);
      72         116 :     _accel_num = accel_variable->number();
      73         116 :   }
      74          60 :   else if (!_has_beta && !_has_gamma && !_has_velocity && !_has_acceleration)
      75             :   {
      76          60 :     _du_dot_du = &(_var.duDotDu());
      77          60 :     _du_dotdot_du = &(_var.duDotDotDu());
      78          60 :     _u_dot_old = &(_var.dofValuesDotOld());
      79             : 
      80          60 :     addFEVariableCoupleableVectorTag(_time_integrator.uDotFactorTag());
      81          60 :     addFEVariableCoupleableVectorTag(_time_integrator.uDotDotFactorTag());
      82             : 
      83          60 :     _u_dot_factor = &_var.vectorTagDofValue(_time_integrator.uDotFactorTag());
      84          60 :     _u_dotdot_factor = &_var.vectorTagDofValue(_time_integrator.uDotDotFactorTag());
      85             :   }
      86             :   else
      87           0 :     mooseError("NodalTranslationalInertia: Either all or none of `beta`, `gamma`, `velocity` and "
      88             :                "`acceleration` should be provided as input.");
      89             : 
      90         176 :   if (!_has_nodal_mass_file && !_has_mass)
      91           1 :     mooseError(
      92             :         "NodalTranslationalInertia: Please provide either mass or nodal_mass_file as input.");
      93         175 :   else if (_has_nodal_mass_file && _has_mass)
      94           2 :     mooseError("NodalTranslationalInertia: Please provide either mass or nodal_mass_file as input, "
      95             :                "not both.");
      96             : 
      97         173 :   if (_has_nodal_mass_file)
      98             :   {
      99         186 :     MooseUtils::DelimitedFileReader nodal_mass_file(getParam<FileName>("nodal_mass_file"));
     100             :     nodal_mass_file.setHeaderFlag(MooseUtils::DelimitedFileReader::HeaderFlag::OFF);
     101          62 :     nodal_mass_file.read();
     102          62 :     std::vector<std::vector<Real>> data = nodal_mass_file.getData();
     103          62 :     if (data.size() != 4)
     104           2 :       mooseError("NodalTranslationalInertia: The number of columns in ",
     105             :                  getParam<FileName>("nodal_mass_file"),
     106             :                  " should be 4.");
     107          61 :     unsigned int node_found = 0;
     108          61 :     const std::set<BoundaryID> bnd_ids = BoundaryRestrictable::boundaryIDs();
     109         134 :     for (auto & bnd_id : bnd_ids)
     110             :     {
     111          73 :       const std::vector<dof_id_type> & bnd_node_set = _mesh.getNodeList(bnd_id);
     112         530 :       for (auto & bnd_node : bnd_node_set)
     113             :       {
     114         457 :         const Node & node = _mesh.nodeRef(bnd_node);
     115         457 :         _node_id_to_mass[bnd_node] = 0.0;
     116             : 
     117        2414 :         for (unsigned int i = 0; i < data[0].size(); ++i)
     118             :         {
     119        1273 :           if (MooseUtils::absoluteFuzzyEqual(data[0][i], node(0), 1e-6) &&
     120        3159 :               MooseUtils::absoluteFuzzyEqual(data[1][i], node(1), 1e-6) &&
     121             :               MooseUtils::absoluteFuzzyEqual(data[2][i], node(2), 1e-6))
     122             :           {
     123         457 :             _node_id_to_mass[bnd_node] = data[3][i];
     124         457 :             node_found += 1;
     125         457 :             break;
     126             :           }
     127             :         }
     128             :       }
     129             :     }
     130          61 :     if (node_found != data[0].size())
     131           1 :       mooseError("NodalTranslationalInertia: Out of ",
     132           1 :                  data[0].size(),
     133             :                  " nodal positions in ",
     134             :                  getParam<FileName>("nodal_mass_file"),
     135             :                  " only ",
     136             :                  node_found,
     137             :                  " nodes were found in the boundary.");
     138          60 :   }
     139             : 
     140             :   // Check for Explicit and alpha parameter
     141         171 :   if (_alpha != 0 && _time_integrator.isExplicit())
     142           0 :     mooseError("NodalTranslationalInertia: HHT time integration parameter can only be used with "
     143             :                "Newmark-Beta time integration.");
     144             : 
     145             :   // Check if beta and explicit are being used simultaneously
     146         171 :   if (_has_beta && _time_integrator.isExplicit())
     147           0 :     mooseError("NodalTranslationalInertia: Newmark-beta integration parameter, beta, cannot be "
     148             :                "provided along with an explicit time "
     149             :                "integrator.");
     150         171 : }
     151             : 
     152             : Real
     153       25173 : NodalTranslationalInertia::computeQpResidual()
     154             : {
     155       25173 :   if (_dt == 0)
     156             :     return 0;
     157             :   else
     158             :   {
     159             :     Real mass = 0.0;
     160       25173 :     if (_has_mass)
     161       11751 :       mass = _mass;
     162             :     else
     163             :     {
     164       13422 :       if (_node_id_to_mass.find(_current_node->id()) != _node_id_to_mass.end())
     165       13422 :         mass = _node_id_to_mass[_current_node->id()];
     166             :       else
     167           0 :         mooseError("NodalTranslationalInertia: Unable to find an entry for the current node in the "
     168             :                    "_node_id_to_mass map.");
     169             :     }
     170             : 
     171       25173 :     if (_has_beta)
     172             :     {
     173             :       mooseAssert(_beta > 0.0, "NodalTranslationalInertia: Beta parameter should be positive.");
     174       12654 :       const NumericVector<Number> & aux_sol_old = _aux_sys->solutionOld();
     175             : 
     176       12654 :       const Real vel_old = aux_sol_old(_current_node->dof_number(_aux_sys->number(), _vel_num, 0));
     177             :       const Real accel_old =
     178       12654 :           aux_sol_old(_current_node->dof_number(_aux_sys->number(), _accel_num, 0));
     179             : 
     180             :       const Real accel =
     181       12654 :           1. / _beta *
     182       12654 :           (((_u[_qp] - (*_u_old)[_qp]) / (_dt * _dt)) - vel_old / _dt - accel_old * (0.5 - _beta));
     183       12654 :       const Real vel = vel_old + (_dt * (1 - _gamma)) * accel_old + _gamma * _dt * accel;
     184       12654 :       return mass * (accel + vel * _eta * (1 + _alpha) - _alpha * _eta * vel_old);
     185             :     }
     186             : 
     187             :     else
     188             :       // all cases (Explicit, implicit and implicit with HHT)
     189             :       // Note that _alpha is enforced to be zero for explicit integration
     190       12519 :       return mass * ((*_u_dotdot_factor)[_qp] + (*_u_dot_factor)[_qp] * _eta * (1.0 + _alpha) -
     191       12519 :                      _alpha * _eta * (*_u_dot_old)[_qp]);
     192             :   }
     193             : }
     194             : 
     195             : Real
     196       13917 : NodalTranslationalInertia::computeQpJacobian()
     197             : {
     198             :   mooseAssert(_beta > 0.0, "NodalTranslationalInertia: Beta parameter should be positive.");
     199             : 
     200       13917 :   if (_dt == 0)
     201             :     return 0;
     202             :   else
     203             :   {
     204             :     Real mass = 0.0;
     205       13917 :     if (_has_mass)
     206        5877 :       mass = _mass;
     207             :     else
     208             :     {
     209        8040 :       if (_node_id_to_mass.find(_current_node->id()) != _node_id_to_mass.end())
     210        8040 :         mass = _node_id_to_mass[_current_node->id()];
     211             :       else
     212           0 :         mooseError("NodalTranslationalInertia: Unable to find an entry for the current node in the "
     213             :                    "_node_id_to_mass map.");
     214             :     }
     215       13917 :     if (_has_beta)
     216        6327 :       return mass / (_beta * _dt * _dt) + _eta * (1 + _alpha) * mass * _gamma / _beta / _dt;
     217             :     else
     218        7590 :       return mass * (*_du_dotdot_du)[_qp] + _eta * (1.0 + _alpha) * mass * (*_du_dot_du)[_qp];
     219             :   }
     220             : }

Generated by: LCOV version 1.14