17#include "metaphysicl/metaphysicl_version.h"
18#include "metaphysicl/dualsemidynamicsparsenumberarray.h"
19#include "metaphysicl/parallel_dualnumber.h"
20#if METAPHYSICL_MAJOR_VERSION < 2
21#include "metaphysicl/parallel_dynamic_std_array_wrapper.h"
23#include "metaphysicl/parallel_dynamic_array_wrapper.h"
25#include "metaphysicl/parallel_semidynamicsparsenumberarray.h"
36 params.
addClassDescription(
"Computes the tangential frictional forces for dynamic simulations");
39 "The frictional Lagrange's multiplier for an addtional direction.");
42 "Coupled function to evaluate friction with values from contact pressure and relative "
43 "tangential velocities (from the previous step).");
44 params.
addParam<Real>(
"c_t", 1e0,
"Numerical parameter for tangential constraints");
48 "Minimum value of contact pressure that will trigger frictional enforcement");
49 params.
addParam<Real>(
"mu",
"The friction coefficient for the Coulomb friction law");
50 MooseEnum friction_projection_degree(
"ONE TWO",
"TWO");
51 friction_projection_degree.addDocumentation(
52 "ONE",
"Use the degree-one Alart-Curnier friction residual.");
53 friction_projection_degree.addDocumentation(
54 "TWO",
"Use the degree-two Hueber-Stadler-Wohlmuth friction residual.");
56 "friction_projection_degree",
57 friction_projection_degree,
58 "Degree of the friction-residual projection; see MortarContactUtils.h.");
65 _c_t(getParam<Real>(
"c_t")),
66 _friction_projection_degree(getParam<
MooseEnum>(
"friction_projection_degree")
67 .getEnum<
Moose::Mortar::Contact::FrictionProjectionDegree>()),
68 _secondary_x_dot(_secondary_var.adUDot()),
69 _primary_x_dot(_primary_var.adUDotNeighbor()),
70 _secondary_y_dot(adCoupledDot(
"disp_y")),
71 _primary_y_dot(adCoupledNeighborValueDot(
"disp_y")),
72 _secondary_z_dot(_has_disp_z ? &adCoupledDot(
"disp_z") : nullptr),
73 _primary_z_dot(_has_disp_z ? &adCoupledNeighborValueDot(
"disp_z") : nullptr),
74 _epsilon(getParam<Real>(
"epsilon")),
75 _mu(isParamValid(
"mu") ? getParam<Real>(
"mu") :
std::numeric_limits<double>::quiet_NaN()),
76 _function_friction(isParamValid(
"function_friction") ? &getFunction(
"function_friction")
78 _has_friction_function(isParamValid(
"function_friction")),
83 "A coefficient of friction needs to be provided as a constant value of via a function.");
87 "Either provide a constant coefficient of friction or a function defining the "
88 "coefficient of friction. Both inputs cannot be provided simultaneously.");
90 if (!getParam<bool>(
"use_displaced_mesh"))
92 "'use_displaced_mesh' must be true for the "
93 "ComputeFrictionalForceLMMechanicalContact object");
97 "Three-dimensional mortar frictional contact simulations require an additional "
98 "frictional Lagrange's multiplier to enforce a second tangential pressure");
109 "Frictional contact constraints only support elemental variables of CONSTANT order");
136 const DofObject *
const dof =
146 nodal_tangents[0][
_i];
156 nodal_tangents[1][
_i];
202 const DofObject *
const dof = pr.first;
227 const std::unordered_set<const Node *> & inactive_lm_nodes)
241 const DofObject *
const dof = pr.first;
244 if ((inactive_lm_nodes.find(
static_cast<const Node *
>(dof)) != inactive_lm_nodes.end()) ||
265 const DofObject *
const dof)
275 std::array<dof_id_type, 2> friction_dof_indices;
276 std::array<ADReal, 2> friction_lm_values;
278 const unsigned int num_tangents = 2;
279 for (
const auto i : make_range(num_tangents))
290 const Real contact_pressure_old =
_sys.
solutionOld()(normal_dof_index);
297 const std::array<ADReal, 2> tangential_velocity{{*tangential_vel[0], *tangential_vel[1]}};
299 const auto residual =
309 const ADReal dof_residual = residual[0];
310 const ADReal dof_residual_dir = residual[1];
313 std::array<ADReal, 1>{{dof_residual}},
314 std::array<dof_id_type, 1>{{friction_dof_indices[0]}},
317 std::array<ADReal, 1>{{dof_residual_dir}},
318 std::array<dof_id_type, 1>{{friction_dof_indices[1]}},
324 const DofObject *
const dof)
338 const Real contact_pressure_old =
_sys.
solutionOld()(normal_dof_index);
348 const std::array<ADReal, 1> tangential_pressure{{friction_lm_value}};
349 const std::array<ADReal, 1> tangential_velocity{{tangential_vel}};
351 const ADReal dof_residual =
363 std::array<ADReal, 1>{{dof_residual}},
364 std::array<dof_id_type, 1>{{friction_dof_index}},
370 const ADReal & contact_pressure,
const Real & tangential_vel,
const Real & tangential_vel_dir)
381 ADReal tangential_vel_magnitude =
382 sqrt(tangential_vel * tangential_vel + tangential_vel_dir * tangential_vel_dir + 1.0e-24);
DualNumber< Real, DNDerivativeType, true > ADReal
std::array< MooseUtils::SemidynamicVector< Point, 9 >, 2 > getNodalTangents(const Elem &secondary_elem) const
MooseVariable * getVar(const std::string &var_name, unsigned int comp)
virtual Real value(Real t, const Point &p) const
void paramError(const std::string ¶m, Args... args) const
void mooseError(Args &&... args) const
bool isParamValid(const std::string &name) const
unsigned int number() const
MooseVariable *const _var
const MooseArray< Real > & _coord
const VariableTestValue & _test
Elem const *const & _lower_secondary_elem
const AutomaticMortarGeneration & amg() const
const std::vector< Real > & _JxW_msm
virtual const NumericVector< Number > *const & currentSolution() const=0
unsigned int number() const
NumericVector< Number > & solutionOld()
void addResidualsAndJacobian(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
const Parallel::Communicator & _communicator
processor_id_type processor_id() const
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N > > &derivs, libMesh::dof_id_type index, Real value)