LCOV - code coverage report
Current view: top level - src/nodalkernels - NodalTranslationalInertia.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: f45d79 Lines: 98 104 94.2 %
Date: 2025-07-25 05:00:39 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         566 : NodalTranslationalInertia::validParams()
      22             : {
      23         566 :   InputParameters params = TimeNodalKernel::validParams();
      24         566 :   params.addClassDescription("Computes the inertial forces and mass proportional damping terms "
      25             :                              "corresponding to nodal mass.");
      26        1132 :   params.addCoupledVar("velocity", "velocity variable");
      27        1132 :   params.addCoupledVar("acceleration", "acceleration variable");
      28        1132 :   params.addRangeCheckedParam<Real>(
      29             :       "beta", "beta>0.0", "beta parameter for Newmark Time integration");
      30        1132 :   params.addRangeCheckedParam<Real>(
      31             :       "gamma", "gamma>0.0", "gamma parameter for Newmark Time integration");
      32        1698 :   params.addRangeCheckedParam<Real>("eta",
      33        1132 :                                     0.0,
      34             :                                     "eta>=0.0",
      35             :                                     "Constant real number defining the eta parameter for "
      36             :                                     "Rayleigh damping.");
      37        1698 :   params.addRangeCheckedParam<Real>("alpha",
      38        1132 :                                     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        1132 :   params.addParam<Real>("mass", "Mass associated with the node");
      43        1132 :   params.addParam<FileName>(
      44             :       "nodal_mass_file",
      45             :       "The file containing the nodal positions and the corresponding nodal masses.");
      46         566 :   return params;
      47           0 : }
      48             : 
      49         274 : NodalTranslationalInertia::NodalTranslationalInertia(const InputParameters & parameters)
      50             :   : TimeNodalKernel(parameters),
      51         274 :     _has_mass(isParamValid("mass")),
      52         548 :     _has_beta(isParamValid("beta")),
      53         548 :     _has_gamma(isParamValid("gamma")),
      54         548 :     _has_velocity(isParamValid("velocity")),
      55         548 :     _has_acceleration(isParamValid("acceleration")),
      56         548 :     _has_nodal_mass_file(isParamValid("nodal_mass_file")),
      57         452 :     _mass(_has_mass ? getParam<Real>("mass") : 0.0),
      58         458 :     _beta(_has_beta ? getParam<Real>("beta") : 0.1),
      59         458 :     _gamma(_has_gamma ? getParam<Real>("gamma") : 0.1),
      60         548 :     _eta(getParam<Real>("eta")),
      61         548 :     _alpha(getParam<Real>("alpha")),
      62         548 :     _time_integrator(_sys.getTimeIntegrator(_var.number()))
      63             : {
      64         274 :   if (_has_beta && _has_gamma && _has_velocity && _has_acceleration)
      65             :   {
      66         184 :     _u_old = &(_var.dofValuesOld());
      67         184 :     _aux_sys = &(_fe_problem.getAuxiliarySystem());
      68             : 
      69         368 :     MooseVariable * vel_variable = getVar("velocity", 0);
      70         184 :     _vel_num = vel_variable->number();
      71         368 :     MooseVariable * accel_variable = getVar("acceleration", 0);
      72         184 :     _accel_num = accel_variable->number();
      73         184 :   }
      74          90 :   else if (!_has_beta && !_has_gamma && !_has_velocity && !_has_acceleration)
      75             :   {
      76          90 :     _du_dot_du = &(_var.duDotDu());
      77          90 :     _du_dotdot_du = &(_var.duDotDotDu());
      78          90 :     _u_dot_old = &(_var.dofValuesDotOld());
      79             : 
      80          90 :     addFEVariableCoupleableVectorTag(_time_integrator.uDotFactorTag());
      81          90 :     addFEVariableCoupleableVectorTag(_time_integrator.uDotDotFactorTag());
      82             : 
      83          90 :     _u_dot_factor = &_var.vectorTagDofValue(_time_integrator.uDotFactorTag());
      84          90 :     _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         274 :   if (!_has_nodal_mass_file && !_has_mass)
      91           2 :     mooseError(
      92             :         "NodalTranslationalInertia: Please provide either mass or nodal_mass_file as input.");
      93         272 :   else if (_has_nodal_mass_file && _has_mass)
      94           4 :     mooseError("NodalTranslationalInertia: Please provide either mass or nodal_mass_file as input, "
      95             :                "not both.");
      96             : 
      97         268 :   if (_has_nodal_mass_file)
      98             :   {
      99         282 :     MooseUtils::DelimitedFileReader nodal_mass_file(getParam<FileName>("nodal_mass_file"));
     100             :     nodal_mass_file.setHeaderFlag(MooseUtils::DelimitedFileReader::HeaderFlag::OFF);
     101          94 :     nodal_mass_file.read();
     102          94 :     std::vector<std::vector<Real>> data = nodal_mass_file.getData();
     103          94 :     if (data.size() != 4)
     104           4 :       mooseError("NodalTranslationalInertia: The number of columns in ",
     105             :                  getParam<FileName>("nodal_mass_file"),
     106             :                  " should be 4.");
     107          92 :     unsigned int node_found = 0;
     108          92 :     const std::set<BoundaryID> bnd_ids = BoundaryRestrictable::boundaryIDs();
     109         202 :     for (auto & bnd_id : bnd_ids)
     110             :     {
     111         110 :       const std::vector<dof_id_type> & bnd_node_set = _mesh.getNodeList(bnd_id);
     112         796 :       for (auto & bnd_node : bnd_node_set)
     113             :       {
     114         686 :         const Node & node = _mesh.nodeRef(bnd_node);
     115         686 :         _node_id_to_mass[bnd_node] = 0.0;
     116             : 
     117        3622 :         for (unsigned int i = 0; i < data[0].size(); ++i)
     118             :         {
     119        1910 :           if (MooseUtils::absoluteFuzzyEqual(data[0][i], node(0), 1e-6) &&
     120        4740 :               MooseUtils::absoluteFuzzyEqual(data[1][i], node(1), 1e-6) &&
     121             :               MooseUtils::absoluteFuzzyEqual(data[2][i], node(2), 1e-6))
     122             :           {
     123         686 :             _node_id_to_mass[bnd_node] = data[3][i];
     124         686 :             node_found += 1;
     125         686 :             break;
     126             :           }
     127             :         }
     128             :       }
     129             :     }
     130          92 :     if (node_found != data[0].size())
     131           2 :       mooseError("NodalTranslationalInertia: Out of ",
     132           2 :                  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          90 :   }
     139             : 
     140             :   // Check for Explicit and alpha parameter
     141         264 :   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         264 :   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         264 : }
     151             : 
     152             : Real
     153       33366 : NodalTranslationalInertia::computeQpResidual()
     154             : {
     155       33366 :   if (_dt == 0)
     156             :     return 0;
     157             :   else
     158             :   {
     159             :     Real mass = 0.0;
     160       33366 :     if (_has_mass)
     161       15606 :       mass = _mass;
     162             :     else
     163             :     {
     164       17760 :       if (_node_id_to_mass.find(_current_node->id()) != _node_id_to_mass.end())
     165       17760 :         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       33366 :     if (_has_beta)
     172             :     {
     173             :       mooseAssert(_beta > 0.0, "NodalTranslationalInertia: Beta parameter should be positive.");
     174       16800 :       const NumericVector<Number> & aux_sol_old = _aux_sys->solutionOld();
     175             : 
     176       16800 :       const Real vel_old = aux_sol_old(_current_node->dof_number(_aux_sys->number(), _vel_num, 0));
     177             :       const Real accel_old =
     178       16800 :           aux_sol_old(_current_node->dof_number(_aux_sys->number(), _accel_num, 0));
     179             : 
     180             :       const Real accel =
     181       16800 :           1. / _beta *
     182       16800 :           (((_u[_qp] - (*_u_old)[_qp]) / (_dt * _dt)) - vel_old / _dt - accel_old * (0.5 - _beta));
     183       16800 :       const Real vel = vel_old + (_dt * (1 - _gamma)) * accel_old + _gamma * _dt * accel;
     184       16800 :       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       16566 :       return mass * ((*_u_dotdot_factor)[_qp] + (*_u_dot_factor)[_qp] * _eta * (1.0 + _alpha) -
     191       16566 :                      _alpha * _eta * (*_u_dot_old)[_qp]);
     192             :   }
     193             : }
     194             : 
     195             : Real
     196       18402 : NodalTranslationalInertia::computeQpJacobian()
     197             : {
     198             :   mooseAssert(_beta > 0.0, "NodalTranslationalInertia: Beta parameter should be positive.");
     199             : 
     200       18402 :   if (_dt == 0)
     201             :     return 0;
     202             :   else
     203             :   {
     204             :     Real mass = 0.0;
     205       18402 :     if (_has_mass)
     206        7806 :       mass = _mass;
     207             :     else
     208             :     {
     209       10596 :       if (_node_id_to_mass.find(_current_node->id()) != _node_id_to_mass.end())
     210       10596 :         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       18402 :     if (_has_beta)
     216        8400 :       return mass / (_beta * _dt * _dt) + _eta * (1 + _alpha) * mass * _gamma / _beta / _dt;
     217             :     else
     218       10002 :       return mass * (*_du_dotdot_du)[_qp] + _eta * (1.0 + _alpha) * mass * (*_du_dot_du)[_qp];
     219             :   }
     220             : }

Generated by: LCOV version 1.14