Contact Verification
Overview
Finite element contact addresses the interaction of two surfaces that apply loads to one another.
Hertz Contact of Cylinder and Rigid Surface
The problem is an infinite cylinder in contact with a rigid plane. The problem is taken from Wang and Zhu (2013). See also Johnson (1985).
The analytic expressions for this problem rely on , the radius of a so-called equivalent cylinder.
where and are the radii of two cylinders in contact that have parallel axes. In our case, = 3, and is infinity. This gives = 3.
We also require : where and are Young's modulus and Poisson's ratio with subscripts representing each of the two bodies. In our case, = 1E6, = 0.3, = infinity, and = 0. This gives = 9.1E-7.
is the line load per unit length. We take this to be a pressure applied to the bottom half of the cylinder, 2E3, times . = 1.2E4.
The peak load, which occurs at the centerline of the cylinder, is with
This gives = 0.204 and = 37405. Bison computes as ~3.80E4, giving an error of 1.52%.
Figure 1: Contact traction for Hertz cylinder contact problem.
Input Syntax
#
# Hertz Contact of Cylinder and Rigid Surface
# See https://doi.org/10.1007/978-0-387-92897-5_491
#
# 1/E* = (1-v1^2)/E1 + (1-v2^2)/E2
# v1 = 0.3
# E1 = 1e6
# v2 = 0
# E2 = infinity
# 1/E* = (1-0.09)/1e6 = 9.1e-7
# EstarInv = 9.1e-7
# 1/Re = (R1+R2)/R1/R2
# R1 = 3
# R2 = infinity
# 1/Re = 1/3
# Re = 3.0
# P = pressure at 0.1 seconds * 2*R1
# P = 2e3 * 6
# P = 1.2e4
#
# a is half width of contacting area
# a = sqrt(4 * P * Re / pi * EstarInv)
# a = 0.204
#
# Pmax = 2 * P / pi / a
# Pmax = 37405
#
[GlobalParams<<<{"href": "../../syntax/GlobalParams/index.html"}>>>]
displacements = 'disp_x disp_y'
[]
[Mesh<<<{"href": "../../syntax/Mesh/index.html"}>>>]
[input_file]
type = FileMeshGenerator<<<{"description": "Read a mesh from a file.", "href": "../../source/meshgenerators/FileMeshGenerator.html"}>>>
file<<<{"description": "The filename to read."}>>> = hertz_cyl_coarser.e
[]
[secondary]
type = LowerDBlockFromSidesetGenerator<<<{"description": "Adds lower dimensional elements on the specified sidesets.", "href": "../../source/meshgenerators/LowerDBlockFromSidesetGenerator.html"}>>>
new_block_id<<<{"description": "The lower dimensional block id to create"}>>> = 10001
new_block_name<<<{"description": "The lower dimensional block name to create (optional)"}>>> = 'secondary_lower'
sidesets<<<{"description": "The sidesets from which to create the new block"}>>> = '3'
input<<<{"description": "The mesh we want to modify"}>>> = input_file
[]
[primary]
type = LowerDBlockFromSidesetGenerator<<<{"description": "Adds lower dimensional elements on the specified sidesets.", "href": "../../source/meshgenerators/LowerDBlockFromSidesetGenerator.html"}>>>
new_block_id<<<{"description": "The lower dimensional block id to create"}>>> = 10000
sidesets<<<{"description": "The sidesets from which to create the new block"}>>> = '2'
new_block_name<<<{"description": "The lower dimensional block name to create (optional)"}>>> = 'primary_lower'
input<<<{"description": "The mesh we want to modify"}>>> = secondary
[]
[]
[Problem<<<{"href": "../../syntax/Problem/index.html"}>>>]
type = ReferenceResidualProblem
extra_tag_vectors = 'ref'
reference_vector = 'ref'
[]
[Variables<<<{"href": "../../syntax/Variables/index.html"}>>>]
[disp_x]
[]
[disp_y]
initial_condition<<<{"description": "Specifies a constant initial condition for this variable"}>>> = -0.01
[]
[frictionless_normal_lm]
order<<<{"description": "Specifies the order of the FE shape function to use for this variable (additional orders not listed are allowed)"}>>> = FIRST
family<<<{"description": "Specifies the family of FE shape functions to use for this variable"}>>> = LAGRANGE
block = 'secondary_lower'
use_dual = true
[]
[]
[AuxVariables<<<{"href": "../../syntax/AuxVariables/index.html"}>>>]
[saved_x]
[]
[saved_y]
[]
[]
[Functions<<<{"href": "../../syntax/Functions/index.html"}>>>]
[pressure_function]
type = PiecewiseLinear<<<{"description": "Linearly interpolates between pairs of x-y data", "href": "../../source/functions/PiecewiseLinear.html"}>>>
x<<<{"description": "The abscissa values"}>>> = '0. 1. 3.5'
y<<<{"description": "The ordinate values"}>>> = '0. 2e4 2e4'
[]
[analytic]
type = ParsedFunction<<<{"description": "Function created by parsing a string", "href": "../../source/functions/MooseParsedFunction.html"}>>>
symbol_names<<<{"description": "Symbols (excluding t,x,y,z) that are bound to the values provided by the corresponding items in the vals vector."}>>> = 'EstarInv Re width P'
symbol_values<<<{"description": "Constant numeric values, postprocessor names, function names, and scalar variables corresponding to the symbols in symbol_names."}>>> = '9.1e-7 3.0 6 pressure_function'
expression<<<{"description": "The user defined function."}>>> = '2 * P*width / pi / sqrt(4 * P*width * Re / pi * EstarInv)'
[]
[]
[Physics<<<{"href": "../../syntax/Physics/index.html"}>>>/SolidMechanics<<<{"href": "../../syntax/Physics/SolidMechanics/index.html"}>>>/QuasiStatic<<<{"href": "../../syntax/Physics/SolidMechanics/QuasiStatic/index.html"}>>>]
[fred]
block<<<{"description": "The list of ids of the blocks (subdomain) that the stress divergence kernels will be applied to"}>>> = '1 2 3 4 5 6 7'
strain<<<{"description": "Strain formulation"}>>> = finite
save_in<<<{"description": "The displacement residuals"}>>> = 'saved_x saved_y'
extra_vector_tags<<<{"description": "The tag names for extra vectors that residual data should be saved into"}>>> = 'ref'
generate_output<<<{"description": "Add scalar quantity output for stress and/or strain"}>>> = 'stress_xx stress_yy stress_xy'
[]
[]
[Postprocessors<<<{"href": "../../syntax/Postprocessors/index.html"}>>>]
[traction_applied]
type = NodalSum<<<{"description": "Computes the sum of all of the nodal values of the specified variable. Note: This object sets the default \"unique_node_execute\" flag to true to avoid double counting nodes between shared blocks.", "href": "../../source/postprocessors/NodalSum.html"}>>>
variable<<<{"description": "The name of the variable that this postprocessor operates on"}>>> = saved_y
boundary<<<{"description": "The list of boundaries (ids or names) from the mesh where this object applies"}>>> = 4
[]
[_dt]
type = TimestepSize<<<{"description": "Reports the timestep size", "href": "../../source/postprocessors/TimestepSize.html"}>>>
[]
[bison_peak_traction]
type = NodalExtremeValue<<<{"description": "Finds either the min or max elemental value of a variable over the domain.", "href": "../../source/postprocessors/NodalExtremeValue.html"}>>>
boundary<<<{"description": "The list of boundaries (ids or names) from the mesh where this object applies"}>>> = 3
variable<<<{"description": "The name of the variable that this postprocessor operates on"}>>> = frictionless_normal_lm
[]
[analytical_peak_traction]
type = FunctionValuePostprocessor<<<{"description": "Computes the value of a supplied function at a single point (scalable)", "href": "../../source/postprocessors/FunctionValuePostprocessor.html"}>>>
function<<<{"description": "The function which supplies the postprocessor value."}>>> = analytic
[]
[error]
type = ParsedPostprocessor<<<{"description": "Computes a parsed expression with post-processors", "href": "../../source/postprocessors/ParsedPostprocessor.html"}>>>
pp_names<<<{"description": "Post-processors arguments"}>>> = 'bison_peak_traction analytical_peak_traction'
expression<<<{"description": "function expression"}>>> = '(bison_peak_traction-analytical_peak_traction)/analytical_peak_traction*100'
[]
[]
[BCs<<<{"href": "../../syntax/NuclearMaterials/BCs/index.html"}>>>]
[base_x]
type = DirichletBC<<<{"description": "Imposes the essential boundary condition $u=g$, where $g$ is a constant, controllable value.", "href": "../../source/bcs/DirichletBC.html"}>>>
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = disp_x
boundary<<<{"description": "The list of boundary IDs from the mesh where this object applies"}>>> = '1 2'
value<<<{"description": "Value of the BC"}>>> = 0.0
[]
[base_y]
type = DirichletBC<<<{"description": "Imposes the essential boundary condition $u=g$, where $g$ is a constant, controllable value.", "href": "../../source/bcs/DirichletBC.html"}>>>
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = disp_y
boundary<<<{"description": "The list of boundary IDs from the mesh where this object applies"}>>> = '1 2'
value<<<{"description": "Value of the BC"}>>> = 0.0
[]
[Pressure<<<{"href": "../../syntax/BCs/Pressure/index.html"}>>>]
[pressure]
boundary<<<{"description": "The list of boundaries (ids or names) from the mesh where this object applies"}>>> = 4
function<<<{"description": "The function that describes the pressure"}>>> = pressure_function
use_displaced_mesh<<<{"description": "Whether or not this object should use the displaced mesh for computation. Note that in the case this is true but no displacements are provided in the Mesh block the undisplaced mesh will still be used. For small strain formulations pressure should be applied to the undisplaced mesh to obtain agreement with analytical benchmark solutions."}>>> = false
[]
[]
[]
[Materials<<<{"href": "../../syntax/Materials/index.html"}>>>]
[elas_tens]
type = ComputeIsotropicElasticityTensor<<<{"description": "Compute a constant isotropic elasticity tensor.", "href": "../../source/materials/ComputeIsotropicElasticityTensor.html"}>>>
block<<<{"description": "The list of blocks (ids or names) that this object will be applied"}>>> = '1 2 3 4 5 6 7'
youngs_modulus<<<{"description": "Young's modulus of the material."}>>> = 1e6
poissons_ratio<<<{"description": "Poisson's ratio for the material."}>>> = 0.3
[]
[stress]
type = ComputeFiniteStrainElasticStress<<<{"description": "Compute stress using elasticity for finite strains", "href": "../../source/materials/ComputeFiniteStrainElasticStress.html"}>>>
block<<<{"description": "The list of blocks (ids or names) that this object will be applied"}>>> = '1 2 3 4 5 6 7'
[]
[]
[Executioner<<<{"href": "../../syntax/Executioner/index.html"}>>>]
type = Transient
solve_type = 'PJFNK'
petsc_options = '-snes_ksp_ew'
petsc_options_iname = '-pc_type -pc_factor_mat_solver_type -pc_factor_shift_type -pc_factor_shift_amount -mat_mffd_err'
petsc_options_value = 'lu superlu_dist NONZERO 1e-15 1e-5'
line_search = 'none'
nl_abs_tol = 1e-7
start_time = 0.0
end_time = 0.1
l_tol = 1e-4
dt = 0.1
dtmin = 0.1
[Predictor<<<{"href": "../../syntax/Executioner/Predictor/index.html"}>>>]
type = SimplePredictor
scale = 1.0
[]
[]
[Preconditioning<<<{"href": "../../syntax/Preconditioning/index.html"}>>>]
[SMP]
type = SMP<<<{"description": "Single matrix preconditioner (SMP) builds a preconditioner using user defined off-diagonal parts of the Jacobian.", "href": "../../source/preconditioners/SingleMatrixPreconditioner.html"}>>>
full<<<{"description": "Set to true if you want the full set of couplings between variables simply for convenience so you don't have to set every off_diag_row and off_diag_column combination."}>>> = true
[]
[]
[VectorPostprocessors<<<{"href": "../../syntax/VectorPostprocessors/index.html"}>>>]
[cont_press]
type = NodalValueSampler<<<{"description": "Samples values of nodal variable(s).", "href": "../../source/vectorpostprocessors/NodalValueSampler.html"}>>>
variable<<<{"description": "The names of the variables that this VectorPostprocessor operates on"}>>> = frictionless_normal_lm
boundary<<<{"description": "The list of boundaries (ids or names) from the mesh where this object applies"}>>> = '3'
sort_by<<<{"description": "What to sort the samples by"}>>> = id
[]
[]
[Outputs<<<{"href": "../../syntax/Outputs/index.html"}>>>]
print_linear_residuals<<<{"description": "Enable printing of linear residuals to the screen (Console)"}>>> = true
exodus<<<{"description": "Output the results using the default settings for Exodus output."}>>> = true
csv<<<{"description": "Output the scalar variable and postprocessors to a *.csv file using the default CSV output."}>>> = true
[console]
type = Console<<<{"description": "Object for screen output.", "href": "../../source/outputs/Console.html"}>>>
max_rows<<<{"description": "The maximum number of postprocessor/scalar values displayed on screen during a timestep (set to 0 for unlimited)"}>>> = 5
[]
[csv1]
type = CSV<<<{"description": "Output for postprocessors, vector postprocessors, and scalar variables using comma seperated values (CSV).", "href": "../../source/outputs/CSV.html"}>>>
show<<<{"description": "A list of the variables and postprocessors that should be output to the Exodus file (may include Variables, ScalarVariables, and Postprocessor names)."}>>> = 'cont_press'
file_base<<<{"description": "The desired solution output name without an extension. If not provided, MOOSE sets it with Outputs/file_base when available. Otherwise, MOOSE uses input file name and this object name for a master input or uses master file_base, the subapp name and this object name for a subapp input to set it."}>>> = cylinder_frictionless
[]
[]
[UserObjects<<<{"href": "../../syntax/UserObjects/index.html"}>>>]
[weighted_vel_uo]
type = LMWeightedGapUserObject<<<{"description": "Provides the mortar normal Lagrange multiplier for constraint enforcement.", "href": "../../source/userobjects/LMWeightedGapUserObject.html"}>>>
primary_boundary<<<{"description": "The name of the primary boundary sideset."}>>> = 2
secondary_boundary<<<{"description": "The name of the secondary boundary sideset."}>>> = 3
primary_subdomain<<<{"description": "The name of the primary subdomain."}>>> = 10000
secondary_subdomain<<<{"description": "The name of the secondary subdomain."}>>> = 10001
disp_x<<<{"description": "The x displacement variable"}>>> = disp_x
disp_y<<<{"description": "The y displacement variable"}>>> = disp_y
lm_variable<<<{"description": "The Lagrange multiplier variable representing the contact pressure."}>>> = frictionless_normal_lm
[]
[]
[Constraints<<<{"href": "../../syntax/Constraints/index.html"}>>>]
[weighted_gap_lm]
type = ComputeWeightedGapLMMechanicalContact<<<{"description": "Computes the weighted gap that will later be used to enforce the zero-penetration mechanical contact conditions", "href": "../../source/constraints/ComputeWeightedGapLMMechanicalContact.html"}>>>
primary_boundary<<<{"description": "The name of the primary boundary sideset."}>>> = 2
secondary_boundary<<<{"description": "The name of the secondary boundary sideset."}>>> = 3
primary_subdomain<<<{"description": "The name of the primary subdomain."}>>> = 10000
secondary_subdomain<<<{"description": "The name of the secondary subdomain."}>>> = 10001
variable<<<{"description": "The name of the lagrange multiplier variable that this constraint is applied to. This parameter may not be supplied in the case of using penalty methods for example"}>>> = frictionless_normal_lm
disp_x<<<{"description": "The x displacement variable"}>>> = disp_x
disp_y<<<{"description": "The y displacement variable"}>>> = disp_y
use_displaced_mesh<<<{"description": "Whether or not this object should use the displaced mesh for computation. Note that in the case this is true but no displacements are provided in the Mesh block the undisplaced mesh will still be used."}>>> = true
c<<<{"description": "Parameter for balancing the size of the gap and contact pressure"}>>> = 1.0e6
weighted_gap_uo<<<{"description": "The weighted gap user object"}>>> = weighted_vel_uo
[]
[x]
type = NormalMortarMechanicalContact<<<{"description": "This class is used to apply normal contact forces using lagrange multipliers", "href": "../../source/constraints/NormalMortarMechanicalContact.html"}>>>
primary_boundary<<<{"description": "The name of the primary boundary sideset."}>>> = '2'
secondary_boundary<<<{"description": "The name of the secondary boundary sideset."}>>> = '3'
primary_subdomain<<<{"description": "The name of the primary subdomain."}>>> = '10000'
secondary_subdomain<<<{"description": "The name of the secondary subdomain."}>>> = '10001'
variable<<<{"description": "The name of the lagrange multiplier variable that this constraint is applied to. This parameter may not be supplied in the case of using penalty methods for example"}>>> = frictionless_normal_lm
secondary_variable<<<{"description": "Primal variable on secondary surface."}>>> = disp_x
component<<<{"description": "The force component constraint that this object is supplying"}>>> = x
use_displaced_mesh<<<{"description": "Whether or not this object should use the displaced mesh for computation. Note that in the case this is true but no displacements are provided in the Mesh block the undisplaced mesh will still be used."}>>> = true
compute_lm_residuals<<<{"description": "Whether to compute Lagrange Multiplier residuals"}>>> = false
weighted_gap_uo<<<{"description": "The weighted gap user object."}>>> = weighted_vel_uo
[]
[y]
type = NormalMortarMechanicalContact<<<{"description": "This class is used to apply normal contact forces using lagrange multipliers", "href": "../../source/constraints/NormalMortarMechanicalContact.html"}>>>
primary_boundary<<<{"description": "The name of the primary boundary sideset."}>>> = '2'
secondary_boundary<<<{"description": "The name of the secondary boundary sideset."}>>> = '3'
primary_subdomain<<<{"description": "The name of the primary subdomain."}>>> = '10000'
secondary_subdomain<<<{"description": "The name of the secondary subdomain."}>>> = '10001'
variable<<<{"description": "The name of the lagrange multiplier variable that this constraint is applied to. This parameter may not be supplied in the case of using penalty methods for example"}>>> = frictionless_normal_lm
secondary_variable<<<{"description": "Primal variable on secondary surface."}>>> = disp_y
component<<<{"description": "The force component constraint that this object is supplying"}>>> = y
use_displaced_mesh<<<{"description": "Whether or not this object should use the displaced mesh for computation. Note that in the case this is true but no displacements are provided in the Mesh block the undisplaced mesh will still be used."}>>> = true
compute_lm_residuals<<<{"description": "Whether to compute Lagrange Multiplier residuals"}>>> = false
weighted_gap_uo<<<{"description": "The weighted gap user object."}>>> = weighted_vel_uo
[]
[](assessment/verification/Contact/hertz/cylinder_frictionless_pressure.i)References
- K. L. Johnson.
Contact Mechanics.
Cambridge University Press, 1985.
doi:10.1017/CBO9781139171731.[BibTeX]
- Q. Jane Wang and Dong Zhu.
Hertz Theory: Contact of Cylindrical Surfaces, pages 1639–1647.
Springer US, Boston, MA, 2013.
doi:10.1007/978-0-387-92897-5_491.[BibTeX]