- 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_variableThe 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.
 - 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.
 
LMWeightedGapUserObject
Description
The LMWeightedGapUserObject object provides the Lagrange multiplier and interpolation function for the enforcement of mortar mechanical constraints. In essence, the Lagrange multiplier is provided to NormalMortarMechanicalContact to enforce the non-penetration constraint. 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
 - 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
 - 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/bouncing-block-contact/frictionless-weighted-gap-mixed-basis.i)
 - (modules/contact/test/tests/simple_contact/two_block_compress/two_equal_blocks_compress_2d.i)
 - (modules/contact/test/tests/simple_contact/two_block_compress/two_equal_blocks_compress_2d_pg.i)
 - (modules/combined/test/tests/nodal_patch_recovery/npr_with_lower_domains.i)
 - (modules/contact/test/tests/3d-mortar-contact/frictionless-mortar-3d.i)
 - (modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-vel.i)
 - (modules/contact/test/tests/sliding_block/edge_dropping/two_equal_blocks_slide_2d.i)
 - (modules/contact/test/tests/3d-mortar-contact/frictionless-mortar-3d_pg.i)
 - (modules/combined/test/tests/gap_heat_transfer_mortar/small-2d/small.i)
 - (modules/combined/test/tests/stateful_mortar_constraints/stateful_mortar_npr.i)
 - (modules/contact/test/tests/bouncing-block-contact/frictionless-weighted-gap.i)
 - (modules/contact/test/tests/mortar_dynamics/block-dynamics-reference.i)
 - (modules/contact/test/tests/simple_contact/two_block_compress/two_equal_blocks_compress_3d.i)
 - (modules/combined/test/tests/gap_heat_transfer_mortar/small-2d-rz/small.i)
 - (modules/contact/test/tests/bouncing-block-contact/mixed-weighted-gap-swapped.i)
 - (modules/contact/test/tests/sliding_block/edge_dropping/two_equal_blocks_slide_3d.i)
 - (modules/combined/test/tests/gap_heat_transfer_mortar/finite-2d/finite_rr.i)
 - (modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-wear.i)
 - (modules/contact/test/tests/3d-mortar-contact/frictionless-mortar-3d-test-derivative-trimming.i)
 - (modules/combined/test/tests/gap_heat_transfer_mortar/finite-2d/finite.i)
 - (modules/contact/test/tests/mortar_dynamics/block-dynamics.i)
 - (modules/contact/test/tests/simple_contact/two_block_compress/two_equal_blocks_compress_3d_pg.i)
 - (modules/combined/test/tests/gap_heat_transfer_mortar/finite-2d-rz/finite.i)
 
Child Objects
(modules/contact/test/tests/bouncing-block-contact/frictionless-weighted-gap-mixed-basis.i)
starting_point = 2e-1
offset = 1e-2
[GlobalParams]
  displacements = 'disp_x disp_y'
  diffusivity = 1e0
  scaling = 1e0
[]
[Mesh]
  file = long-bottom-block-1elem-blocks.e
  second_order = true
  patch_update_strategy = always
[]
[Variables]
  [./disp_x]
    block = '1 2'
    order = SECOND
  [../]
  [./disp_y]
    block = '1 2'
    order = SECOND
  [../]
  [./normal_lm]
    block = 3
  [../]
[]
# [AuxVariables]
#   [pid]
#     order = CONSTANT
#     family = MONOMIAL
#   []
# []
# [AuxKernels]
#   [pid]
#     type = ProcessorIDAux
#     variable = pid
#   []
# []
[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_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [./weighted_gap_lm]
    type = ComputeWeightedGapLMMechanicalContact
    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 = 1
    weighted_gap_uo = weighted_gap_uo
  [../]
  [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_gap_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_gap_uo
  []
[]
[BCs]
  [./botx]
    type = DirichletBC
    variable = disp_x
    boundary = 40
    value = 0.0
    preset = false
  [../]
  [./boty]
    type = DirichletBC
    variable = disp_y
    boundary = 40
    value = 0.0
    preset = false
  [../]
  [./topy]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 30
    function = '${starting_point} * cos(2 * pi / 40 * t) + ${offset}'
    preset = false
  [../]
  [./leftx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 50
    function = '1e-2 * t'
    preset = false
  [../]
[]
[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'
  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
  abort_on_solve_fail = true
  nl_rel_tol = 1e-12
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = 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/simple_contact/two_block_compress/two_equal_blocks_compress_2d.i)
[GlobalParams]
  displacements = 'disp_x disp_y'
  volumetric_locking_correction = true
[]
[Mesh]
  [left_block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = -1.0
    xmax = 0.0
    ymin = -0.5
    ymax = 0.5
    nx = 4
    ny = 4
    elem_type = QUAD4
  []
  [left_block_sidesets]
    type = RenameBoundaryGenerator
    input = left_block
    old_boundary = '0 1 2 3'
    new_boundary = '10 11 12 13'
  []
  [left_block_id]
    type = SubdomainIDGenerator
    input = left_block_sidesets
    subdomain_id = 1
  []
  [right_block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0.0
    xmax = 1.0
    ymin = -0.5
    ymax = 0.5
    nx = 5
    ny = 5
    elem_type = QUAD4
  []
  [right_block_sidesets]
    type = RenameBoundaryGenerator
    input = right_block
    old_boundary = '0 1 2 3'
    new_boundary = '20 21 22 23'
  []
  [right_block_id]
    type = SubdomainIDGenerator
    input = right_block_sidesets
    subdomain_id = 2
  []
  [combined_mesh]
    type = MeshCollectionGenerator
    inputs = 'left_block_id right_block_id'
  []
  [left_lower]
    type = LowerDBlockFromSidesetGenerator
    input = combined_mesh
    sidesets = '11'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [right_lower]
    type = LowerDBlockFromSidesetGenerator
    input = left_lower
    sidesets = '23'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
[]
[Variables]
  [normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    strain = FINITE
    incremental = true
    add_variables = true
    block = '1 2'
  []
[]
[Functions]
  [horizontal_movement]
    type = PiecewiseLinear
    x = '0 1.0'
    y = '0 0.4'
  []
  [vertical_movement]
    type = PiecewiseLinear
    x = '0 1.0'
    y = '0 0'
  []
[]
[BCs]
  [push_left_x]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 13
    function = horizontal_movement
  []
  [fix_right_x]
    type = DirichletBC
    variable = disp_x
    boundary = 21
    value = 0.0
  []
  [fix_right_y]
    type = DirichletBC
    variable = disp_y
    boundary = 21
    value = 0.0
  []
  [push_left_y]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 13
    function = vertical_movement
  []
[]
[Materials]
  [elasticity_tensor_left]
    type = ComputeIsotropicElasticityTensor
    block = 1
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_left]
    type = ComputeFiniteStrainElasticStress
    block = 1
  []
  [elasticity_tensor_right]
    type = ComputeIsotropicElasticityTensor
    block = 2
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_right]
    type = ComputeFiniteStrainElasticStress
    block = 2
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    correct_edge_dropping = true
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [normal_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
[]
[Preconditioning]
  [SMP]
    type = SMP
    full = true
  []
[]
[Executioner]
  type = Transient
  solve_type = 'PJFNK'
  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-10'
  line_search = 'none'
  dt = 0.1
  dtmin = 0.01
  end_time = 1.0
  l_max_its = 20
  nl_max_its = 20
  nl_rel_tol = 1e-8
  nl_abs_tol = 1e-10
[]
[Outputs]
  csv = true
  execute_on = 'FINAL'
[]
[Postprocessors]
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = 'secondary_lower'
  []
  [normal_lm]
    type = ElementAverageValue
    variable = normal_lm
    block = 'secondary_lower'
  []
  [avg_disp_x]
    type = ElementAverageValue
    variable = disp_x
    block = '1 2'
  []
  [avg_disp_y]
    type = ElementAverageValue
    variable = disp_y
    block = '1 2'
  []
  [max_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
  []
  [max_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
  []
  [min_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
    value_type = min
  []
  [min_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
    value_type = min
  []
[]
(modules/contact/test/tests/simple_contact/two_block_compress/two_equal_blocks_compress_2d_pg.i)
[GlobalParams]
  displacements = 'disp_x disp_y'
  volumetric_locking_correction = true
[]
[Mesh]
  [left_block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = -1.0
    xmax = 0.0
    ymin = -0.5
    ymax = 0.5
    nx = 4
    ny = 4
    elem_type = QUAD4
  []
  [left_block_sidesets]
    type = RenameBoundaryGenerator
    input = left_block
    old_boundary = '0 1 2 3'
    new_boundary = '10 11 12 13'
  []
  [left_block_id]
    type = SubdomainIDGenerator
    input = left_block_sidesets
    subdomain_id = 1
  []
  [right_block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0.0
    xmax = 1.0
    ymin = -0.5
    ymax = 0.5
    nx = 5
    ny = 5
    elem_type = QUAD4
  []
  [right_block_sidesets]
    type = RenameBoundaryGenerator
    input = right_block
    old_boundary = '0 1 2 3'
    new_boundary = '20 21 22 23'
  []
  [right_block_id]
    type = SubdomainIDGenerator
    input = right_block_sidesets
    subdomain_id = 2
  []
  [combined_mesh]
    type = MeshCollectionGenerator
    inputs = 'left_block_id right_block_id'
  []
  [left_lower]
    type = LowerDBlockFromSidesetGenerator
    input = combined_mesh
    sidesets = '11'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [right_lower]
    type = LowerDBlockFromSidesetGenerator
    input = left_lower
    sidesets = '23'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
[]
[Variables]
  [normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[AuxVariables]
  [aux_lm]
    block = 'secondary_lower'
    use_dual = false
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    strain = FINITE
    incremental = true
    add_variables = true
    block = '1 2'
  []
[]
[Functions]
  [horizontal_movement]
    type = PiecewiseLinear
    x = '0 1.0'
    y = '0 0.4'
  []
  [vertical_movement]
    type = PiecewiseLinear
    x = '0 1.0'
    y = '0 0'
  []
[]
[BCs]
  [push_left_x]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 13
    function = horizontal_movement
  []
  [fix_right_x]
    type = DirichletBC
    variable = disp_x
    boundary = 21
    value = 0.0
  []
  [fix_right_y]
    type = DirichletBC
    variable = disp_y
    boundary = 21
    value = 0.0
  []
  [push_left_y]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 13
    function = vertical_movement
  []
[]
[Materials]
  [elasticity_tensor_left]
    type = ComputeIsotropicElasticityTensor
    block = 1
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_left]
    type = ComputeFiniteStrainElasticStress
    block = 1
  []
  [elasticity_tensor_right]
    type = ComputeIsotropicElasticityTensor
    block = 2
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_right]
    type = ComputeFiniteStrainElasticStress
    block = 2
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    correct_edge_dropping = true
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_petrov_galerkin = true
    aux_lm = aux_lm
  []
[]
[Constraints]
  [normal_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
[]
[Preconditioning]
  [SMP]
    type = SMP
    full = true
  []
[]
[Executioner]
  type = Transient
  solve_type = 'PJFNK'
  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-10'
  line_search = 'none'
  dt = 0.1
  dtmin = 0.01
  end_time = 1.0
  l_max_its = 20
  nl_max_its = 20
  nl_rel_tol = 1e-8
  nl_abs_tol = 1e-10
[]
[Outputs]
  csv = true
  execute_on = 'FINAL'
[]
[Postprocessors]
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = 'secondary_lower'
  []
  [normal_lm]
    type = ElementAverageValue
    variable = normal_lm
    block = 'secondary_lower'
  []
  [avg_disp_x]
    type = ElementAverageValue
    variable = disp_x
    block = '1 2'
  []
  [avg_disp_y]
    type = ElementAverageValue
    variable = disp_y
    block = '1 2'
  []
  [max_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
  []
  [max_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
  []
  [min_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
    value_type = min
  []
  [min_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
    value_type = min
  []
[]
(modules/combined/test/tests/nodal_patch_recovery/npr_with_lower_domains.i)
E_block = 1e7
E_plank = 1e7
elem = QUAD4
order = FIRST
[Mesh]
  patch_size = 80
  patch_update_strategy = auto
  [plank]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = -0.3
    xmax = 0.3
    ymin = -10
    ymax = 10
    nx = 2
    ny = 67
    elem_type = ${elem}
    boundary_name_prefix = plank
  []
  [plank_id]
    type = SubdomainIDGenerator
    input = plank
    subdomain_id = 1
  []
  [block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0.31
    xmax = 0.91
    ymin = 7.7
    ymax = 8.5
    nx = 3
    ny = 4
    elem_type = ${elem}
    boundary_name_prefix = block
    boundary_id_offset = 10
  []
  [block_id]
    type = SubdomainIDGenerator
    input = block
    subdomain_id = 2
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'plank_id block_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'plank block'
  []
  [secondary]
    input = block_rename
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'block_left'
    new_block_id = '30'
    new_block_name = 'frictionless_secondary_subdomain'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'plank_right'
    new_block_id = '20'
    new_block_name = 'frictionless_primary_subdomain'
  []
[]
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Variables]
  [disp_x]
    order = ${order}
    block = 'plank block'
    scaling = '${fparse 2.0 / (E_plank + E_block)}'
  []
  [disp_y]
    order = ${order}
    block = 'plank block'
    scaling = '${fparse 2.0 / (E_plank + E_block)}'
  []
  [temp]
    order = ${order}
    block = 'plank block'
    scaling = 1e-1
  []
  [thermal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    scaling = 1e-7
  []
  [frictionless_normal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    use_dual = true
  []
[]
[AuxVariables]
  [stress_xx]
    order = FIRST
    family = MONOMIAL
    block = 'plank block'
  []
  [stress_yy]
    order = FIRST
    family = MONOMIAL
    block = 'plank block'
  []
  [stress_xx_recovered]
    order = FIRST
    family = LAGRANGE
    block = 'plank block'
  []
  [stress_yy_recovered]
    order = FIRST
    family = LAGRANGE
    block = 'plank block'
  []
[]
[AuxKernels]
  [stress_xx]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_xx
    index_i = 0
    index_j = 0
    execute_on = 'timestep_end'
    block = 'plank block'
  []
  [stress_yy]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_yy
    index_i = 1
    index_j = 1
    execute_on = 'timestep_end'
    block = 'plank block'
  []
  [stress_xx_recovered]
    type = NodalPatchRecoveryAux
    variable = stress_xx_recovered
    nodal_patch_recovery_uo = stress_xx_patch
    execute_on = 'TIMESTEP_END'
    block = 'plank block'
  []
  [stress_yy_recovered]
    type = NodalPatchRecoveryAux
    variable = stress_yy_recovered
    nodal_patch_recovery_uo = stress_yy_patch
    execute_on = 'TIMESTEP_END'
    block = 'plank block'
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [action]
    generate_output = 'stress_zz vonmises_stress hydrostatic_stress strain_xx strain_yy strain_zz'
    block = 'plank block'
    use_automatic_differentiation = false
    strain = FINITE
  []
[]
[Kernels]
  [hc]
    type = HeatConduction
    variable = temp
    use_displaced_mesh = true
    block = 'plank block'
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    lm_variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
  [stress_xx_patch]
    type = NodalPatchRecoveryMaterialProperty
    patch_polynomial_order = FIRST
    property = 'stress'
    component = '0 0'
    execute_on = 'NONLINEAR TIMESTEP_END'
    block = 'plank block'
  []
  [stress_yy_patch]
    type = NodalPatchRecoveryMaterialProperty
    patch_polynomial_order = FIRST
    property = 'stress'
    component = '1 1'
    execute_on = 'NONLINEAR TIMESTEP_END'
    block = 'plank block'
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [thermal_contact]
    type = GapConductanceConstraint
    variable = thermal_lm
    secondary_variable = temp
    k = 1
    use_displaced_mesh = true
    primary_boundary = plank_right
    primary_subdomain = frictionless_primary_subdomain
    secondary_boundary = block_left
    secondary_subdomain = frictionless_secondary_subdomain
    displacements = 'disp_x disp_y'
  []
[]
[BCs]
  [left_temp]
    type = DirichletBC
    variable = temp
    boundary = 'plank_left'
    value = 400
  []
  [right_temp]
    type = DirichletBC
    variable = temp
    boundary = 'block_right'
    value = 300
  []
  [left_x]
    type = DirichletBC
    variable = disp_x
    boundary = plank_left
    value = 0.0
  []
  [left_y]
    type = DirichletBC
    variable = disp_y
    boundary = plank_bottom
    value = 0.0
  []
  [right_x]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = block_right
    function = '-0.04*sin(4*(t+1.5))+0.02'
    preset = false
  []
  [right_y]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = block_right
    function = '-t'
    preset = false
  []
[]
[Materials]
  [plank]
    type = ComputeIsotropicElasticityTensor
    block = 'plank'
    poissons_ratio = 0.3
    youngs_modulus = ${E_plank}
  []
  [block]
    type = ComputeIsotropicElasticityTensor
    block = 'block'
    poissons_ratio = 0.3
    youngs_modulus = ${E_block}
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = 'plank block'
  []
  [heat_plank]
    type = HeatConductionMaterial
    block = plank
    thermal_conductivity = 2
    specific_heat = 1
  []
  [heat_block]
    type = HeatConductionMaterial
    block = block
    thermal_conductivity = 1
    specific_heat = 1
  []
[]
[Executioner]
  type = Transient
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -snes_max_it'
  petsc_options_value = 'lu       NONZERO               1e-15                   20'
  end_time = 0.4
  dt = 0.1
  dtmin = 0.1
  timestep_tolerance = 1e-6
  line_search = 'none'
[]
[Postprocessors]
  [nl_its]
    type = NumNonlinearIterations
  []
  [total_nl_its]
    type = CumulativeValuePostprocessor
    postprocessor = nl_its
  []
  [l_its]
    type = NumLinearIterations
  []
  [total_l_its]
    type = CumulativeValuePostprocessor
    postprocessor = l_its
  []
  [contact]
    type = ContactDOFSetSize
    variable = frictionless_normal_lm
    subdomain = frictionless_secondary_subdomain
  []
  [avg_hydro]
    type = ElementAverageValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [avg_temp]
    type = ElementAverageValue
    variable = temp
    block = 'block'
  []
  [max_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [min_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
    value_type = min
  []
  [avg_vonmises]
    type = ElementAverageValue
    variable = vonmises_stress
    block = 'block'
  []
  [max_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
  []
  [min_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
    value_type = min
  []
  [stress_xx_recovered]
    type = ElementExtremeValue
    variable = stress_xx_recovered
    block = 'block'
    value_type = max
  []
  [stress_yy_recovered]
    type = ElementExtremeValue
    variable = stress_yy_recovered
    block = 'block'
    value_type = max
  []
[]
[Outputs]
  exodus = true
  [comp]
    type = CSV
    show = 'contact avg_temp'
  []
  [out]
    type = CSV
  []
  [dof]
    type = DOFMap
    execute_on = 'initial'
  []
[]
[Debug]
  show_var_residual_norms = true
[]
(modules/contact/test/tests/3d-mortar-contact/frictionless-mortar-3d.i)
starting_point = 0.25
offset = 0.00
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  diffusivity = 1e0
  scaling = 1e0
[]
[Mesh]
  second_order = false
  [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'
  []
[]
[Variables]
  [disp_x]
    block = '1 2'
  []
  [disp_y]
    block = '1 2'
  []
  [disp_z]
    block = '1 2'
  []
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[ICs]
  [disp_z]
    block = 1
    variable = disp_z
    value = '${fparse offset}'
    type = ConstantIC
  []
  [disp_x]
    block = 1
    variable = disp_x
    value = 0
    type = ConstantIC
  []
  [disp_y]
    block = 1
    variable = disp_y
    value = 0
    type = ConstantIC
  []
[]
[Kernels]
  [disp_x]
    type = MatDiffusion
    variable = disp_x
  []
  [disp_y]
    type = MatDiffusion
    variable = disp_y
  []
  [disp_z]
    type = MatDiffusion
    variable = disp_z
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    lm_variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
  []
[]
[Constraints]
  [normal_lm]
    type = ComputeWeightedGapLMMechanicalContact
    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
    weighted_gap_uo = weighted_gap_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_gap_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_gap_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_gap_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 = 1
  dt = .5
  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 = 100
  nl_max_its = 30
  # nl_rel_tol = 1e-6
  nl_abs_tol = 1e-12
  line_search = 'none'
  snesmf_reuse_base = false
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  csv = 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 = 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
  []
[]
(modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-vel.i)
starting_point = 2e-1
offset = -0.19
[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
  []
[]
[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]
  [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
    correct_edge_dropping = true
    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_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeDynamicWeightedGapLMMechanicalContact
    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
    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_gap_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_gap_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 = 50
    function = '1e-2 * t'
  []
[]
[Executioner]
  type = Transient
  end_time = 0.1
  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_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'
  nl_max_its = 20
  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/sliding_block/edge_dropping/two_equal_blocks_slide_2d.i)
[GlobalParams]
  displacements = 'disp_x disp_y'
  volumetric_locking_correction = true
[]
[Mesh]
  [left_block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = -1.0
    xmax = 0.0
    ymin = -0.5
    ymax = 0.5
    nx = 4
    ny = 4
    elem_type = QUAD4
  []
  [left_block_sidesets]
    type = RenameBoundaryGenerator
    input = left_block
    old_boundary = '0 1 2 3'
    new_boundary = '10 11 12 13'
  []
  [left_block_id]
    type = SubdomainIDGenerator
    input = left_block_sidesets
    subdomain_id = 1
  []
  [right_block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0.0
    xmax = 1.0
    ymin = -0.5
    ymax = 0.5
    nx = 5
    ny = 5
    elem_type = QUAD4
  []
  [right_block_sidesets]
    type = RenameBoundaryGenerator
    input = right_block
    old_boundary = '0 1 2 3'
    new_boundary = '20 21 22 23'
  []
  [right_block_id]
    type = SubdomainIDGenerator
    input = right_block_sidesets
    subdomain_id = 2
  []
  [combined_mesh]
    type = MeshCollectionGenerator
    inputs = 'left_block_id right_block_id'
  []
  [left_lower]
    type = LowerDBlockFromSidesetGenerator
    input = combined_mesh
    sidesets = '11'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [right_lower]
    type = LowerDBlockFromSidesetGenerator
    input = left_lower
    sidesets = '23'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
[]
[Variables]
  [normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    strain = FINITE
    incremental = true
    add_variables = true
    block = '1 2'
  []
[]
[Functions]
  [horizontal_movement]
    type = PiecewiseLinear
    x = '0 0.1 4'
    y = '0 0.05 0.05'
  []
  [vertical_movement]
    type = PiecewiseLinear
    x = '0 0.1 4'
    y = '0 0 0.3'
  []
[]
[BCs]
  [push_left_x]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 13
    function = horizontal_movement
  []
  [fix_right_x]
    type = DirichletBC
    variable = disp_x
    boundary = 21
    value = 0.0
  []
  [fix_right_y]
    type = DirichletBC
    variable = disp_y
    boundary = 21
    value = 0.0
  []
  [push_left_y]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 13
    function = vertical_movement
  []
[]
[Materials]
  [elasticity_tensor_left]
    type = ComputeIsotropicElasticityTensor
    block = 1
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_left]
    type = ComputeFiniteStrainElasticStress
    block = 1
  []
  [elasticity_tensor_right]
    type = ComputeIsotropicElasticityTensor
    block = 2
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_right]
    type = ComputeFiniteStrainElasticStress
    block = 2
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    lm_variable = normal_lm
    correct_edge_dropping = true
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [normal_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
[]
[Preconditioning]
  [SMP]
    type = SMP
    full = true
  []
[]
[Executioner]
  type = Transient
  solve_type = 'PJFNK'
  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-10'
  line_search = 'none'
  dt = 0.1
  dtmin = 0.01
  end_time = 1.0
  l_max_its = 20
  nl_max_its = 20
  nl_rel_tol = 1e-6
  nl_abs_tol = 1e-8
  snesmf_reuse_base = false
[]
[Outputs]
  csv = true
  execute_on = 'FINAL'
[]
[Postprocessors]
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = 'secondary_lower'
  []
  [normal_lm]
    type = ElementAverageValue
    variable = normal_lm
    block = 'secondary_lower'
  []
  [avg_disp_x]
    type = ElementAverageValue
    variable = disp_x
    block = '1 2'
  []
  [avg_disp_y]
    type = ElementAverageValue
    variable = disp_y
    block = '1 2'
  []
  [max_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
  []
  [max_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
  []
  [min_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
    value_type = min
  []
  [min_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
    value_type = min
  []
[]
(modules/contact/test/tests/3d-mortar-contact/frictionless-mortar-3d_pg.i)
starting_point = 0.25
offset = 0.00
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  diffusivity = 1e0
  scaling = 1e0
[]
[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'
  []
[]
[Variables]
  [disp_x]
    block = '1 2'
  []
  [disp_y]
    block = '1 2'
  []
  [disp_z]
    block = '1 2'
  []
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[AuxVariables]
  [aux_lm]
    block = 'secondary_lower'
    use_dual = false
  []
[]
[ICs]
  [disp_z]
    block = 1
    variable = disp_z
    value = '${fparse offset}'
    type = ConstantIC
  []
  [disp_x]
    block = 1
    variable = disp_x
    value = 0
    type = ConstantIC
  []
  [disp_y]
    block = 1
    variable = disp_y
    value = 0
    type = ConstantIC
  []
[]
[Kernels]
  [disp_x]
    type = MatDiffusion
    variable = disp_x
  []
  [disp_y]
    type = MatDiffusion
    variable = disp_y
  []
  [disp_z]
    type = MatDiffusion
    variable = disp_z
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    lm_variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_petrov_galerkin = true
    aux_lm = aux_lm
  []
[]
[Constraints]
  [normal_lm]
    type = ComputeWeightedGapLMMechanicalContact
    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
    weighted_gap_uo = weighted_gap_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_gap_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_gap_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_gap_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 = 1
  dt = .5
  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 = 100
  nl_max_its = 30
  nl_abs_tol = 1e-12
  line_search = 'none'
  snesmf_reuse_base = false
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  csv = true
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Postprocessors]
  [contact]
    type = ContactDOFSetSize
    variable = mortar_normal_lm
    subdomain = 'secondary_lower'
    execute_on = 'nonlinear timestep_end'
  []
  [lambda]
    type = ElementAverageValue
    variable = mortar_normal_lm
    block = 'secondary_lower'
  []
[]
(modules/combined/test/tests/gap_heat_transfer_mortar/small-2d/small.i)
E_block = 1e7
E_plank = 1e7
elem = QUAD4
order = FIRST
name = 'small'
[Mesh]
  patch_size = 80
  patch_update_strategy = auto
  [plank]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = -0.3
    xmax = 0.3
    ymin = -10
    ymax = 10
    nx = 2
    ny = 67
    elem_type = ${elem}
    boundary_name_prefix = plank
  []
  [plank_id]
    type = SubdomainIDGenerator
    input = plank
    subdomain_id = 1
  []
  [block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0.31
    xmax = 0.91
    ymin = 7.7
    ymax = 8.5
    nx = 3
    ny = 4
    elem_type = ${elem}
    boundary_name_prefix = block
    boundary_id_offset = 10
  []
  [block_id]
    type = SubdomainIDGenerator
    input = block
    subdomain_id = 2
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'plank_id block_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'plank block'
  []
  [secondary]
    input = block_rename
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'block_left'
    new_block_id = '30'
    new_block_name = 'frictionless_secondary_subdomain'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'plank_right'
    new_block_id = '20'
    new_block_name = 'frictionless_primary_subdomain'
  []
[]
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Variables]
  [disp_x]
    order = ${order}
    block = 'plank block'
    scaling = ${fparse 2.0 / (E_plank + E_block)}
  []
  [disp_y]
    order = ${order}
    block = 'plank block'
    scaling = ${fparse 2.0 / (E_plank + E_block)}
  []
  [temp]
    order = ${order}
    block = 'plank block'
    scaling = 1e-1
  []
  [thermal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    scaling = 1e-7
  []
  [frictionless_normal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [action]
    generate_output = 'stress_xx stress_yy stress_zz vonmises_stress hydrostatic_stress strain_xx strain_yy strain_zz'
    block = 'plank block'
    use_automatic_differentiation = true
  []
[]
[Kernels]
  [hc]
    type = ADHeatConduction
    variable = temp
    use_displaced_mesh = true
    block = 'plank block'
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    lm_variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [thermal_contact]
    type = GapConductanceConstraint
    variable = thermal_lm
    secondary_variable = temp
    k = 1
    use_displaced_mesh = true
    primary_boundary = plank_right
    primary_subdomain = frictionless_primary_subdomain
    secondary_boundary = block_left
    secondary_subdomain = frictionless_secondary_subdomain
    displacements = 'disp_x disp_y'
  []
[]
[BCs]
  [left_temp]
    type = DirichletBC
    variable = temp
    boundary = 'plank_left'
    value = 400
  []
  [right_temp]
    type = DirichletBC
    variable = temp
    boundary = 'block_right'
    value = 300
  []
  [left_x]
    type = DirichletBC
    variable = disp_x
    boundary = plank_left
    value = 0.0
  []
  [left_y]
    type = DirichletBC
    variable = disp_y
    boundary = plank_bottom
    value = 0.0
  []
  [right_x]
    type = ADFunctionDirichletBC
    variable = disp_x
    boundary = block_right
    function = '-0.04*sin(4*(t+1.5))+0.02'
  []
  [right_y]
    type = ADFunctionDirichletBC
    variable = disp_y
    boundary = block_right
    function = '-t'
  []
[]
[Materials]
  [plank]
    type = ADComputeIsotropicElasticityTensor
    block = 'plank'
    poissons_ratio = 0.3
    youngs_modulus = ${E_plank}
  []
  [block]
    type = ADComputeIsotropicElasticityTensor
    block = 'block'
    poissons_ratio = 0.3
    youngs_modulus = ${E_block}
  []
  [stress]
    type = ADComputeLinearElasticStress
    block = 'plank block'
  []
  [heat_plank]
    type = ADHeatConductionMaterial
    block = plank
    thermal_conductivity = 2
    specific_heat = 1
  []
  [heat_block]
    type = ADHeatConductionMaterial
    block = block
    thermal_conductivity = 1
    specific_heat = 1
  []
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
[Executioner]
  type = Transient
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -snes_max_it'
  petsc_options_value = 'lu       NONZERO               1e-15                   20'
  end_time = 13.5
  dt = 0.1
  dtmin = 0.1
  timestep_tolerance = 1e-6
  line_search = 'none'
[]
[Postprocessors]
  [nl_its]
    type = NumNonlinearIterations
  []
  [total_nl_its]
    type = CumulativeValuePostprocessor
    postprocessor = nl_its
  []
  [l_its]
    type = NumLinearIterations
  []
  [total_l_its]
    type = CumulativeValuePostprocessor
    postprocessor = l_its
  []
  [contact]
    type = ContactDOFSetSize
    variable = frictionless_normal_lm
    subdomain = frictionless_secondary_subdomain
  []
  [avg_hydro]
    type = ElementAverageValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [avg_temp]
    type = ElementAverageValue
    variable = temp
    block = 'block'
  []
  [max_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [min_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
    value_type = min
  []
  [avg_vonmises]
    type = ElementAverageValue
    variable = vonmises_stress
    block = 'block'
  []
  [max_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
  []
  [min_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
    value_type = min
  []
[]
[Outputs]
  file_base = ${name}
  [comp]
    type = CSV
    show = 'contact avg_temp'
  []
  [out]
    type = CSV
    file_base = '${name}_out'
  []
[]
[Debug]
  show_var_residual_norms = true
[]
(modules/combined/test/tests/stateful_mortar_constraints/stateful_mortar_npr.i)
E_block = 1e7
E_plank = 1e7
elem = QUAD4
order = FIRST
[Mesh]
  patch_size = 80
  patch_update_strategy = auto
  [plank]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = -0.3
    xmax = 0.3
    ymin = -10
    ymax = 10
    nx = 2
    ny = 67
    elem_type = ${elem}
    boundary_name_prefix = plank
  []
  [plank_id]
    type = SubdomainIDGenerator
    input = plank
    subdomain_id = 1
  []
  [block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0.31
    xmax = 0.91
    ymin = 7.7
    ymax = 8.5
    nx = 3
    ny = 4
    elem_type = ${elem}
    boundary_name_prefix = block
    boundary_id_offset = 10
  []
  [block_id]
    type = SubdomainIDGenerator
    input = block
    subdomain_id = 2
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'plank_id block_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'plank block'
  []
  [secondary]
    input = block_rename
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'block_left'
    new_block_id = '30'
    new_block_name = 'frictionless_secondary_subdomain'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'plank_right'
    new_block_id = '20'
    new_block_name = 'frictionless_primary_subdomain'
  []
[]
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Variables]
  [disp_x]
    order = ${order}
    block = 'plank block'
    scaling = '${fparse 2.0 / (E_plank + E_block)}'
  []
  [disp_y]
    order = ${order}
    block = 'plank block'
    scaling = '${fparse 2.0 / (E_plank + E_block)}'
  []
  [temp]
    order = ${order}
    block = 'plank block'
    scaling = 1e-1
  []
  [thermal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    scaling = 1e-7
  []
  [frictionless_normal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    use_dual = true
  []
[]
[AuxVariables]
  [stress_xx]
    order = FIRST
    family = MONOMIAL
    block = 'plank block'
  []
  [stress_yy]
    order = FIRST
    family = MONOMIAL
    block = 'plank block'
  []
  [stress_xx_recovered]
    order = FIRST
    family = LAGRANGE
    block = 'plank block'
  []
  [stress_yy_recovered]
    order = FIRST
    family = LAGRANGE
    block = 'plank block'
  []
[]
[AuxKernels]
  [stress_xx]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_xx
    index_i = 0
    index_j = 0
    execute_on = 'timestep_end'
    block = 'plank block'
  []
  [stress_yy]
    type = RankTwoAux
    rank_two_tensor = stress
    variable = stress_yy
    index_i = 1
    index_j = 1
    execute_on = 'timestep_end'
    block = 'plank block'
  []
  [stress_xx_recovered]
    type = NodalPatchRecoveryAux
    variable = stress_xx_recovered
    nodal_patch_recovery_uo = stress_xx_patch
    execute_on = 'TIMESTEP_END'
    block = 'plank block'
  []
  [stress_yy_recovered]
    type = NodalPatchRecoveryAux
    variable = stress_yy_recovered
    nodal_patch_recovery_uo = stress_yy_patch
    execute_on = 'TIMESTEP_END'
    block = 'plank block'
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [action]
    generate_output = 'stress_zz vonmises_stress hydrostatic_stress strain_xx strain_yy strain_zz'
    block = 'plank block'
    use_automatic_differentiation = false
    strain = FINITE
  []
[]
[Kernels]
  [hc]
    type = HeatConduction
    variable = temp
    use_displaced_mesh = true
    block = 'plank block'
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    lm_variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
  [stress_xx_patch]
    type = NodalPatchRecoveryMaterialProperty
    patch_polynomial_order = FIRST
    property = 'stress'
    component = '0 0'
    execute_on = 'NONLINEAR TIMESTEP_END'
    block = 'plank block'
  []
  [stress_yy_patch]
    type = NodalPatchRecoveryMaterialProperty
    patch_polynomial_order = FIRST
    property = 'stress'
    component = '1 1'
    execute_on = 'NONLINEAR TIMESTEP_END'
    block = 'plank block'
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [thermal_contact]
    type = GapConductanceStatefulConstraint
    variable = thermal_lm
    secondary_variable = temp
    k = 0.0001
    use_displaced_mesh = true
    primary_boundary = plank_right
    primary_subdomain = frictionless_primary_subdomain
    secondary_boundary = block_left
    secondary_subdomain = frictionless_secondary_subdomain
    displacements = 'disp_x disp_y'
    stateful_variable = stress_xx_recovered
  []
[]
[BCs]
  [left_temp]
    type = DirichletBC
    variable = temp
    boundary = 'plank_left'
    value = 400
  []
  [right_temp]
    type = DirichletBC
    variable = temp
    boundary = 'block_right'
    value = 300
  []
  [left_x]
    type = DirichletBC
    variable = disp_x
    boundary = plank_left
    value = 0.0
  []
  [left_y]
    type = DirichletBC
    variable = disp_y
    boundary = plank_bottom
    value = 0.0
  []
  [right_x]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = block_right
    function = '-0.04*sin(4*(t+1.5))+0.02'
    preset = false
  []
  [right_y]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = block_right
    function = '-t'
    preset = false
  []
[]
[Materials]
  [plank]
    type = ComputeIsotropicElasticityTensor
    block = 'plank'
    poissons_ratio = 0.3
    youngs_modulus = ${E_plank}
  []
  [block]
    type = ComputeIsotropicElasticityTensor
    block = 'block'
    poissons_ratio = 0.3
    youngs_modulus = ${E_block}
  []
  [stress]
    type = ComputeFiniteStrainElasticStress
    block = 'plank block'
  []
  [heat_plank]
    type = HeatConductionMaterial
    block = plank
    thermal_conductivity = 2
    specific_heat = 1
  []
  [heat_block]
    type = HeatConductionMaterial
    block = block
    thermal_conductivity = 1
    specific_heat = 1
  []
[]
[Executioner]
  type = Transient
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -snes_max_it'
  petsc_options_value = 'lu       NONZERO               1e-15                   20'
  end_time = 0.5
  dt = 0.1
  dtmin = 0.1
  timestep_tolerance = 1e-6
  line_search = 'none'
[]
[Postprocessors]
  [avg_hydro]
    type = ElementAverageValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [avg_temp]
    type = ElementAverageValue
    variable = temp
    block = 'block'
  []
  [max_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [min_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
    value_type = min
  []
  [avg_vonmises]
    type = ElementAverageValue
    variable = vonmises_stress
    block = 'block'
  []
  [max_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
  []
  [min_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
    value_type = min
  []
  [stress_xx_recovered]
    type = ElementExtremeValue
    variable = stress_xx_recovered
    block = 'block'
    value_type = max
  []
  [stress_yy_recovered]
    type = ElementExtremeValue
    variable = stress_yy_recovered
    block = 'block'
    value_type = max
  []
  [min_temperature]
    type = ElementExtremeValue
    variable = temp
    block = 'plank'
    value_type = min
  []
[]
[Outputs]
  exodus = true
  [out]
    type = CSV
  []
  [dof]
    type = DOFMap
    execute_on = 'initial'
  []
[]
[Debug]
  show_var_residual_norms = true
[]
(modules/contact/test/tests/bouncing-block-contact/frictionless-weighted-gap.i)
starting_point = 2e-1
offset = 1e-2
[GlobalParams]
  displacements = 'disp_x disp_y'
  diffusivity = 1e0
  scaling = 1e0
[]
[Mesh]
  file = long-bottom-block-1elem-blocks.e
[]
[Variables]
  [disp_x]
    block = '1 2'
  []
  [disp_y]
    block = '1 2'
  []
  [normal_lm]
    block = 3
  []
[]
[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_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeWeightedGapLMMechanicalContact
    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 = 1
    weighted_gap_uo = weighted_gap_uo
  []
  [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_gap_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_gap_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}'
    preset = false
  []
  [leftx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 50
    function = '1e-2 * t'
    preset = false
  []
[]
[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'
  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 = true
  nl_rel_tol = 1e-12
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = 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_dynamics/block-dynamics-reference.i)
starting_point = 2e-1
offset = -0.19
[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
  []
[]
[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]
  [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'
  []
  [kinetic_energy]
    order = CONSTANT
    family = MONOMIAL
  []
  [elastic_energy]
    order = CONSTANT
    family = MONOMIAL
  []
[]
[AuxKernels]
  [accel_x]
    type = NewmarkAccelAux
    variable = accel_x
    displacement = disp_x
    velocity = vel_x
    beta = 0.25
    execute_on = 'timestep_end'
  []
  [vel_x]
    type = NewmarkVelAux
    variable = vel_x
    acceleration = accel_x
    gamma = 0.5
    execute_on = 'timestep_end'
  []
  [accel_y]
    type = NewmarkAccelAux
    variable = accel_y
    displacement = disp_y
    velocity = vel_y
    beta = 0.25
    execute_on = 'timestep_end'
  []
  [vel_y]
    type = NewmarkVelAux
    variable = vel_y
    acceleration = accel_y
    gamma = 0.5
    execute_on = 'timestep_end'
  []
  [kinetic_energy]
    type = KineticEnergyAux
    block = '1 2'
    variable = kinetic_energy
    newmark_velocity_x = vel_x
    newmark_velocity_y = vel_y
    newmark_velocity_z = 0.0
    density = density
  []
  [elastic_energy]
    type = ElasticEnergyAux
    variable = elastic_energy
    block = '1 2'
  []
[]
# User object provides the contact force (e.g. LM)
# for the application of the generalized force
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  # Not using 'dynamic' constraints results in poor enforcement of contact
  # constraints and lack of kinetic and elastic energy conservation.
  [weighted_gap_lm]
    type = ComputeDynamicWeightedGapLMMechanicalContact
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    newmark_beta = 0.25
    newmark_gamma = 0.5
    use_displaced_mesh = true
    # Capture tolerance is important. If too small, stabilization takes longer
    capture_tolerance = 1.0e-5
    c = 1.0e6
  []
  [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_gap_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_gap_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 = 0.275 # 8.0
  dt = 0.025
  dtmin = .025
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -snes_linesearch_monitor'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount'
  petsc_options_value = 'lu       NONZERO               1e-15'
  nl_max_its = 50
  line_search = 'none'
  [TimeIntegrator]
    type = NewmarkBeta
    beta = 0.25
    gamma = 0.5
  []
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  checkpoint = true
  csv = true
[]
[Postprocessors]
  active = 'contact total_kinetic_energy total_elastic_energy'
  [num_nl]
    type = NumNonlinearIterations
  []
  [cumulative]
    type = CumulativeValuePostprocessor
    postprocessor = num_nl
  []
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = '3'
    execute_on = 'nonlinear timestep_end'
  []
  [total_kinetic_energy]
    type = ElementIntegralVariablePostprocessor
    variable = kinetic_energy
    block = '1 2'
  []
  [total_elastic_energy]
    type = ElementIntegralVariablePostprocessor
    variable = elastic_energy
    block = '1 2'
  []
[]
(modules/contact/test/tests/simple_contact/two_block_compress/two_equal_blocks_compress_3d.i)
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[Mesh]
  [left_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 1
    ny = 1
    nz = 1
    xmin = -1.0
    xmax = 0.0
    ymin = -0.5
    ymax = 0.5
    zmin = -0.5
    zmax = 0.5
    elem_type = HEX8
  []
  [left_block_sidesets]
    type = RenameBoundaryGenerator
    input = left_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'left_bottom left_back left_right left_front left_left left_top'
  []
  [left_block_id]
    type = SubdomainIDGenerator
    input = left_block_sidesets
    subdomain_id = 1
  []
  [right_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 2
    ny = 2
    nz = 2
    xmin = 0.0
    xmax = 1.0
    ymin = -0.5
    ymax = 0.5
    zmin = -0.5
    zmax = 0.5
    elem_type = HEX8
  []
  [right_block_sidesets]
    type = RenameBoundaryGenerator
    input = right_block
    old_boundary = '0 1 2 3 4 5'
    # new_boundary = 'right_bottom right_back right_right right_front right_left right_top'
    new_boundary = '100 101 102 103 104 105'
  []
  [right_block_sidesets_rename]
    type = RenameBoundaryGenerator
    input = right_block_sidesets
    old_boundary = '100 101 102 103 104 105'
    new_boundary = 'right_bottom right_back right_right right_front right_left right_top'
  []
  [right_block_id]
    type = SubdomainIDGenerator
    input = right_block_sidesets_rename
    subdomain_id = 2
  []
  [combined_mesh]
    type = MeshCollectionGenerator
    inputs = 'left_block_id right_block_id'
  []
  [left_lower]
    type = LowerDBlockFromSidesetGenerator
    input = combined_mesh
    sidesets = 'left_right'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [right_lower]
    type = LowerDBlockFromSidesetGenerator
    input = left_lower
    sidesets = 'right_left'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
[]
[Variables]
  [normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    strain = FINITE
    incremental = true
    add_variables = true
    block = '1 2'
  []
[]
[Functions]
  [horizontal_movement]
    type = PiecewiseLinear
    x = '0 0.5'
    y = '0 0.2'
  []
  [vertical_movement]
    type = PiecewiseLinear
    x = '0 1.0'
    y = '0 0'
  []
[]
[BCs]
  [push_left_x]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 'left_left'
    function = horizontal_movement
  []
  [push_left_y]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 'left_left'
    function = vertical_movement
  []
  [fix_left_z]
    type = DirichletBC
    variable = disp_z
    boundary = 'left_left'
    value = 0.0
  []
  [fix_right_x]
    type = DirichletBC
    variable = disp_x
    boundary = 'right_right'
    value = 0.0
  []
  [fix_right_y]
    type = DirichletBC
    variable = disp_y
    boundary = 'right_right'
    value = 0.0
  []
  [fix_right_z]
    type = DirichletBC
    variable = disp_z
    boundary = 'right_right'
    value = 0.0
  []
[]
[Materials]
  [elasticity_tensor_left]
    type = ComputeIsotropicElasticityTensor
    block = 1
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_left]
    type = ComputeFiniteStrainElasticStress
    block = 1
  []
  [elasticity_tensor_right]
    type = ComputeIsotropicElasticityTensor
    block = 2
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_right]
    type = ComputeFiniteStrainElasticStress
    block = 2
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    correct_edge_dropping = true
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
  []
[]
[Constraints]
  [normal_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
[]
[Preconditioning]
  [SMP]
    type = SMP
    full = true
  []
[]
[Executioner]
  type = Transient
  solve_type = 'PJFNK'
  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-10'
  line_search = 'none'
  dt = 0.1
  dtmin = 0.01
  end_time = 0.4
  l_max_its = 20
  nl_max_its = 20
  nl_rel_tol = 1e-6
  nl_abs_tol = 1e-8
  snesmf_reuse_base = false
[]
[Outputs]
  csv = true
  execute_on = 'FINAL'
[]
[Postprocessors]
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = 'secondary_lower'
  []
  [normal_lm]
    type = ElementAverageValue
    variable = normal_lm
    block = 'secondary_lower'
  []
  [avg_disp_x]
    type = ElementAverageValue
    variable = disp_x
    block = '1 2'
  []
  [avg_disp_y]
    type = ElementAverageValue
    variable = disp_y
    block = '1 2'
  []
  [max_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
  []
  [max_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
  []
  [min_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
    value_type = min
  []
  [min_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
    value_type = min
  []
[]
(modules/combined/test/tests/gap_heat_transfer_mortar/small-2d-rz/small.i)
E_block = 1e7
E_plank = 1e7
elem = QUAD4
order = FIRST
name = 'small'
[Mesh]
  patch_size = 80
  patch_update_strategy = auto
  [plank]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0
    xmax = 0.6
    ymin = -10
    ymax = 10
    nx = 2
    ny = 67
    elem_type = ${elem}
    boundary_name_prefix = plank
  []
  [plank_id]
    type = SubdomainIDGenerator
    input = plank
    subdomain_id = 1
  []
  [block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0.61
    xmax = 1.21
    ymin = 7.7
    ymax = 8.5
    nx = 3
    ny = 4
    elem_type = ${elem}
    boundary_name_prefix = block
    boundary_id_offset = 10
  []
  [block_id]
    type = SubdomainIDGenerator
    input = block
    subdomain_id = 2
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'plank_id block_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'plank block'
  []
  [secondary]
    input = block_rename
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'block_left'
    new_block_id = '30'
    new_block_name = 'frictionless_secondary_subdomain'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'plank_right'
    new_block_id = '20'
    new_block_name = 'frictionless_primary_subdomain'
  []
  coord_type = RZ
[]
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Variables]
  [disp_x]
    order = ${order}
    block = 'plank block'
    scaling = ${fparse 2.0 / (E_plank + E_block)}
  []
  [disp_y]
    order = ${order}
    block = 'plank block'
    scaling = ${fparse 2.0 / (E_plank + E_block)}
  []
  [temp]
    order = ${order}
    block = 'plank block'
    scaling = 1e-1
  []
  [thermal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    scaling = 1e-7
  []
  [frictionless_normal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [action]
    generate_output = 'stress_xx stress_yy stress_zz vonmises_stress hydrostatic_stress strain_xx strain_yy strain_zz'
    block = 'plank block'
    use_automatic_differentiation = true
  []
[]
[Kernels]
  [hc]
    type = ADHeatConduction
    variable = temp
    use_displaced_mesh = true
    block = 'plank block'
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    lm_variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [thermal_contact]
    type = GapConductanceConstraint
    variable = thermal_lm
    secondary_variable = temp
    k = 1
    use_displaced_mesh = true
    primary_boundary = plank_right
    primary_subdomain = frictionless_primary_subdomain
    secondary_boundary = block_left
    secondary_subdomain = frictionless_secondary_subdomain
    displacements = 'disp_x disp_y'
  []
[]
[BCs]
  [left_temp]
    type = DirichletBC
    variable = temp
    boundary = 'plank_left'
    value = 400
  []
  [right_temp]
    type = DirichletBC
    variable = temp
    boundary = 'block_right'
    value = 300
  []
  [left_x]
    type = DirichletBC
    variable = disp_x
    boundary = plank_left
    value = 0.0
  []
  [left_y]
    type = DirichletBC
    variable = disp_y
    boundary = plank_bottom
    value = 0.0
  []
  [right_x]
    type = ADFunctionDirichletBC
    variable = disp_x
    boundary = block_right
    function = '-0.04*sin(4*(t+1.5))+0.02'
    preset = false
  []
  [right_y]
    type = ADFunctionDirichletBC
    variable = disp_y
    boundary = block_right
    function = '-t'
    preset = false
  []
[]
[Materials]
  [plank]
    type = ADComputeIsotropicElasticityTensor
    block = 'plank'
    poissons_ratio = 0.3
    youngs_modulus = ${E_plank}
  []
  [block]
    type = ADComputeIsotropicElasticityTensor
    block = 'block'
    poissons_ratio = 0.3
    youngs_modulus = ${E_block}
  []
  [stress]
    type = ADComputeLinearElasticStress
    block = 'plank block'
  []
  [heat_plank]
    type = ADHeatConductionMaterial
    block = plank
    thermal_conductivity = 2
    specific_heat = 1
  []
  [heat_block]
    type = ADHeatConductionMaterial
    block = block
    thermal_conductivity = 1
    specific_heat = 1
  []
[]
[Executioner]
  type = Transient
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -snes_max_it'
  petsc_options_value = 'lu       NONZERO               1e-15                   20'
  end_time = 13.5
  dt = 0.1
  dtmin = 0.1
  timestep_tolerance = 1e-6
  line_search = 'none'
[]
[Postprocessors]
  [nl_its]
    type = NumNonlinearIterations
  []
  [total_nl_its]
    type = CumulativeValuePostprocessor
    postprocessor = nl_its
  []
  [l_its]
    type = NumLinearIterations
  []
  [total_l_its]
    type = CumulativeValuePostprocessor
    postprocessor = l_its
  []
  [contact]
    type = ContactDOFSetSize
    variable = frictionless_normal_lm
    subdomain = frictionless_secondary_subdomain
  []
  [avg_hydro]
    type = ElementAverageValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [avg_temp]
    type = ElementAverageValue
    variable = temp
    block = 'block'
  []
  [max_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [min_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
    value_type = min
  []
  [avg_vonmises]
    type = ElementAverageValue
    variable = vonmises_stress
    block = 'block'
  []
  [max_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
  []
  [min_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
    value_type = min
  []
[]
[Outputs]
  file_base = ${name}
  [comp]
    type = CSV
    show = 'contact avg_temp'
  []
  [out]
    type = CSV
    file_base = '${name}_out'
  []
[]
[Debug]
  show_var_residual_norms = true
[]
(modules/contact/test/tests/bouncing-block-contact/mixed-weighted-gap-swapped.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]
  second_order = true
  [file_mesh]
    type = FileMeshGenerator
    file = long-bottom-block-1elem-blocks-coarse.e
  []
[]
[Variables]
  [disp_x]
    block = '1 2'
    scaling = 1e1
    order = SECOND
  []
  [disp_y]
    block = '1 2'
    scaling = 1e1
    order = SECOND
  []
  [frictional_normal_lm]
    block = 4
    scaling = 1e3
  []
[]
[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_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = 10
    secondary_boundary = 20
    primary_subdomain = 3
    secondary_subdomain = 4
    lm_variable = frictional_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    correct_edge_dropping = true
  []
[]
[Constraints]
  [frictional_normal_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = 10
    secondary_boundary = 20
    primary_subdomain = 3
    secondary_subdomain = 4
    variable = frictional_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    normalize_c = true
    c = 1.0e-2
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 10
    secondary_boundary = 20
    primary_subdomain = 3
    secondary_subdomain = 4
    variable = frictional_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 10
    secondary_boundary = 20
    primary_subdomain = 3
    secondary_subdomain = 4
    variable = frictional_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_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
[]
[Preconditioning]
  [smp]
    type = SMP
    full = true
  []
[]
(modules/contact/test/tests/sliding_block/edge_dropping/two_equal_blocks_slide_3d.i)
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[Mesh]
  [left_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 1
    ny = 1
    nz = 1
    xmin = -1.0
    xmax = 0.0
    ymin = -0.5
    ymax = 0.5
    zmin = -0.5
    zmax = 0.5
    elem_type = HEX8
  []
  [left_block_sidesets]
    type = RenameBoundaryGenerator
    input = left_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'left_bottom left_back left_right left_front left_left left_top'
  []
  [left_block_id]
    type = SubdomainIDGenerator
    input = left_block_sidesets
    subdomain_id = 1
  []
  [right_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 2
    ny = 2
    nz = 2
    xmin = 0.0
    xmax = 1.0
    ymin = -0.5
    ymax = 0.5
    zmin = -0.5
    zmax = 0.5
    elem_type = HEX8
  []
  [right_block_sidesets]
    type = RenameBoundaryGenerator
    input = right_block
    old_boundary = '0 1 2 3 4 5'
    # new_boundary = 'right_bottom right_back right_right right_front right_left right_top'
    new_boundary = '100 101 102 103 104 105'
  []
  [right_block_sidesets_rename]
    type = RenameBoundaryGenerator
    input = right_block_sidesets
    old_boundary = '100 101 102 103 104 105'
    new_boundary = 'right_bottom right_back right_right right_front right_left right_top'
  []
  [right_block_id]
    type = SubdomainIDGenerator
    input = right_block_sidesets_rename
    subdomain_id = 2
  []
  [combined_mesh]
    type = MeshCollectionGenerator
    inputs = 'left_block_id right_block_id'
  []
  [left_lower]
    type = LowerDBlockFromSidesetGenerator
    input = combined_mesh
    sidesets = 'left_right'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [right_lower]
    type = LowerDBlockFromSidesetGenerator
    input = left_lower
    sidesets = 'right_left'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
[]
[Variables]
  [normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    strain = FINITE
    incremental = true
    add_variables = true
    block = '1 2'
  []
[]
[Functions]
  [horizontal_movement]
    type = PiecewiseLinear
    x = '0 0.1 4'
    y = '0 0.05 0.05'
  []
  [vertical_movement]
    type = PiecewiseLinear
    x = '0 0.1 4'
    y = '0 0 0.3'
  []
[]
[BCs]
  [push_left_x]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 'left_left'
    function = horizontal_movement
  []
  [push_left_y]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 'left_left'
    function = vertical_movement
  []
  [fix_left_z]
    type = DirichletBC
    variable = disp_z
    boundary = 'left_left'
    value = 0.0
  []
  [fix_right_x]
    type = DirichletBC
    variable = disp_x
    boundary = 'right_right'
    value = 0.0
  []
  [fix_right_y]
    type = DirichletBC
    variable = disp_y
    boundary = 'right_right'
    value = 0.0
  []
  [fix_right_z]
    type = DirichletBC
    variable = disp_z
    boundary = 'right_right'
    value = 0.0
  []
[]
[Materials]
  [elasticity_tensor_left]
    type = ComputeIsotropicElasticityTensor
    block = 1
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_left]
    type = ComputeFiniteStrainElasticStress
    block = 1
  []
  [elasticity_tensor_right]
    type = ComputeIsotropicElasticityTensor
    block = 2
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_right]
    type = ComputeFiniteStrainElasticStress
    block = 2
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
  []
[]
[Constraints]
  [normal_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
[]
[Preconditioning]
  [SMP]
    type = SMP
    full = true
  []
[]
[Executioner]
  type = Transient
  solve_type = 'PJFNK'
  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-10'
  line_search = 'none'
  dt = 0.1
  dtmin = 0.01
  end_time = 0.4
  l_max_its = 20
  nl_max_its = 20
  nl_rel_tol = 1e-6
  nl_abs_tol = 1e-8
  snesmf_reuse_base = false
[]
[Outputs]
  csv = true
  execute_on = 'FINAL'
[]
[Postprocessors]
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = 'secondary_lower'
  []
  [normal_lm]
    type = ElementAverageValue
    variable = normal_lm
    block = 'secondary_lower'
  []
  [avg_disp_x]
    type = ElementAverageValue
    variable = disp_x
    block = '1 2'
  []
  [avg_disp_y]
    type = ElementAverageValue
    variable = disp_y
    block = '1 2'
  []
  [max_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
  []
  [max_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
  []
  [min_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
    value_type = min
  []
  [min_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
    value_type = min
  []
[]
(modules/combined/test/tests/gap_heat_transfer_mortar/finite-2d/finite_rr.i)
E_block = 1e7
E_plank = 1e7
elem = QUAD4
order = FIRST
name = 'finite'
[Mesh]
  patch_size = 80
  patch_update_strategy = auto
  [plank]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = -0.3
    xmax = 0.3
    ymin = -10
    ymax = 10
    nx = 2
    ny = 67
    elem_type = ${elem}
    boundary_name_prefix = plank
  []
  [plank_id]
    type = SubdomainIDGenerator
    input = plank
    subdomain_id = 1
  []
  [block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0.31
    xmax = 0.91
    ymin = 7.7
    ymax = 8.5
    nx = 3
    ny = 4
    elem_type = ${elem}
    boundary_name_prefix = block
    boundary_id_offset = 10
  []
  [block_id]
    type = SubdomainIDGenerator
    input = block
    subdomain_id = 2
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'plank_id block_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'plank block'
  []
  [secondary]
    input = block_rename
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'block_left'
    new_block_id = '30'
    new_block_name = 'frictionless_secondary_subdomain'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'plank_right'
    new_block_id = '20'
    new_block_name = 'frictionless_primary_subdomain'
  []
[]
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Problem]
  type = ReferenceResidualProblem
  reference_vector = 'ref'
  extra_tag_vectors = 'ref'
  converge_on = 'disp_x disp_y temp'
[]
[Variables]
  [disp_x]
    order = ${order}
    block = 'plank block'
    scaling = ${fparse 2.0 / (E_plank + E_block)}
  []
  [disp_y]
    order = ${order}
    block = 'plank block'
    scaling = ${fparse 2.0 / (E_plank + E_block)}
  []
  [temp]
    order = ${order}
    block = 'plank block'
    scaling = 1e-1
  []
  [thermal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    scaling = 1e-7
  []
  [frictionless_normal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [action]
    generate_output = 'stress_xx stress_yy stress_zz vonmises_stress hydrostatic_stress strain_xx strain_yy strain_zz'
    block = 'plank block'
    use_automatic_differentiation = true
    strain = FINITE
    extra_vector_tags = 'ref'
  []
[]
[Kernels]
  [hc]
    type = ADHeatConduction
    variable = temp
    use_displaced_mesh = true
    block = 'plank block'
    extra_vector_tags = 'ref'
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    lm_variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [thermal_contact]
    type = GapConductanceConstraint
    variable = thermal_lm
    secondary_variable = temp
    k = 1
    use_displaced_mesh = true
    primary_boundary = plank_right
    primary_subdomain = frictionless_primary_subdomain
    secondary_boundary = block_left
    secondary_subdomain = frictionless_secondary_subdomain
    displacements = 'disp_x disp_y'
  []
[]
[BCs]
  [left_temp]
    type = ADDirichletBC
    variable = temp
    boundary = 'plank_left'
    value = 400
  []
  [right_temp]
    type = ADDirichletBC
    variable = temp
    boundary = 'block_right'
    value = 300
  []
  [left_x]
    type = ADDirichletBC
    variable = disp_x
    boundary = plank_left
    value = 0.0
  []
  [left_y]
    type = ADDirichletBC
    variable = disp_y
    boundary = plank_bottom
    value = 0.0
  []
  [right_x]
    type = ADFunctionDirichletBC
    variable = disp_x
    boundary = block_right
    function = '-0.04*sin(4*(t+1.5))+0.02'
    preset = false
  []
  [right_y]
    type = ADFunctionDirichletBC
    variable = disp_y
    boundary = block_right
    function = '-t'
    preset = false
  []
[]
[Materials]
  [plank]
    type = ADComputeIsotropicElasticityTensor
    block = 'plank'
    poissons_ratio = 0.3
    youngs_modulus = ${E_plank}
  []
  [block]
    type = ADComputeIsotropicElasticityTensor
    block = 'block'
    poissons_ratio = 0.3
    youngs_modulus = ${E_block}
  []
  [stress]
    type = ADComputeFiniteStrainElasticStress
    block = 'plank block'
  []
  [heat_plank]
    type = ADHeatConductionMaterial
    block = plank
    thermal_conductivity = 2
    specific_heat = 1
  []
  [heat_block]
    type = ADHeatConductionMaterial
    block = block
    thermal_conductivity = 1
    specific_heat = 1
  []
[]
[Executioner]
  type = Transient
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -snes_max_it'
  petsc_options_value = 'lu       NONZERO               1e-15                   20'
  end_time = 13.5
  dt = 0.1
  dtmin = 0.1
  timestep_tolerance = 1e-6
  line_search = 'none'
  nl_abs_tol = 1e-13
[]
[Postprocessors]
  [nl_its]
    type = NumNonlinearIterations
  []
  [total_nl_its]
    type = CumulativeValuePostprocessor
    postprocessor = nl_its
  []
  [l_its]
    type = NumLinearIterations
  []
  [total_l_its]
    type = CumulativeValuePostprocessor
    postprocessor = l_its
  []
  [contact]
    type = ContactDOFSetSize
    variable = frictionless_normal_lm
    subdomain = frictionless_secondary_subdomain
  []
  [avg_hydro]
    type = ElementAverageValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [avg_temp]
    type = ElementAverageValue
    variable = temp
    block = 'block'
  []
  [max_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [min_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
    value_type = min
  []
  [avg_vonmises]
    type = ElementAverageValue
    variable = vonmises_stress
    block = 'block'
  []
  [max_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
  []
  [min_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
    value_type = min
  []
[]
[Outputs]
  file_base = ${name}
  [comp]
    type = CSV
    show = 'contact avg_temp'
  []
  [out]
    type = CSV
    file_base = '${name}_out'
  []
  [dof]
    type = DOFMap
    execute_on = 'initial'
  []
[]
[Debug]
  show_var_residual_norms = true
[]
(modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-wear.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
  []
[]
[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'
  []
  [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]
  [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_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeDynamicWeightedGapLMMechanicalContact
    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
    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_gap_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_gap_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(8.0 * pi / 4 * t) + ${offset}'
  []
  [leftx]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 50
    function = '1e-2 * t'
  []
[]
[Executioner]
  type = Transient
  end_time = 0.675
  dt = 0.075
  dtmin = .075
  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 = 30
  line_search = 'l2'
  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/3d-mortar-contact/frictionless-mortar-3d-test-derivative-trimming.i)
starting_point = 0.25
offset = 0.00
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  diffusivity = 1e0
  scaling = 1e0
[]
[Mesh]
  second_order = false
  [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 = 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'
  []
[]
[Variables]
  [disp_x]
    block = '1 2'
  []
  [disp_y]
    block = '1 2'
  []
  [disp_z]
    block = '1 2'
  []
  [mortar_normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[ICs]
  [disp_z]
    block = 1
    variable = disp_z
    value = '${fparse offset}'
    type = ConstantIC
  []
  [disp_x]
    block = 1
    variable = disp_x
    value = 0
    type = ConstantIC
  []
  [disp_y]
    block = 1
    variable = disp_y
    value = 0
    type = ConstantIC
  []
[]
[Kernels]
  [disp_x]
    type = MatDiffusion
    variable = disp_x
  []
  [disp_y]
    type = MatDiffusion
    variable = disp_y
  []
  [disp_z]
    type = MatDiffusion
    variable = disp_z
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = 'bottom_top'
    secondary_boundary = 'top_bottom'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    lm_variable = mortar_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
  []
[]
[Constraints]
  [normal_lm]
    type = ComputeWeightedGapLMMechanicalContact
    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
    c = 1.0e4
    weighted_gap_uo = weighted_gap_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_gap_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_gap_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_gap_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 = 1
  dt = .5
  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 = 100
  nl_max_its = 30
  # nl_rel_tol = 1e-6
  nl_abs_tol = 1e-12
  line_search = 'none'
  snesmf_reuse_base = false
[]
[Debug]
  show_var_residual_norms = true
[]
[Outputs]
  exodus = true
  csv = 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 = 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
  []
[]
(modules/combined/test/tests/gap_heat_transfer_mortar/finite-2d/finite.i)
E_block = 1e7
E_plank = 1e7
elem = QUAD4
order = FIRST
name = 'finite'
[Mesh]
  patch_size = 80
  patch_update_strategy = auto
  [plank]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = -0.3
    xmax = 0.3
    ymin = -10
    ymax = 10
    nx = 2
    ny = 67
    elem_type = ${elem}
    boundary_name_prefix = plank
  []
  [plank_id]
    type = SubdomainIDGenerator
    input = plank
    subdomain_id = 1
  []
  [block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0.31
    xmax = 0.91
    ymin = 7.7
    ymax = 8.5
    nx = 3
    ny = 4
    elem_type = ${elem}
    boundary_name_prefix = block
    boundary_id_offset = 10
  []
  [block_id]
    type = SubdomainIDGenerator
    input = block
    subdomain_id = 2
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'plank_id block_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'plank block'
  []
  [secondary]
    input = block_rename
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'block_left'
    new_block_id = '30'
    new_block_name = 'frictionless_secondary_subdomain'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'plank_right'
    new_block_id = '20'
    new_block_name = 'frictionless_primary_subdomain'
  []
[]
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Variables]
  [disp_x]
    order = ${order}
    block = 'plank block'
    scaling = ${fparse 2.0 / (E_plank + E_block)}
  []
  [disp_y]
    order = ${order}
    block = 'plank block'
    scaling = ${fparse 2.0 / (E_plank + E_block)}
  []
  [temp]
    order = ${order}
    block = 'plank block'
    scaling = 1e-1
  []
  [thermal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    scaling = 1e-7
  []
  [frictionless_normal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [action]
    generate_output = 'stress_xx stress_yy stress_zz vonmises_stress hydrostatic_stress strain_xx strain_yy strain_zz'
    block = 'plank block'
    use_automatic_differentiation = true
    strain = FINITE
  []
[]
[Kernels]
  [hc]
    type = ADHeatConduction
    variable = temp
    use_displaced_mesh = true
    block = 'plank block'
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    lm_variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [thermal_contact]
    type = GapConductanceConstraint
    variable = thermal_lm
    secondary_variable = temp
    k = 1
    use_displaced_mesh = true
    primary_boundary = plank_right
    primary_subdomain = frictionless_primary_subdomain
    secondary_boundary = block_left
    secondary_subdomain = frictionless_secondary_subdomain
    displacements = 'disp_x disp_y'
  []
[]
[BCs]
  [left_temp]
    type = ADDirichletBC
    variable = temp
    boundary = 'plank_left'
    value = 400
  []
  [right_temp]
    type = ADDirichletBC
    variable = temp
    boundary = 'block_right'
    value = 300
  []
  [left_x]
    type = ADDirichletBC
    variable = disp_x
    boundary = plank_left
    value = 0.0
  []
  [left_y]
    type = ADDirichletBC
    variable = disp_y
    boundary = plank_bottom
    value = 0.0
  []
  [right_x]
    type = ADFunctionDirichletBC
    variable = disp_x
    boundary = block_right
    function = '-0.04*sin(4*(t+1.5))+0.02'
    preset = false
  []
  [right_y]
    type = ADFunctionDirichletBC
    variable = disp_y
    boundary = block_right
    function = '-t'
    preset = false
  []
[]
[Materials]
  [plank]
    type = ADComputeIsotropicElasticityTensor
    block = 'plank'
    poissons_ratio = 0.3
    youngs_modulus = ${E_plank}
  []
  [block]
    type = ADComputeIsotropicElasticityTensor
    block = 'block'
    poissons_ratio = 0.3
    youngs_modulus = ${E_block}
  []
  [stress]
    type = ADComputeFiniteStrainElasticStress
    block = 'plank block'
  []
  [heat_plank]
    type = ADHeatConductionMaterial
    block = plank
    thermal_conductivity = 2
    specific_heat = 1
  []
  [heat_block]
    type = ADHeatConductionMaterial
    block = block
    thermal_conductivity = 1
    specific_heat = 1
  []
[]
[Executioner]
  type = Transient
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -snes_max_it'
  petsc_options_value = 'lu       NONZERO               1e-15                   20'
  end_time = 13.5
  dt = 0.1
  dtmin = 0.1
  timestep_tolerance = 1e-6
  line_search = 'none'
[]
[Postprocessors]
  [nl_its]
    type = NumNonlinearIterations
  []
  [total_nl_its]
    type = CumulativeValuePostprocessor
    postprocessor = nl_its
  []
  [l_its]
    type = NumLinearIterations
  []
  [total_l_its]
    type = CumulativeValuePostprocessor
    postprocessor = l_its
  []
  [contact]
    type = ContactDOFSetSize
    variable = frictionless_normal_lm
    subdomain = frictionless_secondary_subdomain
  []
  [avg_hydro]
    type = ElementAverageValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [avg_temp]
    type = ElementAverageValue
    variable = temp
    block = 'block'
  []
  [max_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [min_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
    value_type = min
  []
  [avg_vonmises]
    type = ElementAverageValue
    variable = vonmises_stress
    block = 'block'
  []
  [max_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
  []
  [min_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
    value_type = min
  []
[]
[Outputs]
  file_base = ${name}
  [comp]
    type = CSV
    show = 'contact avg_temp'
  []
  [out]
    type = CSV
    file_base = '${name}_out'
  []
  [dof]
    type = DOFMap
    execute_on = 'initial'
  []
[]
[Debug]
  show_var_residual_norms = true
[]
(modules/contact/test/tests/mortar_dynamics/block-dynamics.i)
starting_point = 2e-1
offset = -0.19
[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
  []
[]
[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]
  [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]
  [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_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = 20
    secondary_boundary = 10
    primary_subdomain = 4
    secondary_subdomain = 3
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeDynamicWeightedGapLMMechanicalContact
    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
    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_gap_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_gap_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 = 50
    function = '1e-2 * t'
  []
[]
[Executioner]
  type = Transient
  end_time = 75
  dt = 0.05
  dtmin = .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 = 20
  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/simple_contact/two_block_compress/two_equal_blocks_compress_3d_pg.i)
[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  volumetric_locking_correction = true
[]
[Mesh]
  [left_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 1
    ny = 1
    nz = 1
    xmin = -1.0
    xmax = 0.0
    ymin = -0.5
    ymax = 0.5
    zmin = -0.5
    zmax = 0.5
    elem_type = HEX8
  []
  [left_block_sidesets]
    type = RenameBoundaryGenerator
    input = left_block
    old_boundary = '0 1 2 3 4 5'
    new_boundary = 'left_bottom left_back left_right left_front left_left left_top'
  []
  [left_block_id]
    type = SubdomainIDGenerator
    input = left_block_sidesets
    subdomain_id = 1
  []
  [right_block]
    type = GeneratedMeshGenerator
    dim = 3
    nx = 2
    ny = 2
    nz = 2
    xmin = 0.0
    xmax = 1.0
    ymin = -0.5
    ymax = 0.5
    zmin = -0.5
    zmax = 0.5
    elem_type = HEX8
  []
  [right_block_sidesets]
    type = RenameBoundaryGenerator
    input = right_block
    old_boundary = '0 1 2 3 4 5'
    # new_boundary = 'right_bottom right_back right_right right_front right_left right_top'
    new_boundary = '100 101 102 103 104 105'
  []
  [right_block_sidesets_rename]
    type = RenameBoundaryGenerator
    input = right_block_sidesets
    old_boundary = '100 101 102 103 104 105'
    new_boundary = 'right_bottom right_back right_right right_front right_left right_top'
  []
  [right_block_id]
    type = SubdomainIDGenerator
    input = right_block_sidesets_rename
    subdomain_id = 2
  []
  [combined_mesh]
    type = MeshCollectionGenerator
    inputs = 'left_block_id right_block_id'
  []
  [left_lower]
    type = LowerDBlockFromSidesetGenerator
    input = combined_mesh
    sidesets = 'left_right'
    new_block_id = '10001'
    new_block_name = 'secondary_lower'
  []
  [right_lower]
    type = LowerDBlockFromSidesetGenerator
    input = left_lower
    sidesets = 'right_left'
    new_block_id = '10000'
    new_block_name = 'primary_lower'
  []
[]
[Variables]
  [normal_lm]
    block = 'secondary_lower'
    use_dual = true
  []
[]
[AuxVariables]
  [aux_lm]
    block = 'secondary_lower'
    use_dual = false
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [all]
    strain = FINITE
    incremental = true
    add_variables = true
    block = '1 2'
  []
[]
[Functions]
  [horizontal_movement]
    type = PiecewiseLinear
    x = '0 0.5'
    y = '0 0.2'
  []
  [vertical_movement]
    type = PiecewiseLinear
    x = '0 1.0'
    y = '0 0'
  []
[]
[BCs]
  [push_left_x]
    type = FunctionDirichletBC
    variable = disp_x
    boundary = 'left_left'
    function = horizontal_movement
  []
  [push_left_y]
    type = FunctionDirichletBC
    variable = disp_y
    boundary = 'left_left'
    function = vertical_movement
  []
  [fix_left_z]
    type = DirichletBC
    variable = disp_z
    boundary = 'left_left'
    value = 0.0
  []
  [fix_right_x]
    type = DirichletBC
    variable = disp_x
    boundary = 'right_right'
    value = 0.0
  []
  [fix_right_y]
    type = DirichletBC
    variable = disp_y
    boundary = 'right_right'
    value = 0.0
  []
  [fix_right_z]
    type = DirichletBC
    variable = disp_z
    boundary = 'right_right'
    value = 0.0
  []
[]
[Materials]
  [elasticity_tensor_left]
    type = ComputeIsotropicElasticityTensor
    block = 1
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_left]
    type = ComputeFiniteStrainElasticStress
    block = 1
  []
  [elasticity_tensor_right]
    type = ComputeIsotropicElasticityTensor
    block = 2
    youngs_modulus = 1.0e6
    poissons_ratio = 0.3
  []
  [stress_right]
    type = ComputeFiniteStrainElasticStress
    block = 2
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = '23'
    secondary_boundary = '11'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    correct_edge_dropping = true
    lm_variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_petrov_galerkin = true
    aux_lm = aux_lm
  []
[]
[Constraints]
  [normal_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    disp_x = disp_x
    disp_y = disp_y
    disp_z = disp_z
    use_displaced_mesh = true
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_z]
    type = NormalMortarMechanicalContact
    primary_boundary = 'right_left'
    secondary_boundary = 'left_right'
    primary_subdomain = 'primary_lower'
    secondary_subdomain = 'secondary_lower'
    variable = normal_lm
    secondary_variable = disp_z
    component = z
    use_displaced_mesh = true
    compute_lm_residuals = false
    correct_edge_dropping = true
    weighted_gap_uo = weighted_gap_uo
  []
[]
[Preconditioning]
  [SMP]
    type = SMP
    full = true
  []
[]
[Executioner]
  type = Transient
  solve_type = 'PJFNK'
  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-10'
  line_search = 'none'
  dt = 0.1
  dtmin = 0.01
  end_time = 0.4
  l_max_its = 20
  nl_max_its = 20
  nl_rel_tol = 1e-6
  nl_abs_tol = 1e-8
  snesmf_reuse_base = false
[]
[Outputs]
  csv = true
  execute_on = 'FINAL'
[]
[Postprocessors]
  [contact]
    type = ContactDOFSetSize
    variable = normal_lm
    subdomain = 'secondary_lower'
  []
  [normal_lm]
    type = ElementAverageValue
    variable = normal_lm
    block = 'secondary_lower'
  []
  [avg_disp_x]
    type = ElementAverageValue
    variable = disp_x
    block = '1 2'
  []
  [avg_disp_y]
    type = ElementAverageValue
    variable = disp_y
    block = '1 2'
  []
  [max_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
  []
  [max_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
  []
  [min_disp_x]
    type = ElementExtremeValue
    variable = disp_x
    block = '1 2'
    value_type = min
  []
  [min_disp_y]
    type = ElementExtremeValue
    variable = disp_y
    block = '1 2'
    value_type = min
  []
[]
(modules/combined/test/tests/gap_heat_transfer_mortar/finite-2d-rz/finite.i)
E_block = 1e7
E_plank = 1e7
elem = QUAD4
order = FIRST
name = 'finite'
[Mesh]
  patch_size = 80
  patch_update_strategy = auto
  coord_type = RZ
  [plank]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0
    xmax = 0.6
    ymin = -10
    ymax = 10
    nx = 2
    ny = 67
    elem_type = ${elem}
    boundary_name_prefix = plank
  []
  [plank_id]
    type = SubdomainIDGenerator
    input = plank
    subdomain_id = 1
  []
  [block]
    type = GeneratedMeshGenerator
    dim = 2
    xmin = 0.61
    xmax = 1.21
    ymin = 7.7
    ymax = 8.5
    nx = 3
    ny = 4
    elem_type = ${elem}
    boundary_name_prefix = block
    boundary_id_offset = 10
  []
  [block_id]
    type = SubdomainIDGenerator
    input = block
    subdomain_id = 2
  []
  [combined]
    type = MeshCollectionGenerator
    inputs = 'plank_id block_id'
  []
  [block_rename]
    type = RenameBlockGenerator
    input = combined
    old_block = '1 2'
    new_block = 'plank block'
  []
  [secondary]
    input = block_rename
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'block_left'
    new_block_id = '30'
    new_block_name = 'frictionless_secondary_subdomain'
  []
  [primary]
    input = secondary
    type = LowerDBlockFromSidesetGenerator
    sidesets = 'plank_right'
    new_block_id = '20'
    new_block_name = 'frictionless_primary_subdomain'
  []
[]
[GlobalParams]
  displacements = 'disp_x disp_y'
[]
[Variables]
  [disp_x]
    order = ${order}
    block = 'plank block'
    scaling = ${fparse 2.0 / (E_plank + E_block)}
  []
  [disp_y]
    order = ${order}
    block = 'plank block'
    scaling = ${fparse 2.0 / (E_plank + E_block)}
  []
  [temp]
    order = ${order}
    block = 'plank block'
    scaling = 1e-1
  []
  [thermal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    scaling = 1e-7
  []
  [frictionless_normal_lm]
    order = ${order}
    block = 'frictionless_secondary_subdomain'
    use_dual = true
  []
[]
[Physics/SolidMechanics/QuasiStatic]
  [action]
    generate_output = 'stress_xx stress_yy stress_zz vonmises_stress hydrostatic_stress strain_xx strain_yy strain_zz'
    block = 'plank block'
    use_automatic_differentiation = true
    strain = FINITE
  []
[]
[Kernels]
  [hc]
    type = ADHeatConduction
    variable = temp
    use_displaced_mesh = true
    block = 'plank block'
  []
[]
[UserObjects]
  [weighted_gap_uo]
    type = LMWeightedGapUserObject
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    lm_variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
  []
[]
[Constraints]
  [weighted_gap_lm]
    type = ComputeWeightedGapLMMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    disp_x = disp_x
    disp_y = disp_y
    use_displaced_mesh = true
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_x]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_x
    component = x
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [normal_y]
    type = NormalMortarMechanicalContact
    primary_boundary = plank_right
    secondary_boundary = block_left
    primary_subdomain = frictionless_primary_subdomain
    secondary_subdomain = frictionless_secondary_subdomain
    variable = frictionless_normal_lm
    secondary_variable = disp_y
    component = y
    use_displaced_mesh = true
    compute_lm_residuals = false
    weighted_gap_uo = weighted_gap_uo
  []
  [thermal_contact]
    type = GapConductanceConstraint
    variable = thermal_lm
    secondary_variable = temp
    k = 1
    use_displaced_mesh = true
    primary_boundary = plank_right
    primary_subdomain = frictionless_primary_subdomain
    secondary_boundary = block_left
    secondary_subdomain = frictionless_secondary_subdomain
    displacements = 'disp_x disp_y'
  []
[]
[BCs]
  [left_temp]
    type = DirichletBC
    variable = temp
    boundary = 'plank_left'
    value = 400
  []
  [right_temp]
    type = DirichletBC
    variable = temp
    boundary = 'block_right'
    value = 300
  []
  [left_x]
    type = DirichletBC
    variable = disp_x
    boundary = plank_left
    value = 0.0
  []
  [left_y]
    type = DirichletBC
    variable = disp_y
    boundary = plank_bottom
    value = 0.0
  []
  [right_x]
    type = ADFunctionDirichletBC
    variable = disp_x
    boundary = block_right
    function = '-0.04*sin(4*(t+1.5))+0.02'
    preset = false
  []
  [right_y]
    type = ADFunctionDirichletBC
    variable = disp_y
    boundary = block_right
    function = '-t'
    preset = false
  []
[]
[Materials]
  [plank]
    type = ADComputeIsotropicElasticityTensor
    block = 'plank'
    poissons_ratio = 0.3
    youngs_modulus = ${E_plank}
  []
  [block]
    type = ADComputeIsotropicElasticityTensor
    block = 'block'
    poissons_ratio = 0.3
    youngs_modulus = ${E_block}
  []
  [stress]
    type = ADComputeFiniteStrainElasticStress
    block = 'plank block'
  []
  [heat_plank]
    type = ADHeatConductionMaterial
    block = plank
    thermal_conductivity = 2
    specific_heat = 1
  []
  [heat_block]
    type = ADHeatConductionMaterial
    block = block
    thermal_conductivity = 1
    specific_heat = 1
  []
[]
[Executioner]
  type = Transient
  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -snes_max_it'
  petsc_options_value = 'lu       NONZERO               1e-15                   20'
  end_time = 13.5
  dt = 0.1
  dtmin = 0.1
  timestep_tolerance = 1e-6
  line_search = 'none'
[]
[Postprocessors]
  [nl_its]
    type = NumNonlinearIterations
  []
  [total_nl_its]
    type = CumulativeValuePostprocessor
    postprocessor = nl_its
  []
  [l_its]
    type = NumLinearIterations
  []
  [total_l_its]
    type = CumulativeValuePostprocessor
    postprocessor = l_its
  []
  [contact]
    type = ContactDOFSetSize
    variable = frictionless_normal_lm
    subdomain = frictionless_secondary_subdomain
  []
  [avg_hydro]
    type = ElementAverageValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [avg_temp]
    type = ElementAverageValue
    variable = temp
    block = 'block'
  []
  [max_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
  []
  [min_hydro]
    type = ElementExtremeValue
    variable = hydrostatic_stress
    block = 'block'
    value_type = min
  []
  [avg_vonmises]
    type = ElementAverageValue
    variable = vonmises_stress
    block = 'block'
  []
  [max_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
  []
  [min_vonmises]
    type = ElementExtremeValue
    variable = vonmises_stress
    block = 'block'
    value_type = min
  []
[]
[Outputs]
  file_base = ${name}
  [comp]
    type = CSV
    show = 'contact avg_temp'
  []
  [out]
    type = CSV
    file_base = '${name}_out'
  []
[]
[Debug]
  show_var_residual_norms = true
[]
(modules/contact/include/userobjects/LMWeightedVelocitiesUserObject.h)
// This file is part of the MOOSE framework
// https://mooseframework.inl.gov
//
// All rights reserved, see COPYRIGHT for full restrictions
// https://github.com/idaholab/moose/blob/master/COPYRIGHT
//
// Licensed under LGPL 2.1, please see LICENSE for details
// https://www.gnu.org/licenses/lgpl-2.1.html
#pragma once
#include "WeightedVelocitiesUserObject.h"
#include "LMWeightedGapUserObject.h"
template <typename>
class MooseVariableFE;
/**
 * Nodal-based mortar contact user object for frictional problem
 */
class LMWeightedVelocitiesUserObject : public WeightedVelocitiesUserObject,
                                       public LMWeightedGapUserObject
{
public:
  static InputParameters validParams();
  LMWeightedVelocitiesUserObject(const InputParameters & parameters);
  virtual const ADVariableValue & contactTangentialPressureDirOne() const override;
  virtual const ADVariableValue & contactTangentialPressureDirTwo() const override;
protected:
  /// The Lagrange multiplier variables representing the tangential contact pressure
  const MooseVariableFE<Real> * const _lm_variable_tangential_one;
  const MooseVariableFE<Real> * const _lm_variable_tangential_two;
};