16#include "metaphysicl/metaphysicl_version.h"
17#include "metaphysicl/dualsemidynamicsparsenumberarray.h"
18#include "metaphysicl/parallel_dualnumber.h"
19#if METAPHYSICL_MAJOR_VERSION < 2
20#include "metaphysicl/parallel_dynamic_std_array_wrapper.h"
22#include "metaphysicl/parallel_dynamic_array_wrapper.h"
24#include "metaphysicl/parallel_semidynamicsparsenumberarray.h"
38 "The frictional Lagrange's multiplier for an addtional direction.");
41 "Coupled function to evaluate friction with values from contact pressure and relative "
42 "tangential velocities");
43 params.
addParam<Real>(
"c_t", 1e0,
"Numerical parameter for tangential constraints");
47 "Minimum value of contact pressure that will trigger frictional enforcement");
49 "mu",
"mu > 0",
"The friction coefficient for the Coulomb friction law");
51 "The weighted tangential velocities user object.");
52 MooseEnum friction_projection_degree(
"ONE TWO",
"TWO");
53 friction_projection_degree.addDocumentation(
54 "ONE",
"Use the degree-one Alart-Curnier friction residual.");
55 friction_projection_degree.addDocumentation(
56 "TWO",
"Use the degree-two Hueber-Stadler-Wohlmuth friction residual.");
58 "friction_projection_degree",
59 friction_projection_degree,
60 "Degree of the friction-residual projection; see MortarContactUtils.h.");
69 _c_t(getParam<Real>(
"c_t")),
70 _friction_projection_degree(getParam<
MooseEnum>(
"friction_projection_degree")
71 .getEnum<
Moose::Mortar::Contact::FrictionProjectionDegree>()),
72 _secondary_x_dot(_secondary_var.adUDot()),
73 _primary_x_dot(_primary_var.adUDotNeighbor()),
74 _secondary_y_dot(adCoupledDot(
"disp_y")),
75 _primary_y_dot(adCoupledNeighborValueDot(
"disp_y")),
76 _secondary_z_dot(_has_disp_z ? &adCoupledDot(
"disp_z") : nullptr),
77 _primary_z_dot(_has_disp_z ? &adCoupledNeighborValueDot(
"disp_z") : nullptr),
78 _epsilon(getParam<Real>(
"epsilon")),
79 _mu(isParamValid(
"function_friction") ?
std::numeric_limits<double>::quiet_NaN()
80 : getParam<Real>(
"mu")),
81 _function_friction(isParamValid(
"function_friction") ? &getFunction(
"function_friction")
83 _has_friction_function(isParamValid(
"function_friction")),
89 "Nodal-normal derivatives are not supported by user object '",
98 "'weighted_velocities_uo' must be defined on the same secondary/primary subdomain "
99 "pair as this constraint when nodal-normal derivatives are enabled.");
101 const std::array<std::pair<const MooseVariable *, unsigned int>, 3>
103 for (
const auto & [
variable, component] : velocity_displacement_variables)
106 "'weighted_velocities_uo' must use the same displacement variables as this "
107 "constraint when nodal-normal derivatives are enabled.");
112 "Please only provide friction either as a function or as a constant value, but not both.");
114 paramError(
"mu",
"Please provide a value or a function for the coefficient of friction.");
116 if (!getParam<bool>(
"use_displaced_mesh"))
118 "'use_displaced_mesh' must be true for the "
119 "ComputeFrictionalForceLMMechanicalContact object");
123 "Three-dimensional mortar frictional contact simulations require an additional "
124 "frictional Lagrange's multiplier to enforce a second tangential pressure");
135 "Frictional contact constraints only support elemental variables of CONSTANT order");
156 const auto & dof_to_weighted_tangential_velocity =
159 const std::unordered_map<const DofObject *, std::pair<ADReal, Real>> & dof_to_weighted_gap =
164 for (
const auto & [dof_object, weighted_velocities_pr] : dof_to_weighted_tangential_velocity)
169 const auto & [weighted_gap_pr, normalization] =
170 libmesh_map_find(dof_to_weighted_gap, dof_object);
187 const std::unordered_set<const Node *> & inactive_lm_nodes)
189 const auto & dof_to_weighted_tangential_velocity =
193 for (
const auto & [dof_object, weighted_velocities_pr] : dof_to_weighted_tangential_velocity)
196 if ((inactive_lm_nodes.find(
static_cast<const Node *
>(dof_object)) !=
197 inactive_lm_nodes.end()) ||
230 std::array<dof_id_type, 2> friction_dof_indices;
231 std::array<ADReal, 2> friction_lm_values;
233 const unsigned int num_tangents = 2;
234 for (
const auto i : make_range(num_tangents))
253 const std::array<ADReal, 2> tangential_velocity{{*tangential_vel[0], *tangential_vel[1]}};
255 const auto residual =
265 const ADReal dof_residual = residual[0];
266 const ADReal dof_residual_dir = residual[1];
269 std::array<ADReal, 1>{{dof_residual}},
270 std::array<dof_id_type, 1>{{friction_dof_indices[0]}},
273 std::array<ADReal, 1>{{dof_residual_dir}},
274 std::array<dof_id_type, 1>{{friction_dof_indices[1]}},
305 const std::array<ADReal, 1> tangential_pressure{{friction_lm_value}};
306 const std::array<ADReal, 1> tangential_velocity{{tangential_vel}};
308 const ADReal dof_residual =
320 std::array<ADReal, 1>{{dof_residual}},
321 std::array<dof_id_type, 1>{{friction_dof_index}},
327 const ADReal & tangential_vel,
328 const ADReal & tangential_vel_dir)
339 ADReal tangential_vel_magnitude =
340 sqrt(tangential_vel * tangential_vel + tangential_vel_dir * tangential_vel_dir + 1.0e-24);
DualNumber< Real, DNDerivativeType, true > ADReal
MooseVariable * getVar(const std::string &var_name, unsigned int comp)
virtual Real value(Real t, const Point &p) const
const InputParameters & parameters() const
const std::string & name() const
void paramError(const std::string ¶m, Args... args) const
bool isParamValid(const std::string &name) const
unsigned int number() const
MooseVariable *const _var
const MooseVariable & variable() const override
SubdomainID primarySubdomain() const
SubdomainID secondarySubdomain() const
virtual const NumericVector< Number > *const & currentSolution() const=0
unsigned int number() const
void addResidualsAndJacobian(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
virtual bool usesNodalNormalDerivatives() const =0
Whether this formulation includes displacement derivatives of the secondary nodal normals.
const std::unordered_map< const DofObject *, std::pair< ADReal, Real > > & dofToWeightedGap() const
Get the degree of freedom to weighted gap information.
virtual Real nodalScale(const DofObject *const) const
Node-based Lagrange-multiplier scaling factor kappa_j of Popp et al.
const MooseVariable * dispVar(unsigned int component) const
Creates dof object to weighted tangential velocities map.
const std::unordered_map< const DofObject *, std::array< ADReal, 2 > > & dofToWeightedVelocities() const
Get the degree of freedom to weighted velocities information.
processor_id_type processor_id() const
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N > > &derivs, libMesh::dof_id_type index, Real value)