LCOV - code coverage report
Current view: top level - src/nodalkernels - NodalRotationalInertia.C (source / functions) Hit Total Coverage
Test: idaholab/moose tensor_mechanics: d6b47a Lines: 138 162 85.2 %
Date: 2024-02-27 11:53:14 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://www.mooseframework.org
       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 "NodalRotationalInertia.h"
      11             : #include "MooseVariable.h"
      12             : #include "AuxiliarySystem.h"
      13             : #include "MooseMesh.h"
      14             : #include "TimeIntegrator.h"
      15             : 
      16             : registerMooseObject("TensorMechanicsApp", NodalRotationalInertia);
      17             : 
      18             : InputParameters
      19          60 : NodalRotationalInertia::validParams()
      20             : {
      21          60 :   InputParameters params = TimeNodalKernel::validParams();
      22          60 :   params.addClassDescription("Calculates the inertial torques and inertia proportional damping "
      23             :                              "corresponding to the nodal rotational inertia.");
      24         120 :   params.addCoupledVar("rotations", "rotational displacement variables");
      25         120 :   params.addCoupledVar("rotational_velocities", "rotational velocity variables");
      26         120 :   params.addCoupledVar("rotational_accelerations", "rotational acceleration variables");
      27         120 :   params.addRangeCheckedParam<Real>(
      28             :       "beta", "beta>0.0", "beta parameter for Newmark Time integration");
      29         120 :   params.addRangeCheckedParam<Real>(
      30             :       "gamma", "gamma>0.0", "gamma parameter for Newmark Time integration");
      31         180 :   params.addRangeCheckedParam<Real>("eta",
      32         120 :                                     0.0,
      33             :                                     "eta>=0.0",
      34             :                                     "Constant real number defining the eta parameter for"
      35             :                                     "Rayleigh damping.");
      36         180 :   params.addRangeCheckedParam<Real>("alpha",
      37         120 :                                     0.0,
      38             :                                     "alpha >= -0.3333 & alpha <= 0.0",
      39             :                                     "Alpha parameter for mass dependent numerical damping induced "
      40             :                                     "by HHT time integration scheme");
      41         120 :   params.addRequiredRangeCheckedParam<Real>(
      42             :       "Ixx", "Ixx>0.0", "Moment of inertia in the x direction.");
      43         120 :   params.addRequiredRangeCheckedParam<Real>(
      44             :       "Iyy", "Iyy>0.0", "Moment of inertia in the y direction.");
      45         120 :   params.addRequiredRangeCheckedParam<Real>(
      46             :       "Izz", "Izz>0.0", "Moment of inertia in the z direction.");
      47         120 :   params.addParam<Real>("Ixy", 0.0, "Moment of inertia in the xy direction.");
      48         120 :   params.addParam<Real>("Ixz", 0.0, "Moment of inertia in the xz direction.");
      49         120 :   params.addParam<Real>("Iyz", 0.0, "Moment of inertia in the yz direction.");
      50         120 :   params.addParam<RealGradient>(
      51             :       "x_orientation", "Unit vector along the x direction if different from global x direction.");
      52         120 :   params.addParam<RealGradient>(
      53             :       "y_orientation", "Unit vector along the y direction if different from global y direction.");
      54         120 :   params.addRequiredRangeCheckedParam<unsigned int>(
      55             :       "component",
      56             :       "component<3",
      57             :       "An integer corresponding to the direction "
      58             :       "the variable this nodalkernel acts in. (0 for rot_x, "
      59             :       "1 for rot_y, and 2 for rot_z).");
      60          60 :   return params;
      61           0 : }
      62             : 
      63          31 : NodalRotationalInertia::NodalRotationalInertia(const InputParameters & parameters)
      64             :   : TimeNodalKernel(parameters),
      65          31 :     _has_beta(isParamValid("beta")),
      66          62 :     _has_gamma(isParamValid("gamma")),
      67          62 :     _has_rot_velocities(isParamValid("rotational_velocities")),
      68          62 :     _has_rot_accelerations(isParamValid("rotational_accelerations")),
      69          62 :     _has_x_orientation(isParamValid("x_orientation")),
      70          62 :     _has_y_orientation(isParamValid("y_orientation")),
      71          31 :     _nrot(coupledComponents("rotations")),
      72          31 :     _rot(_nrot),
      73          31 :     _rot_old(_nrot),
      74          31 :     _rot_vel_num(_nrot),
      75          31 :     _rot_accel_num(_nrot),
      76          31 :     _rot_variables(_nrot),
      77          31 :     _rot_accel(_nrot),
      78          31 :     _rot_vel(_nrot),
      79          31 :     _rot_vel_old(_nrot),
      80          53 :     _beta(_has_beta ? getParam<Real>("beta") : 0.1),
      81          53 :     _gamma(_has_gamma ? getParam<Real>("gamma") : 0.1),
      82          62 :     _eta(getParam<Real>("eta")),
      83          62 :     _alpha(getParam<Real>("alpha")),
      84          62 :     _component(getParam<unsigned int>("component")),
      85          31 :     _rot_dot_residual(_nrot),
      86          31 :     _rot_vel_old_value(_nrot),
      87          31 :     _rot_dotdot_residual(_nrot),
      88          93 :     _time_integrator(*_sys.getTimeIntegrator())
      89             : {
      90          31 :   if (_has_beta && _has_gamma && _has_rot_velocities && _has_rot_accelerations)
      91             :   {
      92          22 :     _aux_sys = &(_fe_problem.getAuxiliarySystem());
      93          44 :     if (coupledComponents("rotational_velocities") != _nrot ||
      94          43 :         coupledComponents("rotational_accelerations") != _nrot)
      95           1 :       mooseError(
      96             :           "NodalRotationalInertia: rotational_velocities and rotational_accelerations should "
      97             :           "be same size "
      98             :           "as rotations.");
      99             : 
     100          84 :     for (unsigned int i = 0; i < _nrot; ++i)
     101             :     {
     102          63 :       MooseVariable * rot_var = getVar("rotations", i);
     103          63 :       MooseVariable * rot_vel_var = getVar("rotational_velocities", i);
     104          63 :       MooseVariable * rot_accel_var = getVar("rotational_accelerations", i);
     105             : 
     106          63 :       _rot[i] = &rot_var->dofValues();
     107          63 :       _rot_old[i] = &rot_var->dofValuesOld();
     108             : 
     109          63 :       _rot_vel_num[i] = rot_vel_var->number();
     110          63 :       _rot_accel_num[i] = rot_accel_var->number();
     111             : 
     112          63 :       _rot_variables[i] = coupled("rotations", i);
     113             :     }
     114             :   }
     115           9 :   else if (!_has_beta && !_has_gamma && !_has_rot_velocities && !_has_rot_accelerations)
     116             :   {
     117          36 :     for (unsigned int i = 0; i < _nrot; ++i)
     118             :     {
     119          27 :       MooseVariable * rot_var = getVar("rotations", i);
     120          27 :       _rot_vel_old_value[i] = &rot_var->dofValuesDotOld();
     121          27 :       _rot_dot_residual[i] =
     122          27 :           &coupledVectorTagDofValue("rotations", _time_integrator.uDotFactorTag(), i);
     123          27 :       _rot_dotdot_residual[i] =
     124          27 :           &coupledVectorTagDofValue("rotations", _time_integrator.uDotDotFactorTag(), i);
     125             : 
     126          27 :       if (i == 0)
     127             :       {
     128           9 :         _du_dot_du = &rot_var->dofValuesDuDotDu();
     129           9 :         _du_dotdot_du = &rot_var->dofValuesDuDotDotDu();
     130             :       }
     131             :     }
     132             :   }
     133             :   else
     134           0 :     mooseError("NodalRotationalInertia: Either all or none of `beta`, `gamma`, "
     135             :                "`rotational_velocities` and `rotational_accelerations` should be provided as "
     136             :                "input.");
     137             : 
     138             :   // Store inertia values in inertia tensor
     139             :   _inertia.zero();
     140          60 :   _inertia(0, 0) = getParam<Real>("Ixx");
     141          60 :   _inertia(0, 1) = getParam<Real>("Ixy");
     142          60 :   _inertia(0, 2) = getParam<Real>("Ixz");
     143          30 :   _inertia(1, 0) = _inertia(0, 1);
     144          60 :   _inertia(1, 1) = getParam<Real>("Iyy");
     145          60 :   _inertia(1, 2) = getParam<Real>("Iyz");
     146          30 :   _inertia(2, 0) = _inertia(0, 2);
     147          30 :   _inertia(2, 1) = _inertia(1, 2);
     148          60 :   _inertia(2, 2) = getParam<Real>("Izz");
     149             : 
     150             :   // Check for positive definiteness of matrix using Sylvester's criterion.
     151          30 :   const Real det1 = _inertia(0, 0);
     152          30 :   const Real det2 = _inertia(0, 0) * _inertia(1, 1) - _inertia(0, 1) * _inertia(1, 0);
     153          30 :   const Real det3 = _inertia.det();
     154             : 
     155          30 :   if (det1 < 1e-6 || det2 < 1e-6 || det3 < 1e-6)
     156           1 :     mooseError("NodalRotationalInertia: The moment of inertia tensor should be positive definite.");
     157          29 :   if (_has_x_orientation && _has_y_orientation)
     158             :   {
     159           4 :     const RealGradient x_orientation = getParam<RealGradient>("x_orientation");
     160           4 :     const RealGradient y_orientation = getParam<RealGradient>("y_orientation");
     161             : 
     162           2 :     if (std::abs(x_orientation.norm() - 1.0) > 1e-6 || std::abs(y_orientation.norm() - 1.0) > 1e-6)
     163           1 :       mooseError("NodalRotationalInertia: x_orientation and y_orientation must be unit vectors.");
     164             : 
     165           1 :     Real sum = x_orientation(0) * y_orientation(0) + x_orientation(1) * y_orientation(1) +
     166           1 :                x_orientation(2) * y_orientation(2);
     167             : 
     168           1 :     if (std::abs(sum) > 1e-4)
     169           1 :       mooseError("NodalRotationalInertia: x_orientation and y_orientation should be perpendicular "
     170             :                  "to each other.");
     171             : 
     172             :     // Calculate z orientation as a cross product of the x and y orientations
     173             :     RealGradient z_orientation;
     174           0 :     z_orientation(0) = (x_orientation(1) * y_orientation(2) - x_orientation(2) * y_orientation(1));
     175           0 :     z_orientation(1) = (x_orientation(2) * y_orientation(0) - x_orientation(0) * y_orientation(2));
     176           0 :     z_orientation(2) = (x_orientation(0) * y_orientation(1) - x_orientation(1) * y_orientation(0));
     177             : 
     178             :     // Rotation matrix from global to original beam local configuration
     179           0 :     RankTwoTensor orientation;
     180           0 :     orientation(0, 0) = x_orientation(0);
     181           0 :     orientation(0, 1) = x_orientation(1);
     182           0 :     orientation(0, 2) = x_orientation(2);
     183           0 :     orientation(1, 0) = y_orientation(0);
     184           0 :     orientation(1, 1) = y_orientation(1);
     185           0 :     orientation(1, 2) = y_orientation(2);
     186           0 :     orientation(2, 0) = z_orientation(0);
     187           0 :     orientation(2, 1) = z_orientation(1);
     188           0 :     orientation(2, 2) = z_orientation(2);
     189             : 
     190           0 :     RankTwoTensor global_inertia = orientation.transpose() * _inertia * orientation;
     191           0 :     _inertia = global_inertia;
     192           0 :   }
     193          27 :   else if ((_has_x_orientation && !_has_y_orientation) ||
     194          27 :            (!_has_x_orientation && _has_y_orientation))
     195           0 :     mooseError("NodalRotationalInertia: Both x_orientation and y_orientation should be provided if "
     196             :                "x_orientation or "
     197             :                "y_orientation is different from global x or y direction, respectively.");
     198             : 
     199             :   // Check for Explicit and alpha parameter
     200          27 :   if (_alpha != 0 && _time_integrator.isExplicit())
     201           0 :     mooseError("NodalRotationalInertia: HHT time integration parameter can only be used with "
     202             :                "Newmark-Beta time integration.");
     203             : 
     204             :   // Check for Explicit and beta parameter
     205          27 :   if (_has_beta != 0 && _time_integrator.isExplicit())
     206           0 :     mooseError("NodalRotationalInertia: beta time integration parameter can only be used with "
     207             :                "Newmark-Beta time integrator.");
     208          27 : }
     209             : 
     210             : Real
     211        2703 : NodalRotationalInertia::computeQpResidual()
     212             : {
     213        2703 :   if (_dt == 0)
     214             :     return 0;
     215             :   else
     216             :   {
     217        2703 :     if (_has_beta)
     218             :     {
     219        1800 :       const NumericVector<Number> & aux_sol_old = _aux_sys->solutionOld();
     220             : 
     221        7200 :       for (unsigned int i = 0; i < _nrot; ++i)
     222             :       {
     223        5400 :         _rot_vel_old[i] =
     224        5400 :             aux_sol_old(_current_node->dof_number(_aux_sys->number(), _rot_vel_num[i], 0));
     225             :         const Real rot_accel_old =
     226        5400 :             aux_sol_old(_current_node->dof_number(_aux_sys->number(), _rot_accel_num[i], 0));
     227             : 
     228        5400 :         _rot_accel[i] = 1.0 / _beta *
     229        5400 :                         ((((*_rot[i])[_qp] - (*_rot_old[i])[_qp]) / (_dt * _dt)) -
     230        5400 :                          _rot_vel_old[i] / _dt - rot_accel_old * (0.5 - _beta));
     231        5400 :         _rot_vel[i] =
     232        5400 :             _rot_vel_old[i] + (_dt * (1.0 - _gamma)) * rot_accel_old + _gamma * _dt * _rot_accel[i];
     233             :       }
     234             : 
     235             :       Real res = 0.0;
     236        7200 :       for (unsigned int i = 0; i < _nrot; ++i)
     237        5400 :         res += _inertia(_component, i) * (_rot_accel[i] + _rot_vel[i] * _eta * (1.0 + _alpha) -
     238        5400 :                                           _alpha * _eta * _rot_vel_old[i]);
     239             : 
     240        1800 :       return res;
     241             :     }
     242             :     else
     243             :     {
     244             :       // All cases (Explicit, implicit and implicit with HHT)
     245             :       // Note that _alpha is ensured to be zero with explicit integration
     246             :       Real res = 0.0;
     247        3612 :       for (unsigned int i = 0; i < _nrot; ++i)
     248        2709 :         res += _inertia(_component, i) * ((*_rot_dotdot_residual[i])[_qp] +
     249        2709 :                                           (*_rot_dot_residual[i])[_qp] * _eta * (1.0 + _alpha) -
     250        2709 :                                           _alpha * _eta * (*_rot_vel_old_value[i])[_qp]);
     251         903 :       return res;
     252             :     }
     253             :   }
     254             : }
     255             : 
     256             : Real
     257         903 : NodalRotationalInertia::computeQpJacobian()
     258             : {
     259         903 :   if (_dt == 0)
     260             :     return 0.0;
     261             :   else
     262             :   {
     263         903 :     if (_has_beta)
     264         600 :       return _inertia(_component, _component) / (_beta * _dt * _dt) +
     265         600 :              _eta * (1.0 + _alpha) * _inertia(_component, _component) * _gamma / _beta / _dt;
     266         303 :     else if (_time_integrator.isExplicit())
     267             :       // for explicit central difference integration, _eta does not appear in the
     268             :       // Jacobian (mass matrix), and alpha is zero
     269           0 :       return _inertia(_component, _component) * (*_du_dotdot_du)[_qp];
     270             :     else
     271             :       // for NewmarkBeta time integrator
     272         303 :       return _inertia(_component, _component) * (*_du_dotdot_du)[_qp] +
     273         303 :              _eta * (1.0 + _alpha) * _inertia(_component, _component) * (*_du_dot_du)[_qp];
     274             :   }
     275             : }
     276             : 
     277             : Real
     278        1806 : NodalRotationalInertia::computeQpOffDiagJacobian(unsigned int jvar)
     279             : {
     280             :   unsigned int coupled_component = 0;
     281             :   bool rot_coupled = false;
     282             : 
     283        4824 :   for (unsigned int i = 0; i < _nrot; ++i)
     284             :   {
     285        4218 :     if (jvar == _rot_variables[i])
     286             :     {
     287             :       coupled_component = i;
     288             :       rot_coupled = true;
     289             :       break;
     290             :     }
     291             :   }
     292             : 
     293        1806 :   if (_dt == 0)
     294             :     return 0.0;
     295        1806 :   else if (rot_coupled)
     296             :   {
     297        1200 :     if (_has_beta)
     298        1200 :       return _inertia(_component, coupled_component) / (_beta * _dt * _dt) +
     299        1200 :              _eta * (1.0 + _alpha) * _inertia(_component, coupled_component) * _gamma / _beta / _dt;
     300             :     else
     301           0 :       return _inertia(_component, coupled_component) * (*_du_dotdot_du)[_qp] +
     302           0 :              _eta * (1.0 + _alpha) * _inertia(_component, coupled_component) * (*_du_dot_du)[_qp];
     303             :   }
     304             :   else
     305             :     return 0.0;
     306             : }

Generated by: LCOV version 1.14