Dynamics

Dynamic problems like the response of a multi degree of freedom structure to external forcing and wave propagation in a medium can also be solved using the Tensor Mechanics module.

The equation of motion for a typical dynamics problem has the following format: (1)

Here, is the mass matrix, is the damping matrix, is the stiffness matrix and is the vector of external forces acting at the nodes. , and are the vector of displacement, velocity and acceleration at the nodes, respectively.

Time integration

To solve the above equation for , an appropriate time integration scheme needs to be chosen. Newmark (Newmark, 1959) and Hilber-Hughes-Taylor (HHT) (Hughes, 2000) time integration schemes are two of the commonly used methods in dynamics.

Newmark time integration

In Newmark time integration, the acceleration and velocity at are written in terms of the displacement, velocity and acceleration at time and the displacement at using the NewmarkAccelAux and NewmarkVelAux Aux Kernels, respectively.

(2)

In the above equations, and are Newmark time integration parameters. Substituting the above two equations into the equation of motion will result in a linear system of equations () from which can be estimated.

  • For and , the Newmark time integration method is implicit and unconditionally stable. This is the constant average acceleration method with no numerical damping. This is recommended only when a constant timestep is used throughout the simulation. If for some reason, the simulation does not converge and the timestep is halved, this time integration method with no numerical damping can result in high frequency noise.

  • and results in the linear acceleration method where the acceleration is linearly varying between and .

  • and is identical to the central difference method.

note

For in structural dynamics problems, the Newmark method is unconditionally stable irrespective of the time-step . For , the Newmark method is at least second order accurate; it is first order accurate for all other values of .

Hilber-Hughes-Taylor time integration

The HHT time integration scheme is built upon Newmark time integration method. Here, in addition to the Newmark equations, the equation of motion is also altered resulting in:

(3)

Here, is the HHT parameter. For , and , the HHT method is at least second-order accurate and unconditionally stable. For non-zero values of , the response at high frequencies (above ) are numerically damped, provided and are defined as above.

More details about the Newmark method and HHT method can be found in these lecture notes.

Rayleigh damping

This is the most common form of structural damping used in dynamic problems. Here, the damping matrix () is assumed to be a linear combination of the mass and stiffness matrices, i.e., . Here, and are the mass and stiffness dependent Rayleigh damping parameters, respectively.

The equation of motion in the presence of Rayleigh damping is: (4)

The degree of damping in the system depends on the coefficients and as follows: (5)

where, is the damping ratio of the system as a function of frequency . For example, the damping ratio as a function of frequency for and is presented in Figure 1. Note that has units of rad/s and used in the figure has units of Hz.

Figure 1: Damping ratio as a function of frequency.

To model a constant damping ratio using Rayleigh damping, the aim is to find and such that the is close to the target damping ratio , which is a constant value, between the frequency range . This can be achieved by minimizing the difference between and for all the frequencies between and , i.e., if

(6)

Then, and results in two equations that are linear in and . Solving these two linear equations simultaneously gives:

(7)

A similar method can be used to estimate and for non-constant damping ratios.

Implementation and Usage

In the MOOSE framework, the mass and stiffness matrices are not explicitly calculated. Only the residuals are calculated. To get the residual, the equation of motion (with Rayleigh damping and HHT time integration) can be written as:

(8)

Here, is the density of the material and is the stress tensor. The weak form of the above equation is used to get the residuals.

The first two terms to the left that contain are calculated in the InertialForce kernel. , , and need to be passed as input to the InertialForce kernel.

The next two terms to the left involving are calculated in DynamicStressDivergenceTensors.

Note that the time derivative of and are approximated as follows:

(9)

The input file syntax for calculating the residual due to both the Inertial force and the DynamicStressDivergenceTensors is:

[Kernels]
  [./DynamicTensorMechanics]
    displacements = 'disp_x disp_y disp_z'
    zeta = 0.1
    alpha = 0.11
  [../]
  [./inertia_x]
    type = InertialForce
    variable = disp_x
    velocity = vel_x
    acceleration = accel_x
    beta = 0.25
    gamma = 0.5
    eta=0.1
    alpha = 0.11
  [../]
  [./inertia_y]
    type = InertialForce
    variable = disp_y
    velocity = vel_y
    acceleration = accel_y
    beta = 0.25
    gamma = 0.5
    eta=0.1
    alpha = 0.11
  [../]
  [./inertia_z]
    type = InertialForce
    variable = disp_z
    velocity = vel_z
    acceleration = accel_z
    beta = 0.25
    gamma = 0.5
    eta = 0.1
    alpha = 0.11
  [../]

[]
(modules/tensor_mechanics/test/tests/dynamics/rayleigh_damping/rayleigh_hht.i)

Here, ./DynamicTensorMechanics is the action that calls the DynamicStressDivergenceTensors kernel.

Finally, when using HHT time integration method, external forces like gravity and pressure also require as input.

note

For dynamic problems, it is recommended to use PresetDisplacement and PresetAcceleration for prescribing the displacement and acceleration at a boundary, respectively.

warning

DynamicStressDivergenceTensors uses the undisplaced mesh by default but kernels such as InertialForce and Gravity, and boundary conditions such as Pressure use the displaced mesh by default. All calculations should be performed either using the undisplaced mesh (recommended for small strain problems) or the displaced mesh (recommended for finite strain problems). Therefore, use_displaced_mesh parameter should be appropriately set for all the kernels and boundary conditions.

Static Initialization

To initialize the system under a constant initial loading such as gravity, an initial static analysis can be conducted by turning off all the dynamics related Kernels and AuxKernels such as InertialForce, NewmarkVelAux and NewmarkAccelAux for the first time step. To turn off stiffness proportional Rayleigh damping for the first time step static_initialization flag can be set to true in DynamicTensorMechanics or DynamicStressDivergenceTensors. An example of static initialization can be found in this following test:

# One 3D element under ramped displacement loading.
#
# loading in z direction:
# time : 0.0 0.1  0.2  0.3
# disp : 0.0 0.0 -0.01 -0.01

# Gravity is applied in y direction. To equilibrate the system
# under gravity, a static analysis is run in the first time step
# by turning off the inertial terms. (see controls block and
# DynamicTensorMechanics block).

# Result: The displacement at the top node in the z direction should match
# the prescribed displacement. Also, the z acceleration should
# be two triangular pulses, one peaking at 0.1 and another peaking at
# 0.2.

# The y displacement would be offset by the gravity displacement.
# Also the y acceleration and velocity should be zero until the loading in
# the z direction starts (i.e, until 0.1s)

# Note: The time step used in the displacement data file should match
# the simulation time step (dt and dtmin in the Executioner block).

[Mesh]
  type = GeneratedMesh
  dim = 3 # Dimension of the mesh
  nx = 1 # Number of elements in the x direction
  ny = 1 # Number of elements in the y direction
  nz = 1 # Number of elements in the z direction
  xmin = 0.0
  xmax = 1
  ymin = 0.0
  ymax = 1
  zmin = 0.0
  zmax = 1
  allow_renumbering = false # So NodalVariableValue can index by id
[]

[Variables] # variables that are solved
  [./disp_x]
  [../]
  [./disp_y]
  [../]
  [./disp_z]
  [../]
[]

[AuxVariables] # variables that are calculated for output
  [./accel_x]
  [../]
  [./vel_x]
  [../]
  [./accel_y]
  [../]
  [./vel_y]
  [../]
  [./accel_z]
  [../]
  [./vel_z]
  [../]
  [./stress_xx]
    order = CONSTANT
    family = MONOMIAL
  [../]
  [./strain_xx]
    order = CONSTANT
    family = MONOMIAL
  [../]
  [./stress_yy]
    order = CONSTANT
    family = MONOMIAL
  [../]
  [./strain_yy]
    order = CONSTANT
    family = MONOMIAL
  [../]
  [./stress_zz]
    order = CONSTANT
    family = MONOMIAL
  [../]
  [./strain_zz]
    order = CONSTANT
    family = MONOMIAL
  [../]
[]

[Kernels]
  [./DynamicTensorMechanics] # zeta*K*vel + K * disp
    displacements = 'disp_x disp_y disp_z'
    zeta = 0.000025
    static_initialization = true #turns off rayliegh damping for the first time step to stabilize system under gravity
  [../]
  [./inertia_x] # M*accel + eta*M*vel
    type = InertialForce
    variable = disp_x
    velocity = vel_x
    acceleration = accel_x
    beta = 0.25 # Newmark time integration
    gamma = 0.5 # Newmark time integration
    eta = 19.63
  [../]
  [./inertia_y]
    type = InertialForce
    variable = disp_y
    velocity = vel_y
    acceleration = accel_y
    beta = 0.25
    gamma = 0.5
    eta = 19.63
  [../]
  [./inertia_z]
    type = InertialForce
    variable = disp_z
    velocity = vel_z
    acceleration = accel_z
    beta = 0.25
    gamma = 0.5
    eta = 19.63
  [../]
  [./gravity]
    type = Gravity
    variable = disp_y
    value = -9.81
  [../]
[]

[AuxKernels]
  [./accel_x] # Calculates and stores acceleration at the end of time step
    type = NewmarkAccelAux
    variable = accel_x
    displacement = disp_x
    velocity = vel_x
    beta = 0.25
    execute_on = timestep_end
  [../]
  [./vel_x] # Calculates and stores velocity at the end of the time step
    type = NewmarkVelAux
    variable = vel_x
    acceleration = accel_x
    gamma = 0.5
    execute_on = timestep_end
  [../]
  [./accel_y]
    type = NewmarkAccelAux
    variable = accel_y
    displacement = disp_y
    velocity = vel_y
    beta = 0.25
    execute_on = timestep_end
  [../]
  [./vel_y]
    type = NewmarkVelAux
    variable = vel_y
    acceleration = accel_y
    gamma = 0.5
    execute_on = timestep_end
  [../]
  [./accel_z]
    type = NewmarkAccelAux
    variable = accel_z
    displacement = disp_z
    velocity = vel_z
    beta = 0.25
    execute_on = timestep_end
  [../]
  [./vel_z]
    type = NewmarkVelAux
    variable = vel_z
    acceleration = accel_z
    gamma = 0.5
    execute_on = timestep_end
  [../]
  [./stress_xx]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_xx
    index_i = 0
    index_j = 0
  [../]
  [./strain_xx]
    type = RankTwoAux
    rank_two_tensor = total_strain
    variable = strain_xx
    index_i = 0
    index_j = 0
  [../]
  [./stress_yy]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_yy
    index_i = 1
    index_j = 1
  [../]
  [./strain_yy]
    type = RankTwoAux
    rank_two_tensor = total_strain
    variable = strain_yy
    index_i = 1
    index_j = 1
  [../]
  [./stress_zz]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_zz
    index_i = 2
    index_j = 2
  [../]
  [./strain_zz]
    type = RankTwoAux
    rank_two_tensor = total_strain
    variable = strain_zz
    index_i = 2
    index_j = 2
  [../]
[]

[Functions]
  [./displacement_front]
    type = PiecewiseLinear
    data_file = 'displacement.csv'
    format = columns
  [../]
[]

[BCs]
  [./prescribed_displacement]
    type = PresetDisplacement
    variable = disp_z
    velocity = vel_z
    acceleration = accel_z
    beta = 0.25
    boundary = front
    function = displacement_front
  [../]
  [./anchor_x]
    type = PresetBC
    variable = disp_x
    boundary = left
    value = 0.0
  [../]
  [./anchor_y]
    type = PresetBC
    variable = disp_y
    boundary = bottom
    value = 0.0
  [../]
  [./anchor_z]
    type = PresetBC
    variable = disp_z
    boundary = back
    value = 0.0
  [../]
[]

[Materials]
  [./elasticity_tensor]
    youngs_modulus = 325e6 #Pa
    poissons_ratio = 0.3
    type = ComputeIsotropicElasticityTensor
    block = 0
  [../]
  [./strain]
    #Computes the strain, assuming small strains
    type = ComputeSmallStrain
    block = 0
    displacements = 'disp_x disp_y disp_z'
  [../]
  [./stress]
    #Computes the stress, using linear elasticity
    type = ComputeLinearElasticStress
    block = 0
  [../]
  [./density]
    type = GenericConstantMaterial
    block = 0
    prop_names = density
    prop_values = 2000 #kg/m3
  [../]
[]

[Controls] # turns off inertial terms for the first time step
  [./period0]
    type = TimePeriod
    disable_objects = '*/vel_x */vel_y */vel_z */accel_x */accel_y */accel_z */inertia_x */inertia_y */inertia_z'
    start_time = 0.0
    end_time = 0.1 # dt used in the simulation
  [../]
[../]

[Executioner]
  type = Transient
  start_time = 0
  end_time = 3.0
  l_tol = 1e-6
  nl_rel_tol = 1e-6
  nl_abs_tol = 1e-6
  dt = 0.1
  timestep_tolerance = 1e-6
[]

[Postprocessors] # These quantites are printed to a csv file at every time step
  [./_dt]
    type = TimestepSize
  [../]
  [./accel_6x]
    type = NodalVariableValue
    nodeid = 6
    variable = accel_x
  [../]
  [./accel_6y]
    type = NodalVariableValue
    nodeid = 6
    variable = accel_y
  [../]
  [./accel_6z]
    type = NodalVariableValue
    nodeid = 6
    variable = accel_z
  [../]
  [./vel_6x]
    type = NodalVariableValue
    nodeid = 6
    variable = vel_x
  [../]
  [./vel_6y]
    type = NodalVariableValue
    nodeid = 6
    variable = vel_y
  [../]
  [./vel_6z]
    type = NodalVariableValue
    nodeid = 6
    variable = vel_z
  [../]
  [./disp_6x]
    type = NodalVariableValue
    nodeid = 6
    variable = disp_x
  [../]
  [./disp_6y]
    type = NodalVariableValue
    nodeid = 6
    variable = disp_y
  [../]
  [./disp_6z]
    type = NodalVariableValue
    nodeid = 6
    variable = disp_z
  [../]
[]

[Outputs]
  exodus = true
  csv = true
  perf_graph = true
[]
(modules/tensor_mechanics/test/tests/dynamics/prescribed_displacement/3D_QStatic_1_Ramped_Displacement_with_gravity.i)

References

  1. T. J. R Hughes. The finite element method:Linear static and dynamic finite element analysis. Dover Publications, Mineola, NY, 2000.[BibTeX]
  2. N. M. Newmark. A method of computation for structural dynamics. Journal of Engineering Mechanics, 85(EM3):67–94, 1959.[BibTeX]