LCOV - code coverage report
Current view: top level - src/kernels - StressDivergenceBeam.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: f45d79 Lines: 158 166 95.2 %
Date: 2025-07-25 05:00:39 Functions: 7 7 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 "StressDivergenceBeam.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "Assembly.h"
      14             : #include "Material.h"
      15             : #include "MooseVariable.h"
      16             : #include "SystemBase.h"
      17             : #include "RankTwoTensor.h"
      18             : #include "NonlinearSystem.h"
      19             : #include "MooseMesh.h"
      20             : 
      21             : #include "libmesh/quadrature.h"
      22             : 
      23             : registerMooseObject("SolidMechanicsApp", StressDivergenceBeam);
      24             : 
      25             : InputParameters
      26        3284 : StressDivergenceBeam::validParams()
      27             : {
      28        3284 :   InputParameters params = Kernel::validParams();
      29        3284 :   params.addClassDescription("Quasi-static and dynamic stress divergence kernel for Beam element");
      30        6568 :   params.addRequiredParam<unsigned int>(
      31             :       "component",
      32             :       "An integer corresponding to the direction "
      33             :       "the variable this kernel acts in. (0 for disp_x, "
      34             :       "1 for disp_y, 2 for disp_z, 3 for rot_x, 4 for rot_y and 5 for rot_z)");
      35        6568 :   params.addRequiredCoupledVar(
      36             :       "displacements",
      37             :       "The displacements appropriate for the simulation geometry and coordinate system");
      38        6568 :   params.addRequiredCoupledVar(
      39             :       "rotations", "The rotations appropriate for the simulation geometry and coordinate system");
      40        6568 :   params.addParam<MaterialPropertyName>(
      41             :       "zeta",
      42        6568 :       0.0,
      43             :       "Name of material property or a constant real number defining the zeta parameter for the "
      44             :       "Rayleigh damping.");
      45        9852 :   params.addRangeCheckedParam<Real>(
      46        6568 :       "alpha", 0.0, "alpha >= -0.3333 & alpha <= 0.0", "alpha parameter for HHT time integration");
      47             : 
      48        3284 :   params.set<bool>("use_displaced_mesh") = true;
      49        3284 :   return params;
      50           0 : }
      51             : 
      52        1970 : StressDivergenceBeam::StressDivergenceBeam(const InputParameters & parameters)
      53             :   : Kernel(parameters),
      54        1970 :     _component(getParam<unsigned int>("component")),
      55        1970 :     _ndisp(coupledComponents("displacements")),
      56        1970 :     _disp_var(_ndisp),
      57        1970 :     _nrot(coupledComponents("rotations")),
      58        1970 :     _rot_var(_nrot),
      59        3940 :     _force(getMaterialPropertyByName<RealVectorValue>("forces")),
      60        1970 :     _moment(getMaterialPropertyByName<RealVectorValue>("moments")),
      61        1970 :     _K11(getMaterialPropertyByName<RankTwoTensor>("Jacobian_11")),
      62        1970 :     _K22(getMaterialPropertyByName<RankTwoTensor>("Jacobian_22")),
      63        1970 :     _K22_cross(getMaterialPropertyByName<RankTwoTensor>("Jacobian_22_cross")),
      64        1970 :     _K21_cross(getMaterialPropertyByName<RankTwoTensor>("Jacobian_12")),
      65        1970 :     _K21(getMaterialPropertyByName<RankTwoTensor>("Jacobian_21")),
      66        1970 :     _original_length(getMaterialPropertyByName<Real>("original_length")),
      67        1970 :     _total_rotation(getMaterialPropertyByName<RankTwoTensor>("total_rotation")),
      68        3940 :     _zeta(getMaterialProperty<Real>("zeta")),
      69        3940 :     _alpha(getParam<Real>("alpha")),
      70        5910 :     _isDamped(getParam<MaterialPropertyName>("zeta") != "0.0" || std::abs(_alpha) > 0.0),
      71        3940 :     _force_old(_isDamped ? &getMaterialPropertyOld<RealVectorValue>("forces") : nullptr),
      72        3940 :     _moment_old(_isDamped ? &getMaterialPropertyOld<RealVectorValue>("moments") : nullptr),
      73        3940 :     _total_rotation_old(_isDamped ? &getMaterialPropertyOld<RankTwoTensor>("total_rotation")
      74             :                                   : nullptr),
      75        2078 :     _force_older(std::abs(_alpha) > 0.0 ? &getMaterialPropertyOlder<RealVectorValue>("forces")
      76             :                                         : nullptr),
      77        2078 :     _moment_older(std::abs(_alpha) > 0.0 ? &getMaterialPropertyOlder<RealVectorValue>("moments")
      78             :                                          : nullptr),
      79        1970 :     _total_rotation_older(std::abs(_alpha) > 0.0
      80        2078 :                               ? &getMaterialPropertyOlder<RankTwoTensor>("total_rotation")
      81             :                               : nullptr),
      82        1970 :     _global_force_res(0),
      83        1970 :     _global_moment_res(0),
      84        1970 :     _force_local_t(0),
      85        1970 :     _moment_local_t(0),
      86        1970 :     _local_force_res(0),
      87        3940 :     _local_moment_res(0)
      88             : {
      89        1970 :   if (_ndisp != _nrot)
      90           2 :     mooseError(
      91             :         "StressDivergenceBeam: The number of displacement and rotation variables should be same.");
      92             : 
      93        7872 :   for (unsigned int i = 0; i < _ndisp; ++i)
      94        5904 :     _disp_var[i] = coupled("displacements", i);
      95             : 
      96        7872 :   for (unsigned int i = 0; i < _nrot; ++i)
      97        5904 :     _rot_var[i] = coupled("rotations", i);
      98        1968 : }
      99             : 
     100             : void
     101     1399992 : StressDivergenceBeam::computeResidual()
     102             : {
     103     1399992 :   prepareVectorTag(_assembly, _var.number());
     104             : 
     105             :   mooseAssert(_local_re.size() == 2,
     106             :               "StressDivergenceBeam: Beam element must have two nodes only.");
     107             : 
     108     1399992 :   _global_force_res.resize(_test.size());
     109     1399992 :   _global_moment_res.resize(_test.size());
     110             : 
     111     1399992 :   computeGlobalResidual(&_force, &_moment, &_total_rotation, _global_force_res, _global_moment_res);
     112             : 
     113             :   // add contributions from stiffness proportional damping (non-zero _zeta) or HHT time integration
     114             :   // (non-zero _alpha)
     115     1399992 :   if (_isDamped && _dt > 0.0)
     116     1399992 :     computeDynamicTerms(_global_force_res, _global_moment_res);
     117             : 
     118     4199976 :   for (_i = 0; _i < _test.size(); ++_i)
     119             :   {
     120     2799984 :     if (_component < 3)
     121     1399992 :       _local_re(_i) = _global_force_res[_i](_component);
     122             :     else
     123     1399992 :       _local_re(_i) = _global_moment_res[_i](_component - 3);
     124             :   }
     125             : 
     126     1399992 :   accumulateTaggedLocalResidual();
     127             : 
     128     1399992 :   if (_has_save_in)
     129             :   {
     130             :     Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
     131           0 :     for (_i = 0; _i < _save_in.size(); ++_i)
     132           0 :       _save_in[_i]->sys().solution().add_vector(_local_re, _save_in[_i]->dofIndices());
     133             :   }
     134     1399992 : }
     135             : 
     136             : void
     137      579192 : StressDivergenceBeam::computeJacobian()
     138             : {
     139      579192 :   prepareMatrixTag(_assembly, _var.number(), _var.number());
     140             : 
     141     1737576 :   for (unsigned int i = 0; i < _test.size(); ++i)
     142             :   {
     143     3475152 :     for (unsigned int j = 0; j < _phi.size(); ++j)
     144             :     {
     145     2316768 :       if (_component < 3)
     146     1737576 :         _local_ke(i, j) = (i == j ? 1 : -1) * _K11[0](_component, _component);
     147             :       else
     148             :       {
     149     1158384 :         if (i == j)
     150      579192 :           _local_ke(i, j) = _K22[0](_component - 3, _component - 3);
     151             :         else
     152      579192 :           _local_ke(i, j) = _K22_cross[0](_component - 3, _component - 3);
     153             :       }
     154             :     }
     155             :   }
     156             : 
     157             :   // scaling factor for Rayliegh damping and HHT time integration
     158      579192 :   if (_isDamped && _dt > 0.0)
     159      579192 :     _local_ke *= (1.0 + _alpha + (1.0 + _alpha) * _zeta[0] / _dt);
     160             : 
     161      579192 :   accumulateTaggedLocalMatrix();
     162             : 
     163      579192 :   if (_has_diag_save_in)
     164             :   {
     165             :     unsigned int rows = _local_ke.m();
     166           0 :     DenseVector<Number> diag(rows);
     167           0 :     for (unsigned int i = 0; i < rows; ++i)
     168           0 :       diag(i) = _local_ke(i, i);
     169             : 
     170             :     Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
     171           0 :     for (unsigned int i = 0; i < _diag_save_in.size(); ++i)
     172           0 :       _diag_save_in[i]->sys().solution().add_vector(diag, _diag_save_in[i]->dofIndices());
     173             :   }
     174      579192 : }
     175             : 
     176             : void
     177     3475152 : StressDivergenceBeam::computeOffDiagJacobian(const unsigned int jvar_num)
     178             : {
     179     3475152 :   if (jvar_num == _var.number())
     180      579192 :     computeJacobian();
     181             :   else
     182             :   {
     183             :     unsigned int coupled_component = 0;
     184             :     bool disp_coupled = false;
     185             :     bool rot_coupled = false;
     186             : 
     187     8687880 :     for (unsigned int i = 0; i < _ndisp; ++i)
     188             :     {
     189     7239900 :       if (jvar_num == _disp_var[i])
     190             :       {
     191             :         coupled_component = i;
     192             :         disp_coupled = true;
     193             :         break;
     194             :       }
     195             :     }
     196             : 
     197     8687880 :     for (unsigned int i = 0; i < _nrot; ++i)
     198             :     {
     199     7239900 :       if (jvar_num == _rot_var[i])
     200             :       {
     201     1447980 :         coupled_component = i + 3;
     202             :         rot_coupled = true;
     203     1447980 :         break;
     204             :       }
     205             :     }
     206             : 
     207     2895960 :     prepareMatrixTag(_assembly, _var.number(), jvar_num);
     208             : 
     209     2895960 :     if (disp_coupled || rot_coupled)
     210             :     {
     211     8687880 :       for (unsigned int i = 0; i < _test.size(); ++i)
     212             :       {
     213    17375760 :         for (unsigned int j = 0; j < _phi.size(); ++j)
     214             :         {
     215    11583840 :           if (_component < 3 && coupled_component < 3)
     216     3475152 :             _local_ke(i, j) += (i == j ? 1 : -1) * _K11[0](_component, coupled_component);
     217     9267072 :           else if (_component < 3 && coupled_component > 2)
     218             :           {
     219     3475152 :             if (i == 0)
     220     1737576 :               _local_ke(i, j) += _K21[0](coupled_component - 3, _component);
     221             :             else
     222     1737576 :               _local_ke(i, j) += _K21_cross[0](coupled_component - 3, _component);
     223             :           }
     224     5791920 :           else if (_component > 2 && coupled_component < 3)
     225             :           {
     226     3475152 :             if (j == 0)
     227     1737576 :               _local_ke(i, j) += _K21[0](_component - 3, coupled_component);
     228             :             else
     229     1737576 :               _local_ke(i, j) += _K21_cross[0](_component - 3, coupled_component);
     230             :           }
     231             :           else
     232             :           {
     233     2316768 :             if (i == j)
     234     1158384 :               _local_ke(i, j) += _K22[0](_component - 3, coupled_component - 3);
     235             :             else
     236     1158384 :               _local_ke(i, j) += _K22_cross[0](_component - 3, coupled_component - 3);
     237             :           }
     238             :         }
     239             :       }
     240             :     }
     241             : 
     242             :     // scaling factor for Rayleigh damping and HHT time integration
     243     2895960 :     if (_isDamped && _dt > 0.0)
     244     2895960 :       _local_ke *= (1.0 + _alpha + (1.0 + _alpha) * _zeta[0] / _dt);
     245             : 
     246     2895960 :     accumulateTaggedLocalMatrix();
     247             :   }
     248     3475152 : }
     249             : 
     250             : void
     251     1399992 : StressDivergenceBeam::computeDynamicTerms(std::vector<RealVectorValue> & global_force_res,
     252             :                                           std::vector<RealVectorValue> & global_moment_res)
     253             : {
     254             :   mooseAssert(_zeta[0] >= 0.0, "StressDivergenceBeam: Zeta parameter should be non-negative.");
     255     1399992 :   std::vector<RealVectorValue> global_force_res_old(_test.size());
     256     1399992 :   std::vector<RealVectorValue> global_moment_res_old(_test.size());
     257     1399992 :   computeGlobalResidual(
     258             :       _force_old, _moment_old, _total_rotation_old, global_force_res_old, global_moment_res_old);
     259             : 
     260             :   // For HHT calculation, the global force and moment residual from t_older is required
     261     2799984 :   std::vector<RealVectorValue> global_force_res_older(_test.size());
     262     1399992 :   std::vector<RealVectorValue> global_moment_res_older(_test.size());
     263             : 
     264     1399992 :   if (std::abs(_alpha) > 0.0)
     265       36000 :     computeGlobalResidual(_force_older,
     266             :                           _moment_older,
     267             :                           _total_rotation_older,
     268             :                           global_force_res_older,
     269             :                           global_moment_res_older);
     270             : 
     271             :   // Update the global_force_res and global_moment_res to include HHT and Rayleigh damping
     272             :   // contributions
     273     4199976 :   for (_i = 0; _i < _test.size(); ++_i)
     274             :   {
     275     2799984 :     global_force_res[_i] =
     276     2799984 :         global_force_res[_i] * (1.0 + _alpha + (1.0 + _alpha) * _zeta[0] / _dt) -
     277     2799984 :         global_force_res_old[_i] * (_alpha + (1.0 + 2.0 * _alpha) * _zeta[0] / _dt) +
     278     2799984 :         global_force_res_older[_i] * (_alpha * _zeta[0] / _dt);
     279     2799984 :     global_moment_res[_i] =
     280     2799984 :         global_moment_res[_i] * (1.0 + _alpha + (1.0 + _alpha) * _zeta[0] / _dt) -
     281     2799984 :         global_moment_res_old[_i] * (_alpha + (1.0 + 2.0 * _alpha) * _zeta[0] / _dt) +
     282     2799984 :         global_moment_res_older[_i] * (_alpha * _zeta[0] / _dt);
     283             :   }
     284     1399992 : }
     285             : 
     286             : void
     287     2835984 : StressDivergenceBeam::computeGlobalResidual(const MaterialProperty<RealVectorValue> * force,
     288             :                                             const MaterialProperty<RealVectorValue> * moment,
     289             :                                             const MaterialProperty<RankTwoTensor> * total_rotation,
     290             :                                             std::vector<RealVectorValue> & global_force_res,
     291             :                                             std::vector<RealVectorValue> & global_moment_res)
     292             : {
     293             :   RealVectorValue a;
     294     2835984 :   _force_local_t.resize(_qrule->n_points());
     295     2835984 :   _moment_local_t.resize(_qrule->n_points());
     296     2835984 :   _local_force_res.resize(_test.size());
     297     2835984 :   _local_moment_res.resize(_test.size());
     298             : 
     299             :   // convert forces/moments from global coordinate system to current beam local configuration
     300     8507952 :   for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
     301             :   {
     302     5671968 :     _force_local_t[_qp] = (*total_rotation)[0] * (*force)[_qp];
     303     5671968 :     _moment_local_t[_qp] = (*total_rotation)[0] * (*moment)[_qp];
     304             :   }
     305             : 
     306             :   // residual for displacement variables
     307     8507952 :   for (_i = 0; _i < _test.size(); ++_i)
     308             :   {
     309     5671968 :     _local_force_res[_i] = a;
     310    22687872 :     for (unsigned int component = 0; component < 3; ++component)
     311             :     {
     312    51047712 :       for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
     313    34031808 :         _local_force_res[_i](component) +=
     314    51047712 :             (_i == 0 ? -1 : 1) * _force_local_t[_qp](component) * 0.5;
     315             :     }
     316             :   }
     317             : 
     318             :   // residual for rotation variables
     319     8507952 :   for (_i = 0; _i < _test.size(); ++_i)
     320             :   {
     321     5671968 :     _local_moment_res[_i] = a;
     322    22687872 :     for (unsigned int component = 3; component < 6; ++component)
     323             :     {
     324    51047712 :       for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
     325             :       {
     326    34031808 :         if (component == 3)
     327    11343936 :           _local_moment_res[_i](component - 3) +=
     328    17015904 :               (_i == 0 ? -1 : 1) * _moment_local_t[_qp](0) * 0.5;
     329    22687872 :         else if (component == 4)
     330    11343936 :           _local_moment_res[_i](component - 3) +=
     331    17015904 :               (_i == 0 ? -1 : 1) * _moment_local_t[_qp](1) * 0.5 +
     332    11343936 :               _force_local_t[_qp](2) * 0.25 * _original_length[0];
     333             :         else
     334    11343936 :           _local_moment_res[_i](component - 3) +=
     335    17015904 :               (_i == 0 ? -1 : 1) * _moment_local_t[_qp](2) * 0.5 -
     336    11343936 :               _force_local_t[_qp](1) * 0.25 * _original_length[0];
     337             :       }
     338             :     }
     339             :   }
     340             : 
     341             :   // convert residual for each variable from current beam local configuration to global
     342             :   // configuration
     343     8507952 :   for (_i = 0; _i < _test.size(); ++_i)
     344             :   {
     345     5671968 :     global_force_res[_i] = (*total_rotation)[0].transpose() * _local_force_res[_i];
     346     5671968 :     global_moment_res[_i] = (*total_rotation)[0].transpose() * _local_moment_res[_i];
     347             :   }
     348     2835984 : }

Generated by: LCOV version 1.14