idaholab/moose: contact coverage diff

Base 4fcf7b Head #33358 34476d
Total Total +/- New
Rate 91.27% 91.38% +0.12% 100.00%
Hits 5005 5081 +76 129
Misses 479 479 - 0
Filename Stmts Miss Cover
modules/contact/include/userobjects/WeightedVelocitiesUserObject.h +1 0 +100.00%
modules/contact/include/utils/ContactFrictionUtils.h +11 +1 +90.91%
modules/contact/src/actions/ContactAction.C +23 0 +0.13%
modules/contact/src/constraints/ComputeDynamicFrictionalForceLMMechanicalContact.C +22 -1 +1.32%
modules/contact/src/constraints/ComputeFrictionalForceLMMechanicalContact.C +19 0 +1.07%
TOTAL +76 0 +0.12%
code
coverage unchanged
code
coverage increased
code
coverage decreased
+
line added or modified

modules/contact/include/userobjects/WeightedVelocitiesUserObject.h

117  
118  
119  
120 +
121  
122  
inline const std::unordered_map<const DofObject *, std::array<ADReal, 2>> &
WeightedVelocitiesUserObject::dofToRealVelocities() const
{
  return _dof_to_real_tangential_velocity;
}

modules/contact/include/utils/ContactFrictionUtils.h

22  
23  
24  
25 +
26  
27  
28 +
29  
30 +
31 +
32 +
33  
34  
35 +
36 +
37  
38  
39  
40 +
41  
42  
43  
namespace Contact
{

CreateMooseEnumClass(FrictionCoefficientRegularization, NONE, ARCTAN_SLIP);

inline MooseEnum
frictionCoefficientRegularizationOptions()
{
  MooseEnum options(getFrictionCoefficientRegularizationOptions(), "NONE");
  options.addDocumentation("NONE", "Use the supplied Coulomb friction coefficient.");
  options.addDocumentation(
      "ARCTAN_SLIP",
      "Scale the Coulomb friction coefficient by an arctangent function of the slip increment.");
  return options;
}

template <typename TMu, typename TSlip>
auto
regularizedFrictionCoefficient(const TMu & mu,
                               const TSlip & slip_increment,
                               const FrictionCoefficientRegularization regularization,
                               const Real reference_slip) -> decltype(mu + mu * slip_increment)
45  
46  
47  
48 +
49 +
50  
51  
52  
53  
54 +
55  
56  
57  
  using std::atan;
  using Result = decltype(mu + mu * slip_increment);

  if (regularization == FrictionCoefficientRegularization::NONE)
    return Result(mu);

  mooseAssert(reference_slip > 0.0,
              "Friction coefficient regularization requires a positive reference slip");

  return mu * (2.0 / libMesh::pi) * atan(slip_increment / reference_slip);
}

} // namespace Contact

modules/contact/src/actions/ContactAction.C

141  
142  
143  
144 +
145 +
146  
147 +
148  
149 +
150  
151  
152 +
153  
154 +
155  
156  
157  
      "iterations for penalizing relative slip distance if the node is under stick conditions.(a "
      "value larger than one, e.g., 10, tends to speed up convergence.)");
  params.addParam<Real>("friction_coefficient", 0, "The friction coefficient");
  params.addParam<MooseEnum>("friction_coefficient_regularization",
                             Moose::Contact::frictionCoefficientRegularizationOptions(),
                             "The regularization applied to the Coulomb friction coefficient.");
  params.addRangeCheckedParam<Real>(
      "friction_reference_slip",
      0.0,
      "friction_reference_slip >= 0",
      "Reference slip increment used by friction coefficient regularization.");
  params.addRangeCheckedParam<Real>(
      "friction_elastic_slip",
      0.0,
      "friction_elastic_slip >= 0",
      "Tangential elastic slip distance over which the Coulomb friction bound is reached.");
  params.addParam<Real>("tension_release",
343  
344  
345  
346 +
347  
348  
349  
      "adaptivity_penalty_normal adaptivity_penalty_friction",
      "Augmented Lagrange");
  // Friction
  params.addParamNamesToGroup(
      "friction_coefficient friction_coefficient_regularization friction_reference_slip "
      "friction_elastic_slip tension_release",
      "Friction");
422  
423  
424  
425 +
426  
427  
428 +
429 +
430 +
431  
432 +
433 +
434  
435  
436 +
437 +
438 +
439  
440  
441  
442 +
443 +
444 +
445 +
446  
447  
448  
               "The 'tangential_penalty' formulation can only be used with the 'coulomb' model");

  const auto friction_coefficient_regularization =
      getParam<MooseEnum>("friction_coefficient_regularization")
          .getEnum<Moose::Contact::FrictionCoefficientRegularization>();
  const bool has_friction_regularization =
      params.isParamSetByUser("friction_elastic_slip") ||
      params.isParamSetByUser("friction_coefficient_regularization") ||
      params.isParamSetByUser("friction_reference_slip");

  if (_model != ContactModel::COULOMB && has_friction_regularization)
    paramError("model",
               "The friction regularization options can only be used with the 'coulomb' model.");

  if (_model == ContactModel::COULOMB && has_friction_regularization &&
      !supportsFrictionRegularization(_formulation))
    paramError("formulation",
               "The friction regularization options are only supported with the 'mortar' "
               "formulation.");

  if (friction_coefficient_regularization !=
          Moose::Contact::FrictionCoefficientRegularization::NONE &&
      getParam<Real>("friction_reference_slip") <= 0.0)
    paramError("friction_reference_slip",
               "A positive friction_reference_slip is required when "
               "friction_coefficient_regularization is not NONE.");

1318  
1319  
1320  
1321 +
1322 +
1323 +
1324 +
1325  
1326  
1327  
            tangential_lagrange_multiplier_3d_name};

      params.set<Real>("mu") = getParam<Real>("friction_coefficient");
      params.set<MooseEnum>("friction_coefficient_regularization") =
          getParam<MooseEnum>("friction_coefficient_regularization");
      params.set<Real>("friction_reference_slip") = getParam<Real>("friction_reference_slip");
      params.set<Real>("friction_elastic_slip") = getParam<Real>("friction_elastic_slip");
      params.applySpecificParameters(parameters(),
                                     {"triangulation",
                                      "triangulate_triangles",

modules/contact/src/constraints/ComputeDynamicFrictionalForceLMMechanicalContact.C

43  
44  
45  
46 +
47  
48  
49  
50  
51 +
52  
53 +
54 +
55  
56 +
57  
58 +
59  
60  
61 +
62  
63 +
64  
65  
66  
      "Coupled function to evaluate friction with values from contact pressure and relative "
      "tangential velocities (from the previous step).");
  params.addParam<Real>("c_t", 1e0, "Numerical parameter for tangential constraints");
  params.addRangeCheckedParam<Real>(
      "epsilon",
      1.0e-7,
      "epsilon > 0",
      "Minimum value of contact pressure that will trigger frictional enforcement");
  params.addRangeCheckedParam<Real>(
      "mu", "mu >= 0", "The friction coefficient for the Coulomb friction law");
  params.addParam<MooseEnum>("friction_coefficient_regularization",
                             Moose::Contact::frictionCoefficientRegularizationOptions(),
                             "The regularization applied to the Coulomb friction coefficient.");
  params.addRangeCheckedParam<Real>(
      "friction_reference_slip",
      0.0,
      "friction_reference_slip >= 0",
      "Reference slip increment used by friction coefficient regularization.");
  params.addRangeCheckedParam<Real>(
      "friction_elastic_slip",
      0.0,
      "friction_elastic_slip >= 0",
      "Tangential elastic slip distance over which the Coulomb friction bound is reached.");
  return params;
78  
79  
80  
81 +
82 +
83  
84 +
85 +
86  
87  
88  
89  
90  
91  
92 +
93  
94  
95  
    _primary_z_dot(_has_disp_z ? &adCoupledNeighborValueDot("disp_z") : nullptr),
    _epsilon(getParam<Real>("epsilon")),
    _mu(isParamValid("mu") ? getParam<Real>("mu") : std::numeric_limits<double>::quiet_NaN()),
    _friction_coefficient_regularization(
        getParam<MooseEnum>("friction_coefficient_regularization")
            .getEnum<Moose::Contact::FrictionCoefficientRegularization>()),
    _friction_reference_slip(getParam<Real>("friction_reference_slip")),
    _friction_elastic_slip(getParam<Real>("friction_elastic_slip")),
    _function_friction(isParamValid("function_friction") ? &getFunction("function_friction")
                                                         : nullptr),
    _has_friction_function(isParamValid("function_friction")),
    _3d(_has_disp_z)
{
  if (!_has_friction_function && !isParamValid("mu"))
    paramError("mu",
               "A coefficient of friction needs to be provided as a constant value or via a "
               "function.");

108  
109  
110  
111 +
112 +
113 +
114 +
115  
116  
117  
               "Three-dimensional mortar frictional contact simulations require an additional "
               "frictional Lagrange's multiplier to enforce a second tangential pressure");

  if (_friction_coefficient_regularization !=
          Moose::Contact::FrictionCoefficientRegularization::NONE &&
      _friction_reference_slip <= 0.0)
    paramError("friction_reference_slip",
               "A positive friction_reference_slip is required when "
               "friction_coefficient_regularization is not NONE.");

160  
161  
162  
163 +
164  
165  
166  
      _test[_i][_qp] * _qp_tangential_velocity_nodal * nodal_tangents[0][_i];

  _dof_to_real_tangential_velocity[dof][0] +=
      _test[_i][_qp] * _qp_real_tangential_velocity_nodal * nodal_tangents[0][_i];

  // Get the _dof_to_weighted_tangential_velocity map for a second direction
  if (_3d)
169  
170  
171  
172 +
173  
174  
175  
        _test[_i][_qp] * _qp_tangential_velocity_nodal * nodal_tangents[1][_i];

    _dof_to_real_tangential_velocity[dof][1] +=
        _test[_i][_qp] * _qp_real_tangential_velocity_nodal * nodal_tangents[1][_i];
  }
}

190  
191  
192  
193 +
194  
195  
196 +
197  
198  
199  

  _dof_to_old_real_tangential_velocity.clear();

  for (const auto & [dof, real_tangential_velocity] : _dof_to_real_tangential_velocity)
    _dof_to_old_real_tangential_velocity.emplace(
        dof,
        std::array<Real, 2>{{MetaPhysicL::raw_value(real_tangential_velocity[0]),
                             MetaPhysicL::raw_value(real_tangential_velocity[1])}});
}

205  
206  
207  
208 +
209 +
210  
211  
212  
  Moose::Mortar::Contact::communicateVelocities(
      _dof_to_weighted_tangential_velocity, _mesh, _nodal, _communicator, false);

  Moose::Mortar::Contact::communicateVelocities(
      _dof_to_real_tangential_velocity, _mesh, _nodal, _communicator, false);

  // Enforce frictional complementarity constraints
  for (const auto & pr : _dof_to_weighted_tangential_velocity)
243  
244  
245  
246 +
247 +
248  
249  
250  
  Moose::Mortar::Contact::communicateVelocities(
      _dof_to_weighted_tangential_velocity, _mesh, _nodal, _communicator, false);

  Moose::Mortar::Contact::communicateVelocities(
      _dof_to_real_tangential_velocity, _mesh, _nodal, _communicator, false);

  // Enforce frictional complementarity constraints
  for (const auto & pr : _dof_to_weighted_tangential_velocity)
304  
305  
306  
307 +
308  
309  
310  
311 +
312  
313  
314 +
315  
316  
317 +
318 +
319 +
320  
321  
322  
323 +
324  
325  
326  

  // Compute the friction coefficient (constant or function)
  const auto & current_real_tangential_velocity =
      libmesh_map_find(_dof_to_real_tangential_velocity, dof);
  const auto old_real_tangential_velocity_it = _dof_to_old_real_tangential_velocity.find(dof);
  const std::array<Real, 2> current_function_real_tangential_velocity{
      {MetaPhysicL::raw_value(current_real_tangential_velocity[0]),
       MetaPhysicL::raw_value(current_real_tangential_velocity[1])}};
  const auto & function_real_tangential_velocity =
      old_real_tangential_velocity_it != _dof_to_old_real_tangential_velocity.end()
          ? old_real_tangential_velocity_it->second
          : current_function_real_tangential_velocity;
  const ADReal slip_increment =
      sqrt(current_real_tangential_velocity[0] * current_real_tangential_velocity[0] +
           current_real_tangential_velocity[1] * current_real_tangential_velocity[1] + 1.0e-24) *
      _dt;
  ADReal mu_ad = computeFrictionValue(contact_pressure_old,
                                      function_real_tangential_velocity[0],
                                      function_real_tangential_velocity[1],
                                      slip_increment);

  ADReal dof_residual;
  ADReal dof_residual_dir;
336  
337  
338  
339 +
340  
341  
342 +
343  
344  
345  
346 +
347 +
348  
349 +
350 +
351  
352  
353 +
354 +
355  
356 +
357  
358 +
359  
360  
361  
    const Real epsilon_sqrt = 1.0e-48;

    const auto lamdba_plus_cg = contact_pressure + c * weighted_gap;
    const auto normal_bound = max(0.0, lamdba_plus_cg);
    const auto friction_bound = mu_ad * normal_bound;
    const auto tangential_compliance =
        _friction_elastic_slip > 0.0 ? _friction_elastic_slip / (friction_bound + _epsilon) : 0.0;

    std::array<ADReal, 2> lambda_t_plus_ctu;
    lambda_t_plus_ctu[0] =
        friction_lm_values[0] +
        c_t * (*tangential_vel[0] * _dt - tangential_compliance * friction_lm_values[0]);
    lambda_t_plus_ctu[1] =
        friction_lm_values[1] +
        c_t * (*tangential_vel[1] * _dt - tangential_compliance * friction_lm_values[1]);

    const auto tangential_trial_norm =
        sqrt(lambda_t_plus_ctu[0] * lambda_t_plus_ctu[0] +
             lambda_t_plus_ctu[1] * lambda_t_plus_ctu[1] + epsilon_sqrt);

    const auto term_1_x = max(friction_bound, tangential_trial_norm) * friction_lm_values[0];

    const auto term_1_y = max(friction_bound, tangential_trial_norm) * friction_lm_values[1];

    const auto term_2_x = friction_bound * lambda_t_plus_ctu[0];

401  
402  
403  
404 +
405  
406  
407  
408 +
409  
410  
411 +
412  
413  
414 +
415 +
416  
417 +
418  
419  
420  

  // Compute the friction coefficient (constant or function)
  const auto & current_real_tangential_velocity =
      libmesh_map_find(_dof_to_real_tangential_velocity, dof);
  const auto old_real_tangential_velocity_it = _dof_to_old_real_tangential_velocity.find(dof);
  const std::array<Real, 2> current_function_real_tangential_velocity{
      {MetaPhysicL::raw_value(current_real_tangential_velocity[0]),
       MetaPhysicL::raw_value(current_real_tangential_velocity[1])}};
  const auto & function_real_tangential_velocity =
      old_real_tangential_velocity_it != _dof_to_old_real_tangential_velocity.end()
          ? old_real_tangential_velocity_it->second
          : current_function_real_tangential_velocity;
  const ADReal slip_increment =
      sqrt(current_real_tangential_velocity[0] * current_real_tangential_velocity[0] + 1.0e-24) *
      _dt;
  ADReal mu_ad = computeFrictionValue(
      contact_pressure_old, function_real_tangential_velocity[0], 0.0, slip_increment);

  ADReal dof_residual;
  // Primal-dual active set strategy (PDASS)
422  
423  
424  
425 +
426 +
427  
428  
429 +
430  
431  
432 +
433  
434 +
435  
436  
437  
    dof_residual = friction_lm_value;
  else
  {
    const auto lambda_plus_cg = contact_pressure + c * weighted_gap;
    const auto normal_bound = max(0.0, lambda_plus_cg);
    const auto friction_bound = mu_ad * normal_bound;
    const auto tangential_compliance =
        _friction_elastic_slip > 0.0 ? _friction_elastic_slip / (friction_bound + _epsilon) : 0.0;
    const auto lambda_t_plus_ctu =
        friction_lm_value +
        c_t * (tangential_vel * _dt - tangential_compliance * friction_lm_value);

    const auto term_1 = max(friction_bound, abs(lambda_t_plus_ctu)) * friction_lm_value;
    const auto term_2 = friction_bound * lambda_t_plus_ctu;

    dof_residual = term_1 - term_2;
460  
461  
462  
463 +
464 +
465  
466  
467  
468  
469  
470 +
471  
472  
  else
  {
    ADReal tangential_vel_magnitude =
        sqrt(function_tangential_vel * function_tangential_vel +
             function_tangential_vel_dir * function_tangential_vel_dir + 1.0e-24);

    mu_ad = _function_friction->value<ADReal>(0.0, contact_pressure, tangential_vel_magnitude, 0.0);
  }

  return Moose::Contact::regularizedFrictionCoefficient(
      mu_ad, slip_increment, _friction_coefficient_regularization, _friction_reference_slip);
}

modules/contact/src/constraints/ComputeFrictionalForceLMMechanicalContact.C

42  
43  
44  
45 +
46  
47  
48  
49  
50  
51  
52 +
53 +
54  
55 +
56  
57 +
58  
59  
60 +
61  
62 +
63  
64  
65  
      "Coupled function to evaluate friction with values from contact pressure and relative "
      "tangential velocities");
  params.addParam<Real>("c_t", 1e0, "Numerical parameter for tangential constraints");
  params.addRangeCheckedParam<Real>(
      "epsilon",
      1.0e-7,
      "epsilon > 0",
      "Minimum value of contact pressure that will trigger frictional enforcement");
  params.addRangeCheckedParam<Real>(
      "mu", "mu >= 0", "The friction coefficient for the Coulomb friction law");
  params.addParam<MooseEnum>("friction_coefficient_regularization",
                             Moose::Contact::frictionCoefficientRegularizationOptions(),
                             "The regularization applied to the Coulomb friction coefficient.");
  params.addRangeCheckedParam<Real>(
      "friction_reference_slip",
      0.0,
      "friction_reference_slip >= 0",
      "Reference slip increment used by friction coefficient regularization.");
  params.addRangeCheckedParam<Real>(
      "friction_elastic_slip",
      0.0,
      "friction_elastic_slip >= 0",
      "Tangential elastic slip distance over which the Coulomb friction bound is reached.");
  params.addRequiredParam<UserObjectName>("weighted_velocities_uo",
82  
83  
84  
85 +
86 +
87  
88 +
89 +
90  
91  
92  
    _epsilon(getParam<Real>("epsilon")),
    _mu(isParamValid("function_friction") ? std::numeric_limits<double>::quiet_NaN()
                                          : getParam<Real>("mu")),
    _friction_coefficient_regularization(
        getParam<MooseEnum>("friction_coefficient_regularization")
            .getEnum<Moose::Contact::FrictionCoefficientRegularization>()),
    _friction_reference_slip(getParam<Real>("friction_reference_slip")),
    _friction_elastic_slip(getParam<Real>("friction_elastic_slip")),
    _function_friction(isParamValid("function_friction") ? &getFunction("function_friction")
                                                         : nullptr),
    _has_friction_function(isParamValid("function_friction")),
110  
111  
112  
113 +
114 +
115 +
116 +
117  
118  
119  
               "Three-dimensional mortar frictional contact simulations require an additional "
               "frictional Lagrange's multiplier to enforce a second tangential pressure");

  if (_friction_coefficient_regularization !=
          Moose::Contact::FrictionCoefficientRegularization::NONE &&
      _friction_reference_slip <= 0.0)
    paramError("friction_reference_slip",
               "A positive friction_reference_slip is required when "
               "friction_coefficient_regularization is not NONE.");

238  
239  
240  
241 +
242  
243 +
244  
245  
246  

  // Compute the friction coefficient (constant or function)
  const auto & real_tangential_velocity =
      libmesh_map_find(_weighted_velocities_uo.dofToRealVelocities(), dof);
  ADReal mu_ad = computeFrictionValue(
      contact_pressure, real_tangential_velocity[0], real_tangential_velocity[1]);

  ADReal dof_residual;
  ADReal dof_residual_dir;
257  
258  
259  
260 +
261  
262  
263 +
264  
265  
266  
267 +
268 +
269  
270 +
271 +
272  
273  
274 +
275 +
276  
277 +
278  
279 +
280  
281  
282  
    const Real epsilon_sqrt = 1.0e-48;

    const auto lamdba_plus_cg = contact_pressure + c * weighted_gap;
    const auto normal_bound = max(0.0, lamdba_plus_cg);
    const auto friction_bound = mu_ad * normal_bound;
    const auto tangential_compliance =
        _friction_elastic_slip > 0.0 ? _friction_elastic_slip / (friction_bound + _epsilon) : 0.0;

    std::array<ADReal, 2> lambda_t_plus_ctu;
    lambda_t_plus_ctu[0] =
        friction_lm_values[0] +
        c_t * (*tangential_vel[0] * _dt - tangential_compliance * friction_lm_values[0]);
    lambda_t_plus_ctu[1] =
        friction_lm_values[1] +
        c_t * (*tangential_vel[1] * _dt - tangential_compliance * friction_lm_values[1]);

    const auto tangential_trial_norm =
        sqrt(lambda_t_plus_ctu[0] * lambda_t_plus_ctu[0] +
             lambda_t_plus_ctu[1] * lambda_t_plus_ctu[1] + epsilon_sqrt);

    const auto term_1_x = max(friction_bound, tangential_trial_norm) * friction_lm_values[0];

    const auto term_1_y = max(friction_bound, tangential_trial_norm) * friction_lm_values[1];

    const auto term_2_x = friction_bound * lambda_t_plus_ctu[0];

321  
322  
323  
324 +
325 +
326  
327  
328  

  // Compute the friction coefficient (constant or function)
  const auto & real_tangential_velocity =
      libmesh_map_find(_weighted_velocities_uo.dofToRealVelocities(), dof);
  ADReal mu_ad = computeFrictionValue(contact_pressure, real_tangential_velocity[0], 0.0);

  ADReal dof_residual;
  // Primal-dual active set strategy (PDASS)
330  
331  
332  
333 +
334 +
335  
336  
337 +
338  
339  
340 +
341  
342 +
343  
344  
345  
    dof_residual = friction_lm_value;
  else
  {
    const auto lambda_plus_cg = contact_pressure + c * weighted_gap;
    const auto normal_bound = max(0.0, lambda_plus_cg);
    const auto friction_bound = mu_ad * normal_bound;
    const auto tangential_compliance =
        _friction_elastic_slip > 0.0 ? _friction_elastic_slip / (friction_bound + _epsilon) : 0.0;
    const auto lambda_t_plus_ctu =
        friction_lm_value +
        c_t * (tangential_vel * _dt - tangential_compliance * friction_lm_value);

    const auto term_1 = max(friction_bound, abs(lambda_t_plus_ctu)) * friction_lm_value;
    const auto term_2 = friction_bound * lambda_t_plus_ctu;

    dof_residual = term_1 - term_2;
371  
372  
373  
374 +
375 +
376  
377 +
378  
379  
  }

  const auto slip_increment =
      sqrt(tangential_vel * tangential_vel + tangential_vel_dir * tangential_vel_dir + 1.0e-24) *
      _dt;
  return Moose::Contact::regularizedFrictionCoefficient(
      mu_ad, slip_increment, _friction_coefficient_regularization, _friction_reference_slip);
}