- disp_xThe x displacement variable
C++ Type:std::vector<VariableName>
Unit:(no unit assumed)
Controllable:No
Description:The x displacement variable
 - disp_yThe y displacement variable
C++ Type:std::vector<VariableName>
Unit:(no unit assumed)
Controllable:No
Description:The y displacement variable
 - lm_variable_normalThe Lagrange multiplier variable representing the contact pressure.
C++ Type:std::vector<VariableName>
Unit:(no unit assumed)
Controllable:No
Description:The Lagrange multiplier variable representing the contact pressure.
 - lm_variable_tangential_oneThe Lagrange multiplier variable representing the tangential contact pressure along the first tangential direction (the only one in two dimensions).
C++ Type:std::vector<VariableName>
Unit:(no unit assumed)
Controllable:No
Description:The Lagrange multiplier variable representing the tangential contact pressure along the first tangential direction (the only one in two dimensions).
 - primary_boundaryThe name of the primary boundary sideset.
C++ Type:BoundaryName
Controllable:No
Description:The name of the primary boundary sideset.
 - primary_subdomainThe name of the primary subdomain.
C++ Type:SubdomainName
Controllable:No
Description:The name of the primary subdomain.
 - secondary_boundaryThe name of the secondary boundary sideset.
C++ Type:BoundaryName
Controllable:No
Description:The name of the secondary boundary sideset.
 - secondary_subdomainThe name of the secondary subdomain.
C++ Type:SubdomainName
Controllable:No
Description:The name of the secondary subdomain.
 - secondary_variablePrimal variable on secondary surface.
C++ Type:VariableName
Unit:(no unit assumed)
Controllable:No
Description:Primal variable on secondary surface.
 
LMWeightedVelocitiesUserObject
Description
The LMWeightedVelocitiesUserObject object provides the Lagrange multiplier and interpolation function for the enforcement of mortar mechanical constraints. In essence, the Lagrange multiplier is provided to TangentialMortarMechanicalContact to enforce friction via a Coulomb model. This object is set up automatically when using the contact action ContactAction
Input Parameters
- aux_lmAuxiliary Lagrange multiplier variable that is utilized together with the Petrov-Galerkin approach.
C++ Type:std::vector<VariableName>
Unit:(no unit assumed)
Controllable:No
Description:Auxiliary Lagrange multiplier variable that is utilized together with the Petrov-Galerkin approach.
 - correct_edge_droppingFalseWhether to enable correct edge dropping treatment for mortar constraints. When disabled any Lagrange Multiplier degree of freedom on a secondary element without full primary contributions will be set (strongly) to 0.
Default:False
C++ Type:bool
Controllable:No
Description:Whether to enable correct edge dropping treatment for mortar constraints. When disabled any Lagrange Multiplier degree of freedom on a secondary element without full primary contributions will be set (strongly) to 0.
 - debug_meshFalseWhether this constraint is going to enable mortar segment mesh debug information. An exodusfile will be generated if the user sets this flag to true
Default:False
C++ Type:bool
Controllable:No
Description:Whether this constraint is going to enable mortar segment mesh debug information. An exodusfile will be generated if the user sets this flag to true
 - disp_zThe z displacement variable
C++ Type:std::vector<VariableName>
Unit:(no unit assumed)
Controllable:No
Description:The z displacement variable
 - ghost_higher_d_neighborsFalseWhether we should ghost higher-dimensional neighbors. This is necessary when we are doing second order mortar with finite volume primal variables, because in order for the method to be second order we must use cell gradients, which couples in the neighbor cells.
Default:False
C++ Type:bool
Controllable:No
Description:Whether we should ghost higher-dimensional neighbors. This is necessary when we are doing second order mortar with finite volume primal variables, because in order for the method to be second order we must use cell gradients, which couples in the neighbor cells.
 - ghost_point_neighborsFalseWhether we should ghost point neighbors of secondary face elements, and consequently also their mortar interface couples.
Default:False
C++ Type:bool
Controllable:No
Description:Whether we should ghost point neighbors of secondary face elements, and consequently also their mortar interface couples.
 - interpolate_normalsFalseWhether to interpolate the nodal normals (e.g. classic idea of evaluating field at quadrature points). If this is set to false, then non-interpolated nodal normals will be used, and then the _normals member should be indexed with _i instead of _qp
Default:False
C++ Type:bool
Controllable:No
Description:Whether to interpolate the nodal normals (e.g. classic idea of evaluating field at quadrature points). If this is set to false, then non-interpolated nodal normals will be used, and then the _normals member should be indexed with _i instead of _qp
 - lm_variable_tangential_twoThe Lagrange multiplier variable representing the tangential contact pressure along the second tangential direction.
C++ Type:std::vector<VariableName>
Unit:(no unit assumed)
Controllable:No
Description:The Lagrange multiplier variable representing the tangential contact pressure along the second tangential direction.
 - minimum_projection_angle40Parameter to control which angle (in degrees) is admissible for the creation of mortar segments. If set to a value close to zero, very oblique projections are allowed, which can result in mortar segments solving physics not meaningfully, and overprojection of primary nodes onto the mortar segment mesh in extreme cases. This parameter is mostly intended for mortar mesh debugging purposes in two dimensions.
Default:40
C++ Type:double
Unit:(no unit assumed)
Controllable:No
Description:Parameter to control which angle (in degrees) is admissible for the creation of mortar segments. If set to a value close to zero, very oblique projections are allowed, which can result in mortar segments solving physics not meaningfully, and overprojection of primary nodes onto the mortar segment mesh in extreme cases. This parameter is mostly intended for mortar mesh debugging purposes in two dimensions.
 - periodicFalseWhether this constraint is going to be used to enforce a periodic condition. This has the effect of changing the normals vector for projection from outward to inward facing
Default:False
C++ Type:bool
Controllable:No
Description:Whether this constraint is going to be used to enforce a periodic condition. This has the effect of changing the normals vector for projection from outward to inward facing
 - primary_variablePrimal variable on primary surface. If this parameter is not provided then the primary variable will be initialized to the secondary variable
C++ Type:VariableName
Unit:(no unit assumed)
Controllable:No
Description:Primal variable on primary surface. If this parameter is not provided then the primary variable will be initialized to the secondary variable
 - use_petrov_galerkinFalseWhether to use the Petrov-Galerkin approach.
Default:False
C++ Type:bool
Controllable:No
Description:Whether to use the Petrov-Galerkin approach.
 
Optional Parameters
- allow_duplicate_execution_on_initialFalseIn the case where this UserObject is depended upon by an initial condition, allow it to be executed twice during the initial setup (once before the IC and again after mesh adaptivity (if applicable).
Default:False
C++ Type:bool
Controllable:No
Description:In the case where this UserObject is depended upon by an initial condition, allow it to be executed twice during the initial setup (once before the IC and again after mesh adaptivity (if applicable).
 - execution_order_group0Execution order groups are executed in increasing order (e.g., the lowest number is executed first). Note that negative group numbers may be used to execute groups before the default (0) group. Please refer to the user object documentation for ordering of user object execution within a group.
Default:0
C++ Type:int
Controllable:No
Description:Execution order groups are executed in increasing order (e.g., the lowest number is executed first). Note that negative group numbers may be used to execute groups before the default (0) group. Please refer to the user object documentation for ordering of user object execution within a group.
 - force_postauxFalseForces the UserObject to be executed in POSTAUX
Default:False
C++ Type:bool
Controllable:No
Description:Forces the UserObject to be executed in POSTAUX
 - force_preauxFalseForces the UserObject to be executed in PREAUX
Default:False
C++ Type:bool
Controllable:No
Description:Forces the UserObject to be executed in PREAUX
 - force_preicFalseForces the UserObject to be executed in PREIC during initial setup
Default:False
C++ Type:bool
Controllable:No
Description:Forces the UserObject to be executed in PREIC during initial setup
 
Execution Scheduling Parameters
- control_tagsAdds user-defined labels for accessing object parameters via control logic.
C++ Type:std::vector<std::string>
Controllable:No
Description:Adds user-defined labels for accessing object parameters via control logic.
 - enableTrueSet the enabled status of the MooseObject.
Default:True
C++ Type:bool
Controllable:Yes
Description:Set the enabled status of the MooseObject.
 - use_displaced_meshTrueWhether 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.
Default:True
C++ Type:bool
Controllable:No
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.
 
Advanced Parameters
- prop_getter_suffixAn optional suffix parameter that can be appended to any attempt to retrieve/get material properties. The suffix will be prepended with a '_' character.
C++ Type:MaterialPropertyName
Unit:(no unit assumed)
Controllable:No
Description:An optional suffix parameter that can be appended to any attempt to retrieve/get material properties. The suffix will be prepended with a '_' character.
 - use_interpolated_stateFalseFor the old and older state use projected material properties interpolated at the quadrature points. To set up projection use the ProjectedStatefulMaterialStorageAction.
Default:False
C++ Type:bool
Controllable:No
Description:For the old and older state use projected material properties interpolated at the quadrature points. To set up projection use the ProjectedStatefulMaterialStorageAction.
 
Material Property Retrieval Parameters
Input Files
- (modules/contact/test/tests/mortar_dynamics/frictional-mortar-3d.i)
 - (modules/contact/test/tests/3d-mortar-contact/half_sphere_nodal_geometry.i)
 - (modules/contact/test/tests/mortar_dynamics/frictional-mortar-3d-dynamics.i)
 - (modules/contact/test/tests/3d-mortar-contact/frictional-mortar-3d.i)
 - (modules/contact/test/tests/pdass_problems/ironing.i)
 - (modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-wear-vel.i)
 - (modules/contact/test/tests/3d-mortar-contact/frictional-mortar-3d-function.i)
 - (modules/contact/test/tests/bouncing-block-contact/frictional-nodal-min-normal-lm-mortar-pdass-tangential-lm-mortar-disp.i)
 - (modules/contact/test/tests/mortar_dynamics/frictional-mortar-3d-dynamics-light-function.i)
 - (modules/contact/test/tests/mortar_dynamics/block-dynamics-friction.i)
 - (modules/contact/test/tests/3d-mortar-contact/frictional-mortar-3d_pg.i)
 - (modules/contact/test/tests/bouncing-block-contact/variational-frictional.i)
 - (modules/contact/test/tests/mortar_dynamics/frictional-mortar-3d-dynamics-light.i)
 - (modules/contact/test/tests/pdass_problems/frictional_bouncing_block.i)
 - (modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-fretting-wear-test-projection_angle.i)
 - (modules/contact/test/tests/mortar_aux_kernels/frictional-mortar-3d-status.i)
 - (modules/contact/test/tests/mortar_dynamics/block-dynamics-friction-creep.i)
 - (modules/contact/test/tests/pdass_problems/cylinder_friction.i)
 - (modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-fretting-wear-test.i)
 
(modules/contact/test/tests/mortar_dynamics/frictional-mortar-3d.i)
starting_point = 0.25
offset = 0.00
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[AuxVariables]
  [mortar_tangent_x]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_y]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_z]
    family = LAGRANGE
    order = FIRST
  []
[]
[AuxKernels]
  [friction_x_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_x
   component = 0
   boundary = 'top_bottom'
  []
  [friction_y_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_y
   component = 1
   boundary = 'top_bottom'
  []
  [friction_z_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_z
   component = 2
   boundary = 'top_bottom'
  []
[]
[Mesh]
  [top_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 3
    ny = 3
    nz = 3
    xmin = -0.25
    xmax = 0.25
    ymin = -0.25
    ymax = 0.25
    zmin = -0.25
    zmax = 0.25
    elem_type = HEX8
  []
  [rotate_top_block]
    type = TransformGenerator
    input = top_block
    transform = ROTATE
    vector_value = '0 0 0'
  []
  [top_block_sidesets]
    type = RenameBoundaryGenerator
    input = rotate_top_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'top_bottom top_back top_right top_front top_left top_top'
  []
  [top_block_id]
    type = SubdomainIDGenerator
    input = top_block_sidesets
    subdomain_id = 1
  []
  [bottom_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 10
    ny = 10
    nz = 2
    xmin = -.5
    xmax = .5
    ymin = -.5
    ymax = .5
    zmin = -.3
    zmax = -.25
    elem_type = HEX8
  []
  [bottom_block_id]
    type = SubdomainIDGenerator
    input = bottom_block
    subdomain_id = 2
  []
  [bottom_block_change_boundary_id]
    type = RenameBoundaryGenerator
    input = bottom_block_id
    old_boundary = '0 1 2 3 4 5'
    new_boundary = '100 101 102 103 104 105'
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'top_block_id bottom_block_change_boundary_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'top_block bottom_block'
  []
  [bottom_right_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = block_rename
    new_boundary = bottom_right
    block = bottom_block
    normal = '1 0 0'
  []
  [bottom_left_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_right_sideset
    new_boundary = bottom_left
    block = bottom_block
    normal = '-1 0 0'
  []
  [bottom_top_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_left_sideset
    new_boundary = bottom_top
    block = bottom_block
    normal = '0 0 1'
  []
  [bottom_bottom_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_top_sideset
    new_boundary = bottom_bottom
    block = bottom_block
    normal = '0  0 -1'
  []
  [bottom_front_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_bottom_sideset
    new_boundary = bottom_front
    block = bottom_block
    normal = '0 1 0'
  []
  [bottom_back_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_front_sideset
    new_boundary = bottom_back
    block = bottom_block
    normal = '0 -1 0'
  []
  [secondary]
    input = bottom_back_sideset
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'top_bottom' # top_back top_left'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'bottom_top'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
  uniform_refine = 0
  allow_renumbering = false
[]
[Variables]
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_3d_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    add_variables = true
    strain = FINITE
    block = '1 2'
    use_automatic_differentiation = false
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_zz'
  []
[]
[Materials]
  [tensor]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1.0e4
    poissons_ratio = 0.0
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
  [tensor_1000]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e5
    poissons_ratio = 0.0
  []
  [stress_1000]
    type = ComputeFiniteStrainElasticStress
    block = '2'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable_normal = mortar_normal_lm
    lm_variable_tangential_one = mortar_tangential_lm
    lm_variable_tangential_two = mortar_tangential_3d_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [friction]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    mu = 0.4
    c = 1e4
    c_t = 1.0e4
    friction_lm = mortar_tangential_lm
    friction_lm_dir = mortar_tangential_3d_lm
    weighted_gap_uo = weighted_vel_uo
    weighted_velocities_uo = weighted_vel_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_x
    component = x
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_y
    component = y
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_z
    component = z
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [botz]
    type = DirichletBC
    variable = disp_z
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [topx]
    type = DirichletBC
    variable = disp_x
    boundary = 'top_top'
    value = 0.0
  []
  [topy]
    type = DirichletBC
    variable = disp_y
    boundary = 'top_top'
    value = 0.0
  []
  [topz]
    type = FunctionDirichletBC
    variable = disp_z
    boundary = 'top_top'
    function = '-${starting_point} * sin(2 * pi / 40 * t) + ${offset}'
  []
[]
[Executioner]
  type = Transient
  end_time = .025
  dt = .025
  dtmin = .001
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -snes_ksp_ew'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -mat_mffd_err'
  petsc_options_value = 'lu       NONZERO               1e-14                  1e-5'
  l_max_its = 15
  nl_max_its = 30
  nl_rel_tol = 1e-11
  nl_abs_tol = 1e-12
  line_search = 'basic'
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  csv = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'contact'
  [contact]
    type = ContactDOFSetSize
    variable = mortar_normal_lm
    subdomain = 'secondary_lower'
    execute_on = 'nonlinear timestep_end'
  []
[]
[VectorPostprocessors]
  [contact-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_normal_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [frictional-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [frictional-pressure-3d]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_3d_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [tangent_x]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_x
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [tangent_y]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_y
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
[]
(modules/contact/test/tests/3d-mortar-contact/half_sphere_nodal_geometry.i)
[Mesh]
  [generated_mesh]
    type = FileMeshGenerator
    file = half_sphere.e
  []
  [secondary]
    type = LowerDBlockFromSidesetGenerator
    new_block_id = 2002
    new_block_name = 'secondary_lower'
    sidesets = '202'
    input = generated_mesh
  []
  [primary]
    type = LowerDBlockFromSidesetGenerator
    new_block_id = 1002
    sidesets = '102'
    new_block_name = 'primary_lower'
    input = secondary
  []
  patch_size = 20
  patch_update_strategy = always
  uniform_refine = 0
[]
[Problem]
  kernel_coverage_check = false
[]
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
  order = FIRST
  family = LAGRANGE
[]
[Variables]
  [frictional_normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [frictional_tangential_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [frictional_tangential_dir_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[AuxVariables]
  [saved_x]
  []
  [saved_y]
  []
  [saved_z]
  []
  [tangent_x]
    family = LAGRANGE
    order = FIRST
  []
  [tangent_y]
    family = LAGRANGE
    order = FIRST
  []
  [tangent_z]
    family = LAGRANGE
    order = FIRST
  []
[]
[AuxKernels]
  [friction_x_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 102
   secondary_boundary = 202
   tangent_one = frictional_tangential_lm
   tangent_two = frictional_tangential_dir_lm
   variable = tangent_x
   component = 0
   boundary = 202
  []
  [friction_y_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 102
   secondary_boundary = 202
   tangent_one = frictional_tangential_lm
   tangent_two = frictional_tangential_dir_lm
   variable = tangent_y
   component = 1
   boundary = 202
  []
  [friction_z_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 102
   secondary_boundary = 202
   tangent_one = frictional_tangential_lm
   tangent_two = frictional_tangential_dir_lm
   variable = tangent_z
   component = 2
   boundary = 202
  []
[]
[Functions]
  [push_down]
    type = ParsedFunction
    expression = 'if(t < 1.5, -t, t-3.0)'
  []
  [force_z]
    type = ParsedFunction
    expression = 'if(t < 0.008, 0.0, (-t)*2.0e2 -t*t*100.0)' # 4.0e5
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    add_variables = true
    strain = FINITE
    block = '1 2'
    use_automatic_differentiation = true
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_zz'
    save_in = 'saved_x saved_y saved_z'
    use_finite_deform_jacobian = true
  []
[]
[BCs]
  [botz]
    type = ADDirichletBC
    variable = disp_z
    boundary = 101
    value = 0.0
  []
  [boty]
    type = ADDirichletBC
    variable = disp_y
    boundary = 101
    value = 0.0
  []
  [botx]
    type = ADDirichletBC
    variable = disp_x
    boundary = 101
    value = 0.0
  []
  [topz]
    type = ADFunctionDirichletBC
    variable = disp_z
    boundary = '201'
    function = push_down
  []
  [topy]
    type = ADDirichletBC
    variable = disp_y
    boundary = '201 202'
    value = 0.0
  []
  [topx]
    type = ADDirichletBC
    variable = disp_x
    boundary = '201 202'
    value = 0.0
  []
[]
[Materials]
  [tensor]
    type = ADComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1.40625e7
    poissons_ratio = 0.25
  []
  [stress]
    type = ADComputeFiniteStrainElasticStress
    block = '1'
  []
  [tensor_1000]
    type = ADComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e5
    poissons_ratio = 0.0
  []
  [stress_1000]
    type = ADComputeFiniteStrainElasticStress
    block = '2'
  []
[]
[Postprocessors]
  [stress_zz]
    type = ElementAverageValue
    variable = stress_zz
    block = 1
  []
  [resid_z]
    type = NodalSum
    variable = saved_z
    boundary = 201
  []
  [disp_z]
    type = NodalExtremeValue
    variable = disp_z
    boundary = 201
  []
[]
[Executioner]
  type = Transient
  solve_type = 'PJFNK'
  petsc_options_iname = '-pc_type -pc_factor_mat_solver_package -pc_factor_shift_type '
                        '-pc_factor_shift_amount -mat_mffd_err'
  petsc_options_value = 'lu    superlu_dist nonzero 1e-14 1e-5'
  line_search = 'none'
  l_max_its = 60
  nl_max_its = 50
  dt = 0.004
  dtmin = 0.00001
  # end_time = 1.8
  end_time = 0.000
  nl_rel_tol = 1.0e-6 #1e-7 # -8, -6 to avoid many iterations. Switch it March 2021
  nl_abs_tol = 1e-6 # 6 if no friction
  l_tol = 1e-4
[]
[Outputs]
  exodus = true
  csv = true
  print_linear_residuals = true
  perf_graph = true
  [console]
    type = Console
    max_rows = 5
  []
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    lm_variable_normal = frictional_normal_lm
    lm_variable_tangential_one = frictional_tangential_lm
    lm_variable_tangential_two = frictional_tangential_dir_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    debug_mesh = true
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    variable = frictional_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    friction_lm = frictional_tangential_lm
    friction_lm_dir = frictional_tangential_dir_lm
    c = 7.0e4
    c_t = 7.0e4
    mu = 0.4
    debug_mesh = true
    weighted_gap_uo = weighted_vel_uo
    weighted_velocities_uo = weighted_vel_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    variable = frictional_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    variable = frictional_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    variable = frictional_normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    variable = frictional_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    variable = frictional_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    variable = frictional_tangential_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_x_dir]
    type = TangentialMortarMechanicalContact
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    variable = frictional_tangential_dir_lm
    secondary_variable = disp_x
    component = x
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y_dir]
    type = TangentialMortarMechanicalContact
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    variable = frictional_tangential_dir_lm
    secondary_variable = disp_y
    component = y
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_z_dir]
    type = TangentialMortarMechanicalContact
    primary_boundary = 102
    secondary_boundary = 202
    primary_subdomain = 1002
    secondary_subdomain = 2002
    variable = frictional_tangential_dir_lm
    secondary_variable = disp_z
    component = z
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[Debug]
 show_var_residual_norms = true
[]
(modules/contact/test/tests/mortar_dynamics/frictional-mortar-3d-dynamics.i)
starting_point = 0.25
offset = 0.00
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[AuxVariables]
  [mortar_tangent_x]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_y]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_z]
    family = LAGRANGE
    order = FIRST
  []
[]
[AuxKernels]
  [friction_x_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_x
   component = 0
   boundary = 'top_bottom'
  []
  [friction_y_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_y
   component = 1
   boundary = 'top_bottom'
  []
  [friction_z_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_z
   component = 2
   boundary = 'top_bottom'
  []
[]
[Mesh]
  [top_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 3
    ny = 3
    nz = 3
    xmin = -0.25
    xmax = 0.25
    ymin = -0.25
    ymax = 0.25
    zmin = -0.25
    zmax = 0.25
    elem_type = HEX8
  []
  [rotate_top_block]
    type = TransformGenerator
    input = top_block
    transform = ROTATE
    vector_value = '0 0 0'
  []
  [top_block_sidesets]
    type = RenameBoundaryGenerator
    input = rotate_top_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'top_bottom top_back top_right top_front top_left top_top'
  []
  [top_block_id]
    type = SubdomainIDGenerator
    input = top_block_sidesets
    subdomain_id = 1
  []
  [bottom_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 10
    ny = 10
    nz = 2
    xmin = -.5
    xmax = .5
    ymin = -.5
    ymax = .5
    zmin = -.3
    zmax = -.25
    elem_type = HEX8
  []
  [bottom_block_id]
    type = SubdomainIDGenerator
    input = bottom_block
    subdomain_id = 2
  []
  [bottom_block_change_boundary_id]
    type = RenameBoundaryGenerator
    input = bottom_block_id
    old_boundary = '0 1 2 3 4 5'
    new_boundary = '100 101 102 103 104 105'
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'top_block_id bottom_block_change_boundary_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'top_block bottom_block'
  []
  [bottom_right_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = block_rename
    new_boundary = bottom_right
    block = bottom_block
    normal = '1 0 0'
  []
  [bottom_left_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_right_sideset
    new_boundary = bottom_left
    block = bottom_block
    normal = '-1 0 0'
  []
  [bottom_top_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_left_sideset
    new_boundary = bottom_top
    block = bottom_block
    normal = '0 0 1'
  []
  [bottom_bottom_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_top_sideset
    new_boundary = bottom_bottom
    block = bottom_block
    normal = '0  0 -1'
  []
  [bottom_front_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_bottom_sideset
    new_boundary = bottom_front
    block = bottom_block
    normal = '0 1 0'
  []
  [bottom_back_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_front_sideset
    new_boundary = bottom_back
    block = bottom_block
    normal = '0 -1 0'
  []
  [secondary]
    input = bottom_back_sideset
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'top_bottom' # top_back top_left'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'bottom_top'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
  uniform_refine = 0
  allow_renumbering = false
[]
[Variables]
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_3d_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[Physics/SolidMechanics/Dynamic]
  [all]
    add_variables = true
    hht_alpha = 0.0
    newmark_beta = 0.25
    newmark_gamma = 0.5
    mass_damping_coefficient = 0.0
    stiffness_damping_coefficient = 0.1
    displacements = 'disp_x disp_y disp_z'
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_zz'
    block = '1 2'
    strain = FINITE
    density = density
  []
[]
[Materials]
  [density]
    type = GenericConstantMaterial
    block = '1 2'
    prop_names = 'density'
    prop_values = '1.0'
  []
  [tensor]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1.0e4
    poissons_ratio = 0.0
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
  [tensor_1000]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e5
    poissons_ratio = 0.0
  []
  [stress_1000]
    type = ComputeFiniteStrainElasticStress
    block = '2'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable_normal = mortar_normal_lm
    lm_variable_tangential_one = mortar_tangential_lm
    lm_variable_tangential_two = mortar_tangential_3d_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [friction]
    type = ComputeDynamicFrictionalForceLMMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    friction_lm = mortar_tangential_lm
    friction_lm_dir = mortar_tangential_3d_lm
    mu = 0.4
    c = 1e4
    c_t = 1.0e4
    newmark_gamma = 0.5
    newmark_beta = 0.25
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_x
    component = x
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_y
    component = y
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_z
    component = z
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [botz]
    type = DirichletBC
    variable = disp_z
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [topx]
    type = DirichletBC
    variable = disp_x
    boundary = 'top_top'
    value = 0.0
  []
  [topy]
    type = DirichletBC
    variable = disp_y
    boundary = 'top_top'
    value = 0.0
  []
  [topz]
    type = FunctionDirichletBC
    variable = disp_z
    boundary = 'top_top'
    function = '-${starting_point} * sin(2 * pi / 40 * t) + ${offset}'
  []
[]
[Executioner]
  type = Transient
  end_time = .025
  dt = .025
  dtmin = .001
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -snes_ksp_ew'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount'
  petsc_options_value = 'lu       NONZERO               1e-14'
  nl_rel_tol = 1e-11
  nl_abs_tol = 1e-11
  line_search = 'basic'
  [TimeIntegrator]
    type = NewmarkBeta
    gamma = 0.5
    beta = 0.25
  []
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  csv = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'contact'
  [contact]
    type = ContactDOFSetSize
    variable = mortar_normal_lm
    subdomain = 'secondary_lower'
    execute_on = 'nonlinear timestep_end'
  []
[]
[VectorPostprocessors]
  [contact-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_normal_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [frictional-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [frictional-pressure-3d]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_3d_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [tangent_x]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_x
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [tangent_y]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_y
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
[]
(modules/contact/test/tests/3d-mortar-contact/frictional-mortar-3d.i)
starting_point = 0.25
offset = 0.00
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[AuxVariables]
  [mortar_tangent_x]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_y]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_z]
    family = LAGRANGE
    order = FIRST
  []
[]
[AuxKernels]
  [friction_x_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_x
   component = 0
   boundary = 'top_bottom'
  []
  [friction_y_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_y
   component = 1
   boundary = 'top_bottom'
  []
  [friction_z_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_z
   component = 2
   boundary = 'top_bottom'
  []
[]
[Mesh]
  [top_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 3
    ny = 3
    nz = 3
    xmin = -0.25
    xmax = 0.25
    ymin = -0.25
    ymax = 0.25
    zmin = -0.25
    zmax = 0.25
    elem_type = HEX8
  []
  [rotate_top_block]
    type = TransformGenerator
    input = top_block
    transform = ROTATE
    vector_value = '0 0 0'
  []
  [top_block_sidesets]
    type = RenameBoundaryGenerator
    input = rotate_top_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'top_bottom top_back top_right top_front top_left top_top'
  []
  [top_block_id]
    type = SubdomainIDGenerator
    input = top_block_sidesets
    subdomain_id = 1
  []
  [bottom_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 10
    ny = 10
    nz = 2
    xmin = -.5
    xmax = .5
    ymin = -.5
    ymax = .5
    zmin = -.3
    zmax = -.25
    elem_type = HEX8
  []
  [bottom_block_id]
    type = SubdomainIDGenerator
    input = bottom_block
    subdomain_id = 2
  []
  [bottom_block_change_boundary_id]
    type = RenameBoundaryGenerator
    input = bottom_block_id
    old_boundary = '0 1 2 3 4 5'
    new_boundary = '100 101 102 103 104 105'
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'top_block_id bottom_block_change_boundary_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'top_block bottom_block'
  []
  [bottom_right_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = block_rename
    new_boundary = bottom_right
    block = bottom_block
    normal = '1 0 0'
  []
  [bottom_left_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_right_sideset
    new_boundary = bottom_left
    block = bottom_block
    normal = '-1 0 0'
  []
  [bottom_top_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_left_sideset
    new_boundary = bottom_top
    block = bottom_block
    normal = '0 0 1'
  []
  [bottom_bottom_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_top_sideset
    new_boundary = bottom_bottom
    block = bottom_block
    normal = '0  0 -1'
  []
  [bottom_front_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_bottom_sideset
    new_boundary = bottom_front
    block = bottom_block
    normal = '0 1 0'
  []
  [bottom_back_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_front_sideset
    new_boundary = bottom_back
    block = bottom_block
    normal = '0 -1 0'
  []
  [secondary]
    input = bottom_back_sideset
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'top_bottom' # top_back top_left'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'bottom_top'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
  uniform_refine = 0
  allow_renumbering = false
[]
[Variables]
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_3d_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    add_variables = true
    strain = FINITE
    block = '1 2'
    use_automatic_differentiation = false
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_zz'
  []
[]
[Materials]
  [tensor]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1.0e4
    poissons_ratio = 0.0
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
  [tensor_1000]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e5
    poissons_ratio = 0.0
  []
  [stress_1000]
    type = ComputeFiniteStrainElasticStress
    block = '2'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    lm_variable_normal = mortar_normal_lm
    lm_variable_tangential_one = mortar_tangential_lm
    lm_variable_tangential_two = mortar_tangential_3d_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
  []
[]
[Constraints]
  [friction]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    mu = 0.4
    c = 1e4
    c_t = 1.0e4
    friction_lm = mortar_tangential_lm
    friction_lm_dir = mortar_tangential_3d_lm
    weighted_gap_uo = weighted_vel_uo
    weighted_velocities_uo = weighted_vel_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_x
    component = x
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_y
    component = y
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_z
    component = z
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [botz]
    type = DirichletBC
    variable = disp_z
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [topx]
    type = DirichletBC
    variable = disp_x
    boundary = 'top_top'
    value = 0.0
  []
  [topy]
    type = DirichletBC
    variable = disp_y
    boundary = 'top_top'
    value = 0.0
  []
  [topz]
    type = FunctionDirichletBC
    variable = disp_z
    boundary = 'top_top'
    function = '-${starting_point} * sin(2 * pi / 40 * t) + ${offset}'
  []
[]
[Executioner]
  type = Transient
  end_time = .025
  dt = .025
  dtmin = .001
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -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-14                  1e-5'
  l_max_its = 15
  nl_max_its = 30
  nl_rel_tol = 1e-11
  nl_abs_tol = 1e-12
  line_search = 'basic'
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  csv = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'contact'
  [contact]
    type = ContactDOFSetSize
    variable = mortar_normal_lm
    subdomain = 'secondary_lower'
    execute_on = 'nonlinear timestep_end'
  []
[]
[VectorPostprocessors]
  [contact-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_normal_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [frictional-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [frictional-pressure-3d]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_3d_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [tangent_x]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_x
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [tangent_y]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_y
    sort_by = 'id'
    execute_on = NONLINEAR
  []
[]
(modules/contact/test/tests/pdass_problems/ironing.i)
[GlobalParams]
  volumetric_locking_correction = true
  displacements = 'disp_x disp_y'
[]
[Mesh]
  [input_file]
    type = FileMeshGenerator
    file = iron.e
  []
  [secondary]
    type = LowerDBlockFromSidesetGenerator
    new_block_id = 10001
    new_block_name = 'secondary_lower'
    sidesets = '10'
    input = input_file
  []
  [primary]
    type = LowerDBlockFromSidesetGenerator
    new_block_id = 10000
    sidesets = '20'
    new_block_name = 'primary_lower'
    input = secondary
  []
  patch_update_strategy = auto
  patch_size = 20
[]
[Variables]
  [disp_x]
  []
  [disp_y]
  []
  [frictionless_normal_lm]
    order = FIRST
    family = LAGRANGE
    block = 'secondary_lower'
    use_dual = true
  []
  [tangential_lm]
    order = FIRST
    family = LAGRANGE
    block = 'secondary_lower'
    use_dual = true
  []
[]
[AuxVariables]
  [stress_xx]
    order = CONSTANT
    family = MONOMIAL
  []
  [stress_yy]
    order = CONSTANT
    family = MONOMIAL
  []
  [stress_xy]
    order = CONSTANT
    family = MONOMIAL
  []
  [saved_x]
  []
  [saved_y]
  []
  [diag_saved_x]
  []
  [diag_saved_y]
  []
  [von_mises]
    order = CONSTANT
    family = MONOMIAL
  []
[]
[Functions]
  [disp_ramp_vert]
    type = PiecewiseLinear
    x = '0. 2. 8.'
    y = '0. -1.0 -1.0'
  []
  [disp_ramp_horz]
    type = PiecewiseLinear
    x = '0. 8.' # x = '0. 2. 8.'
    y = '0. 8.' # y = '0. 0. 8'
  []
[]
[Kernels]
  [TensorMechanics]
    use_displaced_mesh = true
    save_in = 'saved_x saved_y'
    block = '1 2'
    strain = FINITE
  []
[]
[AuxKernels]
  [stress_xx]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_xx
    index_i = 0
    index_j = 0
    execute_on = timestep_end
    block = '1 2'
  []
  [stress_yy]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_yy
    index_i = 1
    index_j = 1
    execute_on = timestep_end
    block = '1 2'
  []
  [stress_xy]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_xy
    index_i = 0
    index_j = 1
    execute_on = timestep_end
    block = '1 2'
  []
  [von_mises_kernel]
    #Calculates the von mises stress and assigns it to von_mises
    type = RankTwoScalarAux
    variable = von_mises
    rank_two_tensor = stress
    execute_on = timestep_end
    scalar_type = VonMisesStress
    block = '1 2'
  []
[]
[Postprocessors]
  [bot_react_x]
    type = NodalSum
    variable = saved_x
    boundary = 20
  []
  [bot_react_y]
    type = NodalSum
    variable = saved_y
    boundary = 20
  []
  [top_react_x]
    type = NodalSum
    variable = saved_x
    boundary = 10
  []
  [top_react_y]
    type = NodalSum
    variable = saved_y
    boundary = 10
  []
  [_dt]
    type = TimestepSize
  []
  [contact_pressure]
    type = NodalVariableValue
    variable = frictionless_normal_lm
    nodeid = 805
  []
[]
[BCs]
  [bot_x_disp]
    type = DirichletBC
    variable = disp_x
    boundary = '40'
    value = 0.0
    preset = false
  []
  [bot_y_disp]
    type = DirichletBC
    variable = disp_y
    boundary = '40'
    value = 0.0
    preset = false
  []
  [top_y_disp]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = '30'
    function = disp_ramp_vert
    preset = false
  []
  [top_x_disp]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = '30'
    function = disp_ramp_horz
    preset = false
  []
[]
[Materials]
  [stuff1_elas_tens]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 6896
    poissons_ratio = 0.32
  []
  [stuff1_strain]
    type = ComputeFiniteStrain
    block = '2'
  []
  [stuff1_stress]
    type = ComputeFiniteStrainElasticStress
    block = '2'
  []
  [stuff2_elas_tens]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 689.6
    poissons_ratio = 0.32
  []
  [stuff2_strain]
    type = ComputeFiniteStrain
    block = '1'
  []
  [stuff2_stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
[]
[Executioner]
  type = Transient
  solve_type = 'PJFNK'
  petsc_options = '-snes_ksp_ew'
  petsc_options_iname = '-pc_type -pc_factor_mat_solver_type'
  petsc_options_value = 'lu     superlu_dist'
  line_search = 'none'
  nl_abs_tol = 1e-7
  nl_rel_tol = 1e-7
  l_tol = 1e-6
  l_max_its = 50
  nl_max_its = 30
  start_time = 0.0
  end_time = 0.1 # 6.5
  dt = 0.0125
  dtmin = 1e-5
[]
[Preconditioning]
  [SMP]
    type = SMP
    full = true
  []
[]
[VectorPostprocessors]
  [cont_press]
    type = NodalValueSampler
    variable = frictionless_normal_lm
    boundary = '10'
    sort_by = id
    execute_on = FINAL
  []
  [friction]
    type = NodalValueSampler
    variable = tangential_lm
    boundary = '10'
    sort_by = id
    execute_on = FINAL
  []
[]
[Outputs]
  print_linear_residuals = true
  perf_graph = true
  exodus = false
  csv = true
  [chkfile]
    type = CSV
    show = 'cont_press friction'
    start_time = 0.0
    execute_vector_postprocessors_on = FINAL
  []
  [console]
    type = Console
    max_rows = 5
  []
[]
[Debug]
  show_var_residual_norms = true
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 10000
    secondary_subdomain = 10001
    lm_variable_normal = frictionless_normal_lm
    lm_variable_tangential_one = tangential_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  # All constraints below for mechanical contact (Mortar)
  [weighted_gap_lm]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 10000
    secondary_subdomain = 10001
    variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    friction_lm = tangential_lm
    mu = 0.5
    c_t = 1.0e1
    c = 1.0e3
    weighted_gap_uo = weighted_vel_uo
    weighted_velocities_uo = weighted_vel_uo
  []
  [x]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = '10000'
    secondary_subdomain = '10001'
    variable = frictionless_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [y]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = '10000'
    secondary_subdomain = '10001'
    variable = frictionless_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = '10000'
    secondary_subdomain = '10001'
    variable = tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = '10000'
    secondary_subdomain = '10001'
    variable = tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
(modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-wear-vel.i)
starting_point = 0.5e-1
offset = -0.05
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Mesh]
  file = long-bottom-block-1elem-blocks.e
[]
[Variables]
  [disp_x]
    block = '1 2'
  []
  [disp_y]
    block = '1 2'
  []
  [normal_lm]
    block = 3
    use_dual = true
    scaling = 1.0e3
  []
  [frictional_lm]
    block = 3
    use_dual = true
  []
[]
[ICs]
  [disp_y]
    block = 2
    variable = disp_y
    value = '${fparse starting_point + offset}'
    type = ConstantIC
  []
[]
[Kernels]
  [DynamicTensorMechanics]
    displacements = 'disp_x disp_y'
    generate_output = 'stress_xx stress_yy'
    strain = FINITE
    block = '1 2'
    stiffness_damping_coefficient = 1.0
    hht_alpha = 0.0
  []
  [inertia_x]
    type = InertialForce
    variable = disp_x
    velocity = vel_x
    acceleration = accel_x
    beta = 0.25
    gamma = 0.5
    alpha = 0
    eta = 0.0
    block = '1 2'
  []
  [inertia_y]
    type = InertialForce
    variable = disp_y
    velocity = vel_y
    acceleration = accel_y
    beta = 0.25
    gamma = 0.5
    alpha = 0
    eta = 0.0
    block = '1 2'
  []
[]
[Materials]
  [elasticity_2]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e6
    poissons_ratio = 0.3
  []
  [elasticity_1]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1e8
    poissons_ratio = 0.3
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1 2'
  []
  [strain]
    type = ComputeFiniteStrain
    block = '1 2'
  []
  [density]
    type = GenericConstantMaterial
    block = '1 2'
    prop_names = 'density'
    prop_values = '7750'
  []
[]
[AuxVariables]
  [worn_depth]
    block = '3'
  []
  [gap_vel]
    block = '3'
  []
  [vel_x]
    block = '1 2'
  []
  [accel_x]
    block = '1 2'
  []
  [vel_y]
    block = '1 2'
  []
  [accel_y]
    block = '1 2'
  []
  [vel_z]
    block = '1 2'
  []
  [accel_z]
    block = '1 2'
  []
[]
[AuxKernels]
  [gap_vel]
    type = WeightedGapVelAux
    variable = gap_vel
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    disp_x = disp_x
    disp_y = disp_y
  []
  [worn_depth]
    type = MortarArchardsLawAux
    variable = worn_depth
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    displacements = 'disp_x disp_y'
    friction_coefficient = 0.5
    energy_wear_coefficient = 1.0
    normal_pressure = normal_lm
  []
  [accel_x]
    type = NewmarkAccelAux
    variable = accel_x
    displacement = disp_x
    velocity = vel_x
    beta = 0.25
    execute_on = 'linear timestep_end'
  []
  [vel_x]
    type = NewmarkVelAux
    variable = vel_x
    acceleration = accel_x
    gamma = 0.5
    execute_on = 'linear timestep_end'
  []
  [accel_y]
    type = NewmarkAccelAux
    variable = accel_y
    displacement = disp_y
    velocity = vel_y
    beta = 0.25
    execute_on = 'linear timestep_end'
  []
  [vel_y]
    type = NewmarkVelAux
    variable = vel_y
    acceleration = accel_y
    gamma = 0.5
    execute_on = 'linear timestep_end'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    secondary_variable = disp_x
    lm_variable_normal = normal_lm
    lm_variable_tangential_one = frictional_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeDynamicFrictionalForceLMMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    c = 1e4
    c_t = 1e6
    mu = 0.15
    friction_lm = frictional_lm
    capture_tolerance = 1.0e-5
    newmark_beta = 0.25
    newmark_gamma = 0.5
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 40
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 40
    value = 0.0
  []
  [topy]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 30
    function = '${starting_point} * cos(16.0 * pi / 4 * t) + ${offset}'
  []
  [leftx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 50
    function = '1e-2 * t'
  []
[]
[Executioner]
  type = Transient
  end_time = 0.3
  dt = 0.03
  dtmin = .002
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -pc_svd_monitor '
                  '-snes_linesearch_monitor -snes_ksp_ew'
  petsc_options_iname = '-pc_type -pc_factor_mat_solver_type -pc_factor_shift_type -pc_factor_shift_amount'
  petsc_options_value = 'lu       superlu_dist                  NONZERO               1e-15'
  nl_max_its = 40
  nl_abs_tol = 1.0e-11
  nl_rel_tol = 1.0e-11
  line_search = 'none'
  snesmf_reuse_base = true
  [TimeIntegrator]
    type = NewmarkBeta
    beta = 0.25
    gamma = 0.5
  []
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  checkpoint = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'contact'
  [num_nl]
    type = NumNonlinearIterations
  []
  [cumulative]
    type = CumulativeValuePostprocessor
    postprocessor = num_nl
  []
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = '3'
    execute_on = 'nonlinear timestep_end'
  []
[]
(modules/contact/test/tests/3d-mortar-contact/frictional-mortar-3d-function.i)
starting_point = 0.25
offset = 0.00
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[AuxVariables]
  [mortar_tangent_x]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_y]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_z]
    family = LAGRANGE
    order = FIRST
  []
[]
[Functions]
  # x: Contact pressure
  # y: Magnitude of tangential relative velocity
  # z: Temperature (to be implemented)
  [mu_function]
    type = ParsedFunction
    expression = '0.3 + (0.7 - 0.3) * 2.17^(-0.5/y) - x/10000'
  []
[]
[AuxKernels]
  [friction_x_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_x
   component = 0
   boundary = 'top_bottom'
  []
  [friction_y_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_y
   component = 1
   boundary = 'top_bottom'
  []
  [friction_z_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_z
   component = 2
   boundary = 'top_bottom'
  []
[]
[Mesh]
  [top_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 3
    ny = 3
    nz = 3
    xmin = -0.25
    xmax = 0.25
    ymin = -0.25
    ymax = 0.25
    zmin = -0.25
    zmax = 0.25
    elem_type = HEX8
  []
  [rotate_top_block]
    type = TransformGenerator
    input = top_block
    transform = ROTATE
    vector_value = '0 0 0'
  []
  [top_block_sidesets]
    type = RenameBoundaryGenerator
    input = rotate_top_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'top_bottom top_back top_right top_front top_left top_top'
  []
  [top_block_id]
    type = SubdomainIDGenerator
    input = top_block_sidesets
    subdomain_id = 1
  []
  [bottom_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 10
    ny = 10
    nz = 2
    xmin = -.5
    xmax = .5
    ymin = -.5
    ymax = .5
    zmin = -.3
    zmax = -.25
    elem_type = HEX8
  []
  [bottom_block_id]
    type = SubdomainIDGenerator
    input = bottom_block
    subdomain_id = 2
  []
  [bottom_block_change_boundary_id]
    type = RenameBoundaryGenerator
    input = bottom_block_id
    old_boundary = '0 1 2 3 4 5'
    new_boundary = '100 101 102 103 104 105'
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'top_block_id bottom_block_change_boundary_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'top_block bottom_block'
  []
  [bottom_right_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = block_rename
    new_boundary = bottom_right
    block = bottom_block
    normal = '1 0 0'
  []
  [bottom_left_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_right_sideset
    new_boundary = bottom_left
    block = bottom_block
    normal = '-1 0 0'
  []
  [bottom_top_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_left_sideset
    new_boundary = bottom_top
    block = bottom_block
    normal = '0 0 1'
  []
  [bottom_bottom_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_top_sideset
    new_boundary = bottom_bottom
    block = bottom_block
    normal = '0  0 -1'
  []
  [bottom_front_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_bottom_sideset
    new_boundary = bottom_front
    block = bottom_block
    normal = '0 1 0'
  []
  [bottom_back_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_front_sideset
    new_boundary = bottom_back
    block = bottom_block
    normal = '0 -1 0'
  []
  [secondary]
    input = bottom_back_sideset
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'top_bottom' # top_back top_left'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'bottom_top'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
  uniform_refine = 0
  allow_renumbering = false
[]
[Variables]
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_3d_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    add_variables = true
    strain = FINITE
    block = '1 2'
    use_automatic_differentiation = false
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_zz'
  []
[]
[Materials]
  [tensor]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1.0e4
    poissons_ratio = 0.0
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
  [tensor_1000]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e5
    poissons_ratio = 0.0
  []
  [stress_1000]
    type = ComputeFiniteStrainElasticStress
    block = '2'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    lm_variable_normal = mortar_normal_lm
    lm_variable_tangential_one = mortar_tangential_lm
    lm_variable_tangential_two = mortar_tangential_3d_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
  []
[]
[Constraints]
  [friction]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    # mu = 0.4
    function_friction = mu_function
    c = 1e4
    c_t = 1.0e6
    friction_lm = mortar_tangential_lm
    friction_lm_dir = mortar_tangential_3d_lm
    weighted_gap_uo = weighted_vel_uo
    weighted_velocities_uo = weighted_vel_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_x
    component = x
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_y
    component = y
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_z
    component = z
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [botz]
    type = DirichletBC
    variable = disp_z
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [topx]
    type = DirichletBC
    variable = disp_x
    boundary = 'top_top'
    value = 0.0
  []
  [topy]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 'top_top'
    function = '0.1*t'
  []
  [topz]
    type = FunctionDirichletBC
    variable = disp_z
    boundary = 'top_top'
    function = '-${starting_point} * sin(2 * pi / 40 * t) + ${offset}'
  []
[]
[Executioner]
  type = Transient
  end_time = .05
  dt = .025
  dtmin = .001
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -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-14                  1e-5'
  l_max_its = 15
  nl_max_its = 30
  nl_rel_tol = 1e-11
  nl_abs_tol = 1e-12
  line_search = 'basic'
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  csv = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'contact'
  [contact]
    type = ContactDOFSetSize
    variable = mortar_normal_lm
    subdomain = 'secondary_lower'
    execute_on = 'nonlinear timestep_end'
  []
[]
[VectorPostprocessors]
  [contact-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_normal_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [frictional-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [frictional-pressure-3d]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_3d_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [tangent_x]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_x
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [tangent_y]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_y
    sort_by = 'id'
    execute_on = NONLINEAR
  []
[]
(modules/contact/test/tests/bouncing-block-contact/frictional-nodal-min-normal-lm-mortar-pdass-tangential-lm-mortar-disp.i)
starting_point = 2e-1
# We offset slightly so we avoid the case where the bottom of the secondary block and the top of the
# primary block are perfectly vertically aligned which can cause the backtracking line search some
# issues for a coarse mesh (basic line search handles that fine)
offset = 1e-2
[GlobalParams]
  displacements = 'disp_x disp_y'
  diffusivity = 1e0
  scaling = 1e0
[]
[Mesh]
  [file_mesh]
    type = FileMeshGenerator
    file = long-bottom-block-1elem-blocks-coarse.e
  []
[]
[Variables]
  [disp_x]
    block = '1 2'
    # order = SECOND
  []
  [disp_y]
    block = '1 2'
    # order = SECOND
  []
  [frictional_normal_lm]
    block = 3
    use_dual = true
  []
  [frictional_tangential_lm]
    block = 3
    use_dual = true
  []
[]
[ICs]
  [disp_y]
    block = 2
    variable = disp_y
    value = '${fparse starting_point + offset}'
    type = ConstantIC
  []
[]
[Kernels]
  [disp_x]
    type = MatDiffusion
    variable = disp_x
  []
  [disp_y]
    type = MatDiffusion
    variable = disp_y
  []
[]
[UserObjects]
  [weighted_velocities_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable_normal = frictional_normal_lm
    lm_variable_tangential_one = frictional_tangential_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [frictional_normal_lm]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_normal_lm
    friction_lm = frictional_tangential_lm
    disp_x = disp_x
    disp_y = disp_y
    mu = 0.1
    c = 1.0e-2
    c_t = 1.0e-1
    weighted_gap_uo = weighted_velocities_uo
    weighted_velocities_uo = weighted_velocities_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_velocities_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_velocities_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_velocities_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_velocities_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 40
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 40
    value = 0.0
  []
  [topy]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 30
    function = '${starting_point} * cos(2 * pi / 40 * t) + ${offset}'
  []
  [leftx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 50
    function = '1e-2 * t'
  []
[]
[Executioner]
  type = Transient
  end_time = 200
  dt = 5
  dtmin = .1
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -pc_svd_monitor '
                  '-snes_linesearch_monitor -snes_ksp_ew'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -mat_mffd_err'
  petsc_options_value = 'lu       NONZERO               1e-15                   1e-5'
  l_max_its = 30
  nl_max_its = 20
  line_search = 'none'
  snesmf_reuse_base = false
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
[]
(modules/contact/test/tests/mortar_dynamics/frictional-mortar-3d-dynamics-light-function.i)
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[AuxVariables]
  [mortar_tangent_x]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_y]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_z]
    family = LAGRANGE
    order = FIRST
  []
[]
[AuxKernels]
  [friction_x_component]
    type = MortarFrictionalPressureVectorAux
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    tangent_one = mortar_tangential_lm
    tangent_two = mortar_tangential_3d_lm
    variable = mortar_tangent_x
    component = 0
    boundary = 'top_bottom'
  []
  [friction_y_component]
    type = MortarFrictionalPressureVectorAux
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    tangent_one = mortar_tangential_lm
    tangent_two = mortar_tangential_3d_lm
    variable = mortar_tangent_y
    component = 1
    boundary = 'top_bottom'
  []
  [friction_z_component]
    type = MortarFrictionalPressureVectorAux
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    tangent_one = mortar_tangential_lm
    tangent_two = mortar_tangential_3d_lm
    variable = mortar_tangent_z
    component = 2
    boundary = 'top_bottom'
  []
[]
[Mesh]
  [top_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 2
    ny = 2
    nz = 1
    xmin = -0.25
    xmax = 0.25
    ymin = -0.25
    ymax = 0.25
    zmin = -0.25
    zmax = 0.25
    elem_type = HEX8
  []
  [rotate_top_block]
    type = TransformGenerator
    input = top_block
    transform = ROTATE
    vector_value = '0 0 0'
  []
  [top_block_sidesets]
    type = RenameBoundaryGenerator
    input = rotate_top_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'top_bottom top_back top_right top_front top_left top_top'
  []
  [top_block_id]
    type = SubdomainIDGenerator
    input = top_block_sidesets
    subdomain_id = 1
  []
  [bottom_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 2
    ny = 2
    nz = 1
    xmin = -.5
    xmax = .5
    ymin = -.5
    ymax = .5
    zmin = -.3
    zmax = -.25
    elem_type = HEX8
  []
  [bottom_block_id]
    type = SubdomainIDGenerator
    input = bottom_block
    subdomain_id = 2
  []
  [bottom_block_change_boundary_id]
    type = RenameBoundaryGenerator
    input = bottom_block_id
    old_boundary = '0 1 2 3 4 5'
    new_boundary = '100 101 102 103 104 105'
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'top_block_id bottom_block_change_boundary_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'top_block bottom_block'
  []
  [bottom_right_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = block_rename
    new_boundary = bottom_right
    block = bottom_block
    normal = '1 0 0'
  []
  [bottom_left_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_right_sideset
    new_boundary = bottom_left
    block = bottom_block
    normal = '-1 0 0'
  []
  [bottom_top_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_left_sideset
    new_boundary = bottom_top
    block = bottom_block
    normal = '0 0 1'
  []
  [bottom_bottom_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_top_sideset
    new_boundary = bottom_bottom
    block = bottom_block
    normal = '0  0 -1'
  []
  [bottom_front_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_bottom_sideset
    new_boundary = bottom_front
    block = bottom_block
    normal = '0 1 0'
  []
  [bottom_back_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_front_sideset
    new_boundary = bottom_back
    block = bottom_block
    normal = '0 -1 0'
  []
  [secondary]
    input = bottom_back_sideset
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'top_bottom' # top_back top_left'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'bottom_top'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
  uniform_refine = 0
[]
[Functions]
  # x: Contact pressure
  # y: Magnitude of tangential relative velocity
  # z: Temperature (to be implemented)
  [mu_function]
    type = ParsedFunction
    expression = '0.3 + 0.5 * 2.17^(-x/100) - 10.0 * y'
  []
[]
[Variables]
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
    scaling = 1e-3
  []
  [mortar_tangential_lm]
    block = 'secondary_lower'
    use_dual = true
    scaling = 1e-3
  []
  [mortar_tangential_3d_lm]
    block = 'secondary_lower'
    use_dual = true
    scaling = 1e-3
  []
[]
[Physics/SolidMechanics/Dynamic]
  [all]
    add_variables = true
    hht_alpha = 0.0
    newmark_beta = 0.25
    newmark_gamma = 0.5
    mass_damping_coefficient = 0.0
    stiffness_damping_coefficient = 0.02
    displacements = 'disp_x disp_y disp_z'
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_zz'
    block = '1 2'
    strain = FINITE
    density = density
  []
[]
[Materials]
  [density]
    type = GenericConstantMaterial
    block = '1 2'
    prop_names = 'density'
    prop_values = '1.0'
  []
  [tensor]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1.0e4
    poissons_ratio = 0.0
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
  [tensor_1000]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e5
    poissons_ratio = 0.0
  []
  [stress_1000]
    type = ComputeFiniteStrainElasticStress
    block = '2'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable_normal = mortar_normal_lm
    lm_variable_tangential_one = mortar_tangential_lm
    lm_variable_tangential_two = mortar_tangential_3d_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [friction]
    type = ComputeDynamicFrictionalForceLMMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    friction_lm = mortar_tangential_lm
    friction_lm_dir = mortar_tangential_3d_lm
    c = 1e5
    c_t = 1.0e5
    newmark_beta = 0.25
    newmark_gamma = 0.5
    interpolate_normals = false
    correct_edge_dropping = true
    capture_tolerance = 1e-04
    function_friction = mu_function
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    interpolate_normals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    interpolate_normals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    interpolate_normals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    interpolate_normals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    interpolate_normals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    interpolate_normals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_x
    component = x
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    interpolate_normals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_y
    component = y
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    interpolate_normals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_z
    component = z
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    interpolate_normals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 'bottom_left bottom_right bottom_front bottom_back bottom_top bottom_bottom'
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 'bottom_left bottom_right bottom_front bottom_back bottom_top bottom_bottom'
    value = 0.0
  []
  [botz]
    type = DirichletBC
    variable = disp_z
    boundary = 'bottom_left bottom_right bottom_front bottom_back bottom_top bottom_bottom'
    value = 0.0
  []
  [topx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 'top_top'
    function = '0.1*t'
  []
  [topy]
    type = DirichletBC
    variable = disp_y
    boundary = 'top_top'
    value = 0.0
  []
  [topz]
    type = FunctionDirichletBC
    variable = disp_z
    boundary = 'top_top'
    function = '-0.1*t'
  []
[]
[Executioner]
  type = Transient
  end_time = .04
  dt = .02
  dtmin = .001
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -snes_ksp_ew'
  petsc_options_iname = '-pc_type  -pc_factor_shift_type'
  petsc_options_value = ' lu       NONZERO             '
  nl_rel_tol = 5e-13
  nl_abs_tol = 5e-13
  line_search = 'basic'
  [TimeIntegrator]
    type = NewmarkBeta
    gamma = 0.5
    beta = 0.25
  []
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  csv = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'contact'
  [contact]
    type = ContactDOFSetSize
    variable = mortar_normal_lm
    subdomain = 'secondary_lower'
    execute_on = 'nonlinear timestep_end'
  []
[]
[VectorPostprocessors]
  [contact-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_normal_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [frictional-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [frictional-pressure-3d]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_3d_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [tangent_x]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_x
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [tangent_y]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_y
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
[]
(modules/contact/test/tests/mortar_dynamics/block-dynamics-friction.i)
starting_point = 2e-1
offset = -0.19
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Mesh]
  file = long-bottom-block-1elem-blocks.e
  allow_renumbering = false
[]
[Variables]
  [disp_x]
    block = '1 2'
  []
  [disp_y]
    block = '1 2'
  []
  [mechanical_normal_lm]
    block = 3
    use_dual = true
  []
  [mechanical_tangential_lm]
    block = 3
    use_dual = true
  []
[]
[ICs]
  [disp_y]
    block = 2
    variable = disp_y
    value = '${fparse starting_point + offset}'
    type = ConstantIC
  []
[]
[Kernels]
  [DynamicTensorMechanics]
    displacements = 'disp_x disp_y'
    generate_output = 'stress_xx stress_yy'
    strain = FINITE
    block = '1 2'
    stiffness_damping_coefficient = 0.05
    hht_alpha = 0.0
  []
  [inertia_x]
    type = InertialForce
    variable = disp_x
    velocity = vel_x
    acceleration = accel_x
    beta = 0.25
    gamma = 0.5
    alpha = 0
    eta = 0.0
    block = '1 2'
  []
  [inertia_y]
    type = InertialForce
    variable = disp_y
    velocity = vel_y
    acceleration = accel_y
    beta = 0.25
    gamma = 0.5
    alpha = 0
    eta = 0.0
    block = '1 2'
  []
[]
[Materials]
  [elasticity_2]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e6
    poissons_ratio = 0.3
  []
  [elasticity_1]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1e8
    poissons_ratio = 0.3
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1 2'
  []
  [strain]
    type = ComputeFiniteStrain
    block = '1 2'
  []
  [density]
    type = GenericConstantMaterial
    block = '1 2'
    prop_names = 'density'
    prop_values = '7750'
  []
[]
[AuxVariables]
  [vel_x]
    block = '1 2'
  []
  [accel_x]
    block = '1 2'
  []
  [vel_y]
    block = '1 2'
  []
  [accel_y]
    block = '1 2'
  []
  [vel_z]
    block = '1 2'
  []
  [accel_z]
    block = '1 2'
  []
  [gap]
    block = 3
  []
[]
[AuxKernels]
  [gap]
    type = WeightedGapAux
    variable = gap
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    use_displaced_mesh = true
  []
  [accel_x]
    type = NewmarkAccelAux
    variable = accel_x
    displacement = disp_x
    velocity = vel_x
    beta = 0.25
    execute_on = 'LINEAR timestep_end'
  []
  [vel_x]
    type = NewmarkVelAux
    variable = vel_x
    acceleration = accel_x
    gamma = 0.5
    execute_on = 'LINEAR timestep_end'
  []
  [accel_y]
    type = NewmarkAccelAux
    variable = accel_y
    displacement = disp_y
    velocity = vel_y
    beta = 0.25
    execute_on = 'LINEAR timestep_end'
  []
  [vel_y]
    type = NewmarkVelAux
    variable = vel_y
    acceleration = accel_y
    gamma = 0.5
    execute_on = 'LINEAR timestep_end'
  []
[]
# User object provides the contact force (e.g. LM)
# for the application of the generalized force
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable_normal = mechanical_normal_lm
    lm_variable_tangential_one = mechanical_tangential_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeDynamicFrictionalForceLMMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = mechanical_normal_lm
    friction_lm = mechanical_tangential_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    c = 1e4
    c_t = 1e4
    mu = 0.5
    newmark_beta = 0.25
    newmark_gamma = 0.5
    capture_tolerance = 1.0e-5
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = mechanical_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = mechanical_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = mechanical_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = mechanical_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 40
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 40
    value = 0.0
  []
  [topy]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 30
    function = '${starting_point} * cos(2 * pi / 4 * t) + ${offset}'
  []
  [leftx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 30 # 50
    function = '0' # '1e-2*t'
  []
[]
[Executioner]
  type = Transient
  end_time = 75
  dt = 0.05
  dtmin = .005
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -pc_svd_monitor '
                  '-snes_linesearch_monitor -snes_ksp_ew'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -mat_mffd_err '
  petsc_options_value = 'lu       NONZERO               1e-15                   1e-5'
  nl_max_its = 50
  line_search = 'none'
  snesmf_reuse_base = false
  [TimeIntegrator]
    type = NewmarkBeta
    beta = 0.25
    gamma = 0.5
  []
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  csv = true
  checkpoint = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[VectorPostprocessors]
  [mechanical_tangential_lm]
    type = NodalValueSampler
    block = '3'
    variable = mechanical_tangential_lm
    sort_by = 'x'
    execute_on = TIMESTEP_END
  []
[]
(modules/contact/test/tests/3d-mortar-contact/frictional-mortar-3d_pg.i)
starting_point = 0.25
offset = 0.00
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[AuxVariables]
  [mortar_tangent_x]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_y]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_z]
    family = LAGRANGE
    order = FIRST
  []
  [aux_lm]
    block = 'secondary_lower'
    use_dual = false
  []
[]
[AuxKernels]
  [friction_x_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_x
   component = 0
   boundary = 'top_bottom'
  []
  [friction_y_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_y
   component = 1
   boundary = 'top_bottom'
  []
  [friction_z_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_z
   component = 2
   boundary = 'top_bottom'
  []
[]
[Mesh]
  [top_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 3
    ny = 3
    nz = 3
    xmin = -0.25
    xmax = 0.25
    ymin = -0.25
    ymax = 0.25
    zmin = -0.25
    zmax = 0.25
    elem_type = HEX8
  []
  [rotate_top_block]
    type = TransformGenerator
    input = top_block
    transform = ROTATE
    vector_value = '0 0 0'
  []
  [top_block_sidesets]
    type = RenameBoundaryGenerator
    input = rotate_top_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'top_bottom top_back top_right top_front top_left top_top'
  []
  [top_block_id]
    type = SubdomainIDGenerator
    input = top_block_sidesets
    subdomain_id = 1
  []
  [bottom_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 10
    ny = 10
    nz = 2
    xmin = -.5
    xmax = .5
    ymin = -.5
    ymax = .5
    zmin = -.3
    zmax = -.25
    elem_type = HEX8
  []
  [bottom_block_id]
    type = SubdomainIDGenerator
    input = bottom_block
    subdomain_id = 2
  []
  [bottom_block_change_boundary_id]
    type = RenameBoundaryGenerator
    input = bottom_block_id
    old_boundary = '0 1 2 3 4 5'
    new_boundary = '100 101 102 103 104 105'
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'top_block_id bottom_block_change_boundary_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'top_block bottom_block'
  []
  [bottom_right_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = block_rename
    new_boundary = bottom_right
    block = bottom_block
    normal = '1 0 0'
  []
  [bottom_left_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_right_sideset
    new_boundary = bottom_left
    block = bottom_block
    normal = '-1 0 0'
  []
  [bottom_top_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_left_sideset
    new_boundary = bottom_top
    block = bottom_block
    normal = '0 0 1'
  []
  [bottom_bottom_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_top_sideset
    new_boundary = bottom_bottom
    block = bottom_block
    normal = '0  0 -1'
  []
  [bottom_front_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_bottom_sideset
    new_boundary = bottom_front
    block = bottom_block
    normal = '0 1 0'
  []
  [bottom_back_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_front_sideset
    new_boundary = bottom_back
    block = bottom_block
    normal = '0 -1 0'
  []
  [secondary]
    input = bottom_back_sideset
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'top_bottom' # top_back top_left'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'bottom_top'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
  uniform_refine = 0
  allow_renumbering = false
[]
[Variables]
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_3d_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    add_variables = true
    strain = FINITE
    block = '1 2'
    use_automatic_differentiation = false
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_zz'
  []
[]
[Materials]
  [tensor]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1.0e4
    poissons_ratio = 0.0
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
  [tensor_1000]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e5
    poissons_ratio = 0.0
  []
  [stress_1000]
    type = ComputeFiniteStrainElasticStress
    block = '2'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    lm_variable_normal = mortar_normal_lm
    lm_variable_tangential_one = mortar_tangential_lm
    lm_variable_tangential_two = mortar_tangential_3d_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_petrov_galerkin = true
    aux_lm = aux_lm
  []
[]
[Constraints]
  [friction]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    mu = 0.4
    c = 1e4
    c_t = 1.0e4
    friction_lm = mortar_tangential_lm
    friction_lm_dir = mortar_tangential_3d_lm
    weighted_gap_uo = weighted_vel_uo
    weighted_velocities_uo = weighted_vel_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_x
    component = x
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_y
    component = y
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_z
    component = z
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [botz]
    type = DirichletBC
    variable = disp_z
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [topx]
    type = DirichletBC
    variable = disp_x
    boundary = 'top_top'
    value = 0.0
  []
  [topy]
    type = DirichletBC
    variable = disp_y
    boundary = 'top_top'
    value = 0.0
  []
  [topz]
    type = FunctionDirichletBC
    variable = disp_z
    boundary = 'top_top'
    function = '-${starting_point} * sin(2 * pi / 40 * t) + ${offset}'
  []
[]
[Executioner]
  type = Transient
  end_time = .025
  dt = .025
  dtmin = .001
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -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-14                  1e-5'
  l_max_its = 15
  nl_max_its = 30
  nl_rel_tol = 1e-11
  nl_abs_tol = 1e-12
  line_search = 'basic'
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  csv = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'contact'
  [contact]
    type = ContactDOFSetSize
    variable = mortar_normal_lm
    subdomain = 'secondary_lower'
    execute_on = 'nonlinear timestep_end'
  []
[]
[VectorPostprocessors]
  [contact-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_normal_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [frictional-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [frictional-pressure-3d]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_3d_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [tangent_x]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_x
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [tangent_y]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_y
    sort_by = 'id'
    execute_on = NONLINEAR
  []
[]
(modules/contact/test/tests/bouncing-block-contact/variational-frictional.i)
starting_point = 2e-1
# We offset slightly so we avoid the case where the bottom of the secondary block and the top of the
# primary block are perfectly vertically aligned which can cause the backtracking line search some
# issues for a coarse mesh (basic line search handles that fine)
offset = 1e-2
[GlobalParams]
  displacements = 'disp_x disp_y'
  diffusivity = 1e0
  correct_edge_dropping = true
[]
[Mesh]
  [file_mesh]
    type = FileMeshGenerator
    file = long-bottom-block-1elem-blocks-coarse.e
  []
[]
[Variables]
  [disp_x]
    block = '1 2'
    scaling = 1e1
  []
  [disp_y]
    block = '1 2'
    scaling = 1e1
  []
  [contact_action_normal_lm]
    block = 4
    scaling = 1e3
  []
  [contact_action_tangential_lm]
    block = 4
    scaling = 1e2
  []
[]
[ICs]
  [disp_y]
    block = 2
    variable = disp_y
    value = '${fparse starting_point + offset}'
    type = ConstantIC
  []
[]
[Kernels]
  [disp_x]
    type = MatDiffusion
    variable = disp_x
  []
  [disp_y]
    type = MatDiffusion
    variable = disp_y
  []
[]
[AuxVariables]
  [procid]
    family = MONOMIAL
    order = CONSTANT
  []
[]
[AuxKernels]
  [procid]
    type = ProcessorIDAux
    variable = procid
  []
[]
[UserObjects]
  [weighted_velocities_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 10
    secondary_boundary = 20
    primary_subdomain = 3
    secondary_subdomain = 4
    lm_variable_normal = contact_action_normal_lm
    lm_variable_tangential_one = contact_action_tangential_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
    correct_edge_dropping = true
  []
[]
[Constraints]
  [frictional_normal_lm]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 10
    secondary_boundary = 20
    primary_subdomain = 3
    secondary_subdomain = 4
    variable = contact_action_normal_lm
    friction_lm = contact_action_tangential_lm
    disp_x = disp_x
    disp_y = disp_y
    mu = 0.1
    normalize_c = true
    c = 1.0e-2
    c_t = 1.0e-1
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_velocities_uo
    weighted_gap_uo = weighted_velocities_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 10
    secondary_boundary = 20
    primary_subdomain = 3
    secondary_subdomain = 4
    variable = contact_action_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_velocities_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 10
    secondary_boundary = 20
    primary_subdomain = 3
    secondary_subdomain = 4
    variable = contact_action_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_velocities_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 10
    secondary_boundary = 20
    primary_subdomain = 3
    secondary_subdomain = 4
    variable = contact_action_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_velocities_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 10
    secondary_boundary = 20
    primary_subdomain = 3
    secondary_subdomain = 4
    variable = contact_action_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_velocities_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 40
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 40
    value = 0.0
  []
  [topy]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 30
    function = '${starting_point} * cos(2 * pi / 40 * t) + ${offset}'
  []
  [leftx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 50
    function = '1e-2 * t'
  []
[]
[Executioner]
  type = Transient
  end_time = 200
  dt = 5
  dtmin = .1
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount'
  petsc_options_value = 'lu       NONZERO               1e-15'
  l_max_its = 30
  nl_max_its = 25
  line_search = 'none'
  nl_rel_tol = 1e-12
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  hide = procid
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
(modules/contact/test/tests/mortar_dynamics/frictional-mortar-3d-dynamics-light.i)
starting_point = 0.25
offset = 0.00
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[AuxVariables]
  [mortar_tangent_x]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_y]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_z]
    family = LAGRANGE
    order = FIRST
  []
[]
[AuxKernels]
  [friction_x_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_x
   component = 0
   boundary = 'top_bottom'
  []
  [friction_y_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_y
   component = 1
   boundary = 'top_bottom'
  []
  [friction_z_component]
   type = MortarFrictionalPressureVectorAux
   primary_boundary = 'bottom_top'
   secondary_boundary = 'top_bottom'
   tangent_one = mortar_tangential_lm
   tangent_two = mortar_tangential_3d_lm
   variable = mortar_tangent_z
   component = 2
   boundary = 'top_bottom'
  []
[]
[Mesh]
  [top_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 2
    ny = 2
    nz = 1
    xmin = -0.25
    xmax = 0.25
    ymin = -0.25
    ymax = 0.25
    zmin = -0.25
    zmax = 0.25
    elem_type = HEX8
  []
  [rotate_top_block]
    type = TransformGenerator
    input = top_block
    transform = ROTATE
    vector_value = '0 0 0'
  []
  [top_block_sidesets]
    type = RenameBoundaryGenerator
    input = rotate_top_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'top_bottom top_back top_right top_front top_left top_top'
  []
  [top_block_id]
    type = SubdomainIDGenerator
    input = top_block_sidesets
    subdomain_id = 1
  []
  [bottom_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 2
    ny = 2
    nz = 1
    xmin = -.5
    xmax = .5
    ymin = -.5
    ymax = .5
    zmin = -.3
    zmax = -.25
    elem_type = HEX8
  []
  [bottom_block_id]
    type = SubdomainIDGenerator
    input = bottom_block
    subdomain_id = 2
  []
  [bottom_block_change_boundary_id]
    type = RenameBoundaryGenerator
    input = bottom_block_id
    old_boundary = '0 1 2 3 4 5'
    new_boundary = '100 101 102 103 104 105'
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'top_block_id bottom_block_change_boundary_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'top_block bottom_block'
  []
  [bottom_right_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = block_rename
    new_boundary = bottom_right
    block = bottom_block
    normal = '1 0 0'
  []
  [bottom_left_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_right_sideset
    new_boundary = bottom_left
    block = bottom_block
    normal = '-1 0 0'
  []
  [bottom_top_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_left_sideset
    new_boundary = bottom_top
    block = bottom_block
    normal = '0 0 1'
  []
  [bottom_bottom_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_top_sideset
    new_boundary = bottom_bottom
    block = bottom_block
    normal = '0  0 -1'
  []
  [bottom_front_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_bottom_sideset
    new_boundary = bottom_front
    block = bottom_block
    normal = '0 1 0'
  []
  [bottom_back_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_front_sideset
    new_boundary = bottom_back
    block = bottom_block
    normal = '0 -1 0'
  []
  [secondary]
    input = bottom_back_sideset
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'top_bottom' # top_back top_left'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'bottom_top'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
  uniform_refine = 0
  allow_renumbering = false
[]
[Variables]
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_lm]
    block = 'secondary_lower'
    use_dual = true
  []
  [mortar_tangential_3d_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[Physics/SolidMechanics/Dynamic]
  [all]
    add_variables = true
    hht_alpha = 0.0
    newmark_beta = 0.25
    newmark_gamma = 0.5
    mass_damping_coefficient = 0.0
    stiffness_damping_coefficient = 0.1
    displacements = 'disp_x disp_y disp_z'
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_zz'
    block = '1 2'
    strain = FINITE
    density = density
  []
[]
[Materials]
  [density]
    type = GenericConstantMaterial
    block = '1 2'
    prop_names = 'density'
    prop_values = '1.0'
  []
  [tensor]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1.0e4
    poissons_ratio = 0.0
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
  [tensor_1000]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e5
    poissons_ratio = 0.0
  []
  [stress_1000]
    type = ComputeFiniteStrainElasticStress
    block = '2'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable_normal = mortar_normal_lm
    lm_variable_tangential_one = mortar_tangential_lm
    lm_variable_tangential_two = mortar_tangential_3d_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [friction]
    type = ComputeDynamicFrictionalForceLMMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    friction_lm = mortar_tangential_lm
    friction_lm_dir = mortar_tangential_3d_lm
    mu = 0.4
    c = 1e4
    c_t = 1.0e4
    newmark_beta = 0.25
    newmark_gamma = 0.5
    correct_edge_dropping = true
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_x
    component = x
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_y
    component = y
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_z
    component = z
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [botz]
    type = DirichletBC
    variable = disp_z
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [topx]
    type = DirichletBC
    variable = disp_x
    boundary = 'top_top'
    value = 0.0
  []
  [topy]
    type = DirichletBC
    variable = disp_y
    boundary = 'top_top'
    value = 0.0
  []
  [topz]
    type = FunctionDirichletBC
    variable = disp_z
    boundary = 'top_top'
    function = '-${starting_point} * sin(2 * pi / 40 * t) + ${offset}'
  []
[]
[Executioner]
  type = Transient
  end_time = .025
  dt = .025
  dtmin = .001
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -snes_ksp_ew'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount'
  petsc_options_value = 'lu       NONZERO               1e-14'
  nl_rel_tol = 1e-11
  nl_abs_tol = 1e-11
  line_search = 'basic'
  [TimeIntegrator]
    type = NewmarkBeta
    gamma = 0.5
    beta = 0.25
  []
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  csv = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'contact'
  [contact]
    type = ContactDOFSetSize
    variable = mortar_normal_lm
    subdomain = 'secondary_lower'
    execute_on = 'nonlinear timestep_end'
  []
[]
[VectorPostprocessors]
  [contact-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_normal_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [frictional-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [frictional-pressure-3d]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_3d_lm
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [tangent_x]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_x
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
  [tangent_y]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_y
    sort_by = 'id'
    execute_on = TIMESTEP_END
  []
[]
(modules/contact/test/tests/pdass_problems/frictional_bouncing_block.i)
starting_point = 2e-1
offset = 1e-2
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Mesh]
  file = long-bottom-block-1elem-blocks.e
  uniform_refine = 0 # 1,2
  patch_update_strategy = always
  allow_renumbering = false
[]
[Variables]
  [disp_x]
    block = '1 2'
  []
  [disp_y]
    block = '1 2'
  []
  [frictional_normal_lm]
    block = 3
    use_dual = true
  []
  [frictional_tangential_lm]
    block = 3
    use_dual = true
  []
[]
[ICs]
  [disp_y]
    block = 2
    variable = disp_y
    value = '${fparse starting_point + offset}'
    type = ConstantIC
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    strain = FINITE
    generate_output = 'stress_xx stress_yy'
    block = '1 2'
  []
[]
[Materials]
  [elasticity_2]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e3
    poissons_ratio = 0.3
  []
  [elasticity_1]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1e6
    poissons_ratio = 0.3
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1 2'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable_normal = frictional_normal_lm
    lm_variable_tangential_one = frictional_tangential_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    friction_lm = frictional_tangential_lm
    mu = 0.4
    c = 1.0e1
    c_t = 1.0e1
    weighted_gap_uo = weighted_vel_uo
    weighted_velocities_uo = weighted_vel_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = '40'
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = '40'
    value = 0.0
  []
  [topy]
    type = ADFunctionDirichletBC
    variable = disp_y
    boundary = 30
    function = '${starting_point} * cos(2 * pi / 20 * t) + ${offset}'
    preset = false
  []
  [leftx]
    type = ADFunctionDirichletBC
    variable = disp_x
    boundary = 30
    function = '2e-2 * t'
    # function = '0'
    preset = false
  []
[]
[Executioner]
  type = Transient
  end_time = 7 # 70
  dt = 0.25 # 0.1 for finer meshes (uniform_refine)
  dtmin = .01
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -pc_svd_monitor '
                  '-snes_linesearch_monitor'
  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'
  l_max_its = 30
  nl_max_its = 40
  line_search = 'none'
  snesmf_reuse_base = false
  nl_abs_tol = 1e-9
  nl_rel_tol = 1e-9
  l_tol = 1e-07 # Tightening l_tol can help with friction
[]
[Debug]
  show_var_residual_norms = true
[]
[VectorPostprocessors]
  [cont_press]
    type = NodalValueSampler
    variable = frictional_normal_lm
    boundary = '10'
    sort_by = x
    execute_on = FINAL
  []
  [friction]
    type = NodalValueSampler
    variable = frictional_tangential_lm
    boundary = '10'
    sort_by = x
    execute_on = FINAL
  []
[]
[Outputs]
  exodus = false
  [checkfile]
    type = CSV
    show = 'cont_press friction'
    start_time = 0.0
    execute_vector_postprocessors_on = FINAL
  []
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'num_nl cumulative_nli contact cumulative_li num_l'
  [num_nl]
    type = NumNonlinearIterations
  []
  [num_l]
    type = NumLinearIterations
  []
  [cumulative_nli]
    type = CumulativeValuePostprocessor
    postprocessor = num_nl
  []
  [cumulative_li]
    type = CumulativeValuePostprocessor
    postprocessor = num_l
  []
  [contact]
    type = ContactDOFSetSize
    variable = frictional_normal_lm
    subdomain = '3'
    execute_on = 'nonlinear timestep_end'
  []
[]
(modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-fretting-wear-test-projection_angle.i)
starting_point = 0.5e-1
offset = -0.045
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Mesh]
  file = long-bottom-block-1elem-blocks-multiple-projections-lowerd.e
[]
[Variables]
  [disp_x]
    block = '1 2'
  []
  [disp_y]
    block = '1 2'
  []
  [normal_lm]
    block = 3
    use_dual = true
  #  scaling = 1.0e-5
  []
  [frictional_lm]
    block = 3
    use_dual = true
  #  scaling = 1.0e-5
  []
[]
[ICs]
  [disp_y]
    block = 2
    variable = disp_y
    value = '${fparse starting_point + offset}'
    type = ConstantIC
  []
[]
[Kernels]
  [DynamicTensorMechanics]
    displacements = 'disp_x disp_y'
    generate_output = 'stress_xx stress_yy'
    strain = FINITE
    block = '1 2'
    stiffness_damping_coefficient = 1.0
    hht_alpha = 0.0
  []
  [inertia_x]
    type = InertialForce
    variable = disp_x
    velocity = vel_x
    acceleration = accel_x
    beta = 0.25
    gamma = 0.5
    alpha = 0
    eta = 0.0
    block = '1 2'
  []
  [inertia_y]
    type = InertialForce
    variable = disp_y
    velocity = vel_y
    acceleration = accel_y
    beta = 0.25
    gamma = 0.5
    alpha = 0
    eta = 0.0
    block = '1 2'
  []
[]
[Materials]
  [elasticity_2]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e6
    poissons_ratio = 0.3
  []
  [elasticity_1]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1e8
    poissons_ratio = 0.3
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1 2'
  []
  [strain]
    type = ComputeFiniteStrain
    block = '1 2'
  []
  [density]
    type = GenericConstantMaterial
    block = '1 2'
    prop_names = 'density'
    prop_values = '7750'
  []
[]
[AuxVariables]
  [worn_depth]
    block = '3'
  []
  [gap_vel]
    block = '3'
  []
  [vel_x]
    block = '1 2'
  []
  [accel_x]
    block = '1 2'
  []
  [vel_y]
    block = '1 2'
  []
  [accel_y]
    block = '1 2'
  []
  [vel_z]
    block = '1 2'
  []
  [accel_z]
    block = '1 2'
  []
[]
[AuxKernels]
  [gap_vel]
    type = WeightedGapVelAux
    variable = gap_vel
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    disp_x = disp_x
    disp_y = disp_y
    debug_mesh = true
    minimum_projection_angle = 0.0
  []
  [worn_depth]
    type = MortarArchardsLawAux
    variable = worn_depth
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    displacements = 'disp_x disp_y'
    friction_coefficient = 0.5
    energy_wear_coefficient = 1.0e-6
    normal_pressure = normal_lm
    execute_on = 'TIMESTEP_END'
    debug_mesh = true
    minimum_projection_angle = 0.0
  []
  [accel_x]
    type = NewmarkAccelAux
    variable = accel_x
    displacement = disp_x
    velocity = vel_x
    beta = 0.25
    execute_on = 'linear timestep_end'
  []
  [vel_x]
    type = NewmarkVelAux
    variable = vel_x
    acceleration = accel_x
    gamma = 0.5
    execute_on = 'linear timestep_end'
  []
  [accel_y]
    type = NewmarkAccelAux
    variable = accel_y
    displacement = disp_y
    velocity = vel_y
    beta = 0.25
    execute_on = 'linear timestep_end'
  []
  [vel_y]
    type = NewmarkVelAux
    variable = vel_y
    acceleration = accel_y
    gamma = 0.5
    execute_on = 'linear timestep_end'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    secondary_variable = disp_x
    lm_variable_normal = normal_lm
    lm_variable_tangential_one = frictional_lm
    disp_x = disp_x
    disp_y = disp_y
    debug_mesh = true
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeDynamicFrictionalForceLMMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    wear_depth = worn_depth
    c = 1e6
    c_t = 1e6
    normalize_c = true
    mu = 0.5
    friction_lm = frictional_lm
    capture_tolerance = 1.0e-5
    newmark_beta = 0.25
    newmark_gamma = 0.5
    debug_mesh = true
    minimum_projection_angle = 0.0
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    minimum_projection_angle = 0.0
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    minimum_projection_angle = 0.0
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    minimum_projection_angle = 0.0
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    debug_mesh = true
    minimum_projection_angle = 0.0
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 40
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 40
    value = 0.0
  []
  [topy]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 30
    function = '${starting_point} * cos(4.0 * pi / 4 * t) + ${offset}'
  []
  [leftx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 50
    function = '1e-2 * (cos(32.0 * pi / 4 * t) - 1.0)'
  []
[]
[Executioner]
  type = Transient
  end_time = 0.0
  dt = 0.05
  dtmin = .002
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -pc_svd_monitor '
                  '-snes_linesearch_monitor -snes_ksp_ew'
  petsc_options_iname = '-pc_type -pc_factor_mat_solver_type -pc_factor_shift_type -pc_factor_shift_amount'
  petsc_options_value = 'lu       superlu_dist                  NONZERO               1e-15'
  nl_max_its = 40
  l_max_its = 15
  line_search = 'l2'
  snesmf_reuse_base = true
  [TimeIntegrator]
    type = NewmarkBeta
    beta = 0.25
    gamma = 0.5
  []
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  checkpoint = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'num_nl cumulative contact'
  [num_nl]
    type = NumNonlinearIterations
  []
  [cumulative]
    type = CumulativeValuePostprocessor
    postprocessor = num_nl
  []
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = '3'
    execute_on = 'nonlinear timestep_end'
  []
[]
(modules/contact/test/tests/mortar_aux_kernels/frictional-mortar-3d-status.i)
starting_point = 0.04
offset = 0.00
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[AuxVariables]
  [mortar_tangent_x]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_y]
    family = LAGRANGE
    order = FIRST
  []
  [mortar_tangent_z]
    family = LAGRANGE
    order = FIRST
  []
  [frictional_status]
    family = LAGRANGE
    order = FIRST
  []
[]
[AuxKernels]
  [friction_x_component]
    type = MortarFrictionalPressureVectorAux
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    tangent_one = mortar_tangential_lm
    tangent_two = mortar_tangential_3d_lm
    variable = mortar_tangent_x
    component = 0
    boundary = 'top_bottom'
  []
  [friction_y_component]
    type = MortarFrictionalPressureVectorAux
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    tangent_one = mortar_tangential_lm
    tangent_two = mortar_tangential_3d_lm
    variable = mortar_tangent_y
    component = 1
    boundary = 'top_bottom'
  []
  [friction_z_component]
    type = MortarFrictionalPressureVectorAux
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    tangent_one = mortar_tangential_lm
    tangent_two = mortar_tangential_3d_lm
    variable = mortar_tangent_z
    component = 2
    boundary = 'top_bottom'
  []
  [frictional_state]
    type = MortarFrictionalStateAux
    tangent_one = mortar_tangential_lm
    boundary = 'top_bottom'
    contact_pressure = mortar_normal_lm
    variable = frictional_status
    mu = 0.4
  []
[]
[Mesh]
  [top_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 2
    ny = 2
    nz = 1
    xmin = -0.25
    xmax = 0.25
    ymin = -0.25
    ymax = 0.25
    zmin = -0.25
    zmax = 0.25
    elem_type = HEX8
  []
  [rotate_top_block]
    type = TransformGenerator
    input = top_block
    transform = ROTATE
    vector_value = '0 0 0'
  []
  [top_block_sidesets]
    type = RenameBoundaryGenerator
    input = rotate_top_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'top_bottom top_back top_right top_front top_left top_top'
  []
  [top_block_id]
    type = SubdomainIDGenerator
    input = top_block_sidesets
    subdomain_id = 1
  []
  [bottom_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 1
    ny = 1
    nz = 1
    xmin = -.5
    xmax = .5
    ymin = -.5
    ymax = .5
    zmin = -.3
    zmax = -.25
    elem_type = HEX8
  []
  [bottom_block_id]
    type = SubdomainIDGenerator
    input = bottom_block
    subdomain_id = 2
  []
  [bottom_block_change_boundary_id]
    type = RenameBoundaryGenerator
    input = bottom_block_id
    old_boundary = '0 1 2 3 4 5'
    new_boundary = '100 101 102 103 104 105'
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'top_block_id bottom_block_change_boundary_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'top_block bottom_block'
  []
  [bottom_right_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = block_rename
    new_boundary = bottom_right
    block = bottom_block
    normal = '1 0 0'
  []
  [bottom_left_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_right_sideset
    new_boundary = bottom_left
    block = bottom_block
    normal = '-1 0 0'
  []
  [bottom_top_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_left_sideset
    new_boundary = bottom_top
    block = bottom_block
    normal = '0 0 1'
  []
  [bottom_bottom_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_top_sideset
    new_boundary = bottom_bottom
    block = bottom_block
    normal = '0  0 -1'
  []
  [bottom_front_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_bottom_sideset
    new_boundary = bottom_front
    block = bottom_block
    normal = '0 1 0'
  []
  [bottom_back_sideset]
    type = SideSetsAroundSubdomainGenerator
    input = bottom_front_sideset
    new_boundary = bottom_back
    block = bottom_block
    normal = '0 -1 0'
  []
  [secondary]
    input = bottom_back_sideset
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'top_bottom' # top_back top_left'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'bottom_top'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
  uniform_refine = 0
  allow_renumbering = false
[]
[Variables]
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
    scaling = 1.0e2
  []
  [mortar_tangential_lm]
    block = 'secondary_lower'
    use_dual = true
    scaling = 1.0e2
  []
  [mortar_tangential_3d_lm]
    block = 'secondary_lower'
    use_dual = true
    scaling = 1.0e2
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    add_variables = true
    strain = FINITE
    block = '1 2'
    use_automatic_differentiation = false
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_zz'
  []
[]
[Materials]
  [tensor]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1.0e2
    # We should try with nonzero Poisson ratio
    poissons_ratio = 0.0
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
  [tensor_1000]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e5
    poissons_ratio = 0.0
  []
  [stress_1000]
    type = ComputeFiniteStrainElasticStress
    block = '2'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    secondary_variable = disp_x
    lm_variable_normal = mortar_normal_lm
    lm_variable_tangential_one = mortar_tangential_lm
    lm_variable_tangential_two = mortar_tangential_3d_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
  []
[]
[Constraints]
  [friction]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    mu = 0.4
    c = 1e1
    c_t = 1.0e1
    friction_lm = mortar_tangential_lm
    friction_lm_dir = mortar_tangential_3d_lm
    weighted_gap_uo = weighted_vel_uo
    weighted_velocities_uo = weighted_vel_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_x
    component = x
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_y
    component = y
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_dir_z]
    type = TangentialMortarMechanicalContact
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = mortar_tangential_3d_lm
    secondary_variable = disp_z
    component = z
    direction = direction_2
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [botz]
    type = DirichletBC
    variable = disp_z
    boundary = 'bottom_left bottom_right bottom_front bottom_back'
    value = 0.0
  []
  [topx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 'top_top'
    function = '0.16*t'
  []
  [topy]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 'top_top'
    function = '0.1*t'
  []
  [topz]
    type = FunctionDirichletBC
    variable = disp_z
    boundary = 'top_top'
    function = '-${starting_point} * sin(2 * pi / 0.4 * t) + ${offset}'
  []
[]
[Executioner]
  type = Transient
  end_time = 0.1
  dt = .02
  dtmin = .02
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -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-13                  1e-7'
  l_max_its = 15
  nl_max_its = 90
  nl_rel_tol = 1e-11
  nl_abs_tol = 1e-11
  line_search = 'basic'
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'contact'
  [contact]
    type = ContactDOFSetSize
    variable = mortar_normal_lm
    subdomain = 'secondary_lower'
    execute_on = 'nonlinear timestep_end'
  []
[]
[VectorPostprocessors]
  [contact-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_normal_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [frictional-pressure]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [frictional-pressure-3d]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangential_3d_lm
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [tangent_x]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_x
    sort_by = 'id'
    execute_on = NONLINEAR
  []
  [tangent_y]
    type = NodalValueSampler
    block = secondary_lower
    variable = mortar_tangent_y
    sort_by = 'id'
    execute_on = NONLINEAR
  []
[]
(modules/contact/test/tests/mortar_dynamics/block-dynamics-friction-creep.i)
starting_point = 1e-1
offset = -0.095
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Mesh]
  file = long-bottom-block-1elem-blocks.e
[]
[Variables]
  [normal_lm]
    block = 3
    use_dual = true
  []
  [frictional_lm]
    block = 3
    use_dual = true
  []
[]
[AuxVariables]
  [creep_strain_xx]
    order = CONSTANT
    family = MONOMIAL
    block = '2'
  []
  [creep_strain_yy]
    order = CONSTANT
    family = MONOMIAL
    block = '2'
  []
  [creep_strain_xy]
    order = CONSTANT
    family = MONOMIAL
    block = '2'
  []
[]
[AuxKernels]
  [creep_strain_xx]
    type = RankTwoAux
    rank_two_tensor = creep_strain
    variable = creep_strain_xx
    index_i = 0
    index_j = 0
    block = '2'
  []
  [creep_strain_yy]
    type = RankTwoAux
    rank_two_tensor = creep_strain
    variable = creep_strain_yy
    index_i = 1
    index_j = 1
    block = '2'
  []
  [creep_strain_xy]
    type = RankTwoAux
    rank_two_tensor = creep_strain
    variable = creep_strain_xy
    index_i = 0
    index_j = 1
    block = '2'
  []
[]
[ICs]
  [disp_y]
    block = 2
    variable = disp_y
    value = '${fparse starting_point + offset}'
    type = ConstantIC
  []
[]
[Physics/SolidMechanics/Dynamic]
  [all]
    add_variables = true
    hht_alpha = 0.0
    newmark_beta = 0.25
    newmark_gamma = 0.5
    mass_damping_coefficient = 0.0
    stiffness_damping_coefficient = 0.01
    displacements = 'disp_x disp_y'
    generate_output = 'stress_xx stress_yy'
    block = '1 2'
    strain = FINITE
  []
[]
[Materials]
  [elasticity_2]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e6
    poissons_ratio = 0.3
  []
  [elasticity_1]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1e8
    poissons_ratio = 0.3
  []
  [multiple_inelastic]
    type = ComputeMultipleInelasticStress
    inelastic_models = 'creep'
    block = '2'
  []
  [creep]
    type = PowerLawCreepStressUpdate
    coefficient = 1.0e-23 # 10e-24
    n_exponent = 4
    activation_energy = 0
    block = '2'
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
  [density]
    type = GenericConstantMaterial
    block = '1 2'
    prop_names = 'density'
    prop_values = '775'
  []
[]
# User object provides the contact force (e.g. LM)
# for the application of the generalized force
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable_normal = normal_lm
    lm_variable_tangential_one = frictional_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeDynamicFrictionalForceLMMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    friction_lm = frictional_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    c = 1e4
    c_t = 1e4
    mu = 0.5
    interpolate_normals = false
    newmark_beta = 0.25
    newmark_gamma = 0.5
    capture_tolerance = 1e-04
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 40
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 40
    value = 0.0
  []
  [topy]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 30
    function = '${starting_point} * cos(2 * pi / 4 * t) + ${offset}'
  []
  [leftx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 30 # 50
    function =  '1e-2*t' #'0.1 *sin(2 * pi / 12 * t)'
  []
[]
[Executioner]
  type = Transient
  end_time = 0.25
  dt = 0.05
  dtmin = 0.05
  solve_type = 'PJFNK'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -pc_svd_monitor '
                  '-snes_linesearch_monitor -snes_ksp_ew'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -mat_mffd_err '
  petsc_options_value = 'lu       NONZERO               1e-15                   1e-5'
  nl_max_its = 50
  line_search = 'none'
  snesmf_reuse_base = false
  [TimeIntegrator]
    type = NewmarkBeta
    beta = 0.25
    gamma = 0.5
  []
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  checkpoint = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'num_nl cumulative contact'
  [num_nl]
    type = NumNonlinearIterations
  []
  [cumulative]
    type = CumulativeValuePostprocessor
    postprocessor = num_nl
  []
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = '3'
    execute_on = 'nonlinear timestep_end'
  []
[]
(modules/contact/test/tests/pdass_problems/cylinder_friction.i)
[GlobalParams]
  volumetric_locking_correction = true
  displacements = 'disp_x disp_y'
[]
[Mesh]
  [input_file]
    type = FileMeshGenerator
    file = hertz_cyl_coarser.e
  []
  [secondary]
    type = LowerDBlockFromSidesetGenerator
    new_block_id = 10001
    new_block_name = 'secondary_lower'
    sidesets = '3'
    input = input_file
  []
  [primary]
    type = LowerDBlockFromSidesetGenerator
    new_block_id = 10000
    sidesets = '2'
    new_block_name = 'primary_lower'
    input = secondary
  []
[]
[Problem]
  type = ReferenceResidualProblem
  extra_tag_vectors = 'ref'
  reference_vector = 'ref'
[]
[Variables]
  [disp_x]
  []
  [disp_y]
  []
  [frictionless_normal_lm]
    order = FIRST
    family = LAGRANGE
    block = 'secondary_lower'
    use_dual = true
  []
  [tangential_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[AuxVariables]
  [stress_xx]
    order = CONSTANT
    family = MONOMIAL
  []
  [stress_yy]
    order = CONSTANT
    family = MONOMIAL
  []
  [stress_xy]
    order = CONSTANT
    family = MONOMIAL
  []
  [saved_x]
  []
  [saved_y]
  []
  [diag_saved_x]
  []
  [diag_saved_y]
  []
[]
[Functions]
  [disp_ramp_vert]
    type = PiecewiseLinear
    x = '0. 1. 3.5'
    y = '0. -0.020 -0.020'
  []
  [disp_ramp_horz]
    type = PiecewiseLinear
    x = '0. 1. 3.5'
    y = '0. 0.0 0.015'
  []
[]
[Kernels]
  [TensorMechanics]
    use_displaced_mesh = true
    save_in = 'saved_x saved_y'
    extra_vector_tags = 'ref'
    block = '1 2 3 4 5 6 7'
  []
[]
[AuxKernels]
  [stress_xx]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_xx
    index_i = 0
    index_j = 0
    execute_on = timestep_end
    block = '1 2 3 4 5 6 7'
  []
  [stress_yy]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_yy
    index_i = 1
    index_j = 1
    execute_on = timestep_end
    block = '1 2 3 4 5 6 7'
  []
  [stress_xy]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_xy
    index_i = 0
    index_j = 1
    execute_on = timestep_end
    block = '1 2 3 4 5 6 7'
  []
[]
[Postprocessors]
  [bot_react_x]
    type = NodalSum
    variable = saved_x
    boundary = 1
  []
  [bot_react_y]
    type = NodalSum
    variable = saved_y
    boundary = 1
  []
  [top_react_x]
    type = NodalSum
    variable = saved_x
    boundary = 4
  []
  [top_react_y]
    type = NodalSum
    variable = saved_y
    boundary = 4
  []
  [_dt]
    type = TimestepSize
  []
  [num_lin_it]
    type = NumLinearIterations
  []
  [num_nonlin_it]
    type = NumNonlinearIterations
  []
[]
[BCs]
  [side_x]
    type = DirichletBC
    variable = disp_y
    boundary = '1 2'
    value = 0.0
  []
  [bot_y]
    type = DirichletBC
    variable = disp_x
    boundary = '1 2'
    value = 0.0
  []
  [top_y_disp]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 4
    function = disp_ramp_vert
  []
  [top_x_disp]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 4
    function = disp_ramp_horz
  []
[]
[Materials]
  [stuff1_elas_tens]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1e10
    poissons_ratio = 0.0
  []
  [stuff1_strain]
    type = ComputeFiniteStrain
    block = '1'
  []
  [stuff1_stress]
    type = ComputeFiniteStrainElasticStress
    block = '1'
  []
  [stuff2_elas_tens]
    type = ComputeIsotropicElasticityTensor
    block = '2 3 4 5 6 7'
    youngs_modulus = 1e6
    poissons_ratio = 0.3
  []
  [stuff2_strain]
    type = ComputeFiniteStrain
    block = '2 3 4 5 6 7'
  []
  [stuff2_stress]
    type = ComputeFiniteStrainElasticStress
    block = '2 3 4 5 6 7'
  []
[]
[Executioner]
  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.3 # 3.5
  l_tol = 1e-4
  dt = 0.1
  dtmin = 0.001
[]
[Preconditioning]
  [SMP]
    type = SMP
    full = true
  []
[]
[VectorPostprocessors]
  [x_disp]
    type = NodalValueSampler
    variable = disp_x
    boundary = '3 4'
    sort_by = id
  []
  [y_disp]
    type = NodalValueSampler
    variable = disp_y
    boundary = '3 4'
    sort_by = id
  []
  [cont_press]
    type = NodalValueSampler
    variable = frictionless_normal_lm
    boundary = '3'
    sort_by = id
  []
  [friction]
    type = NodalValueSampler
    variable = frictionless_normal_lm
    boundary = '3'
    sort_by = id
  []
[]
[Outputs]
  print_linear_residuals = true
  perf_graph = true
  exodus = false
  csv = false
  [console]
    type = Console
    max_rows = 5
  []
  [chkfile]
    type = CSV
    show = 'x_disp y_disp cont_press friction'
    file_base = cylinder_friction_check
    create_final_symlink = true
    execute_on = 'FINAL'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 2
    secondary_boundary = 3
    primary_subdomain = 10000
    secondary_subdomain = 10001
    lm_variable_normal = frictionless_normal_lm
    lm_variable_tangential_one = tangential_lm
    secondary_variable = disp_x
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeFrictionalForceLMMechanicalContact
    primary_boundary = 2
    secondary_boundary = 3
    primary_subdomain = 10000
    secondary_subdomain = 10001
    variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    friction_lm = tangential_lm
    mu = 0.4
    c_t = 1.0e5
    c = 1.0e6
    weighted_gap_uo = weighted_vel_uo
    weighted_velocities_uo = weighted_vel_uo
  []
  [x]
    type = NormalMortarMechanicalContact
    primary_boundary = '2'
    secondary_boundary = '3'
    primary_subdomain = '10000'
    secondary_subdomain = '10001'
    variable = frictionless_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [y]
    type = NormalMortarMechanicalContact
    primary_boundary = '2'
    secondary_boundary = '3'
    primary_subdomain = '10000'
    secondary_subdomain = '10001'
    variable = frictionless_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 2
    secondary_boundary = 3
    primary_subdomain = 10000
    secondary_subdomain = 10001
    variable = tangential_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 2
    secondary_boundary = 3
    primary_subdomain = 10000
    secondary_subdomain = 10001
    variable = tangential_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
(modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-fretting-wear-test.i)
starting_point = 0.5e-1
offset = -0.045
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Mesh]
  file = long-bottom-block-1elem-blocks.e
[]
[Variables]
  [disp_x]
    block = '1 2'
  []
  [disp_y]
    block = '1 2'
  []
  [normal_lm]
    block = 3
    use_dual = true
  #  scaling = 1.0e-5
  []
  [frictional_lm]
    block = 3
    use_dual = true
    scaling = 1.0e-5
  []
[]
[ICs]
  [disp_y]
    block = 2
    variable = disp_y
    value = '${fparse starting_point + offset}'
    type = ConstantIC
  []
[]
[Kernels]
  [DynamicTensorMechanics]
    displacements = 'disp_x disp_y'
    generate_output = 'stress_xx stress_yy'
    strain = FINITE
    block = '1 2'
    stiffness_damping_coefficient = 0.04
    hht_alpha = 0.0
  []
  [inertia_x]
    type = InertialForce
    variable = disp_x
    velocity = vel_x
    acceleration = accel_x
    beta = 0.25
    gamma = 0.5
    alpha = 0
    eta = 0.0
    block = '1 2'
  []
  [inertia_y]
    type = InertialForce
    variable = disp_y
    velocity = vel_y
    acceleration = accel_y
    beta = 0.25
    gamma = 0.5
    alpha = 0
    eta = 0.0
    block = '1 2'
  []
[]
[Materials]
  [elasticity_2]
    type = ComputeIsotropicElasticityTensor
    block = '2'
    youngs_modulus = 1e6
    poissons_ratio = 0.3
  []
  [elasticity_1]
    type = ComputeIsotropicElasticityTensor
    block = '1'
    youngs_modulus = 1e8
    poissons_ratio = 0.3
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = '1 2'
  []
  [strain]
    type = ComputeFiniteStrain
    block = '1 2'
  []
  [density]
    type = GenericConstantMaterial
    block = '1 2'
    prop_names = 'density'
    prop_values = '7750'
  []
[]
[AuxVariables]
  [worn_depth]
    block = '3'
  []
  [gap_vel]
    block = '3'
  []
  [vel_x]
    block = '1 2'
  []
  [accel_x]
    block = '1 2'
  []
  [vel_y]
    block = '1 2'
  []
  [accel_y]
    block = '1 2'
  []
  [vel_z]
    block = '1 2'
  []
  [accel_z]
    block = '1 2'
  []
[]
[AuxKernels]
  [gap_vel]
    type = WeightedGapVelAux
    variable = gap_vel
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    disp_x = disp_x
    disp_y = disp_y
  []
  [worn_depth]
    type = MortarArchardsLawAux
    variable = worn_depth
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    displacements = 'disp_x disp_y'
    friction_coefficient = 0.5
    energy_wear_coefficient = 1.0e-6
    normal_pressure = normal_lm
    execute_on = 'TIMESTEP_END'
  []
  [accel_x]
    type = NewmarkAccelAux
    variable = accel_x
    displacement = disp_x
    velocity = vel_x
    beta = 0.25
    execute_on = 'linear timestep_end'
  []
  [vel_x]
    type = NewmarkVelAux
    variable = vel_x
    acceleration = accel_x
    gamma = 0.5
    execute_on = 'linear timestep_end'
  []
  [accel_y]
    type = NewmarkAccelAux
    variable = accel_y
    displacement = disp_y
    velocity = vel_y
    beta = 0.25
    execute_on = 'linear timestep_end'
  []
  [vel_y]
    type = NewmarkVelAux
    variable = vel_y
    acceleration = accel_y
    gamma = 0.5
    execute_on = 'linear timestep_end'
  []
[]
[UserObjects]
  [weighted_vel_uo]
    type = LMWeightedVelocitiesUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    secondary_variable = disp_x
    lm_variable_normal = normal_lm
    lm_variable_tangential_one = frictional_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeDynamicFrictionalForceLMMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    wear_depth = worn_depth
    c = 1e6
    c_t = 1e6
    normalize_c = true
    mu = 0.5
    friction_lm = frictional_lm
    capture_tolerance = 1.0e-5
    newmark_beta = 0.25
    newmark_gamma = 0.5
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_vel_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    weighted_gap_uo = weighted_vel_uo
  []
  [tangential_x]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
  [tangential_y]
    type = TangentialMortarMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = frictional_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_velocities_uo = weighted_vel_uo
  []
[]
[BCs]
  [botx]
    type = DirichletBC
    variable = disp_x
    boundary = 40
    value = 0.0
  []
  [boty]
    type = DirichletBC
    variable = disp_y
    boundary = 40
    value = 0.0
  []
  [topy]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 30
    function = '${starting_point} * cos(4.0 * pi / 4 * t) + ${offset}'
  []
  [leftx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 50
    function = '1e-5 * (cos(32.0 * pi / 4 * t) - 1.0)'
  []
[]
[Executioner]
  type = Transient
  end_time = 0.5
  dt = 0.05
  dtmin = .002
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -pc_svd_monitor '
                  '-snes_linesearch_monitor -snes_ksp_ew'
  petsc_options_iname = '-pc_type -pc_factor_mat_solver_type -pc_factor_shift_type -pc_factor_shift_amount'
  petsc_options_value = 'lu       superlu_dist                  NONZERO               1e-15'
  nl_max_its = 40
  l_max_its = 15
  line_search = none
  snesmf_reuse_base = true
  [TimeIntegrator]
    type = NewmarkBeta
    beta = 0.25
    gamma = 0.5
  []
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  active = 'contact'
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = '3'
    execute_on = 'nonlinear timestep_end'
  []
[]