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