15#include "metaphysicl/metaphysicl_version.h"
16#include "metaphysicl/dualsemidynamicsparsenumberarray.h"
17#include "metaphysicl/parallel_dualnumber.h"
18#if METAPHYSICL_MAJOR_VERSION < 2
19#include "metaphysicl/parallel_dynamic_std_array_wrapper.h"
21#include "metaphysicl/parallel_dynamic_array_wrapper.h"
23#include "metaphysicl/parallel_semidynamicsparsenumberarray.h"
34 const auto & disp_x_name = ret.
get<std::vector<VariableName>>(
"disp_x");
35 if (disp_x_name.size() != 1)
36 mooseError(
"We require that the disp_x parameter have exactly one coupled name");
39 ret.
set<VariableName>(
"secondary_variable") = disp_x_name[0];
40 ret.
set<VariableName>(
"primary_variable") = disp_x_name[0];
51 params.
addParam<Real>(
"c_t", 1e0,
"Numerical parameter for tangential constraints");
55 "Minimum value of contact pressure that will trigger frictional enforcement");
57 "mu",
"mu > 0",
"The friction coefficient for the Coulomb friction law");
64 _c_t(getParam<Real>(
"c_t")),
65 _secondary_x_dot(adCoupledDot(
"disp_x")),
66 _primary_x_dot(adCoupledNeighborValueDot(
"disp_x")),
67 _secondary_y_dot(adCoupledDot(
"disp_y")),
68 _primary_y_dot(adCoupledNeighborValueDot(
"disp_y")),
69 _secondary_z_dot(_has_disp_z ? &adCoupledDot(
"disp_z") : nullptr),
70 _primary_z_dot(_has_disp_z ? &adCoupledNeighborValueDot(
"disp_z") : nullptr),
71 _mu(getParam<Real>(
"mu")),
72 _epsilon(getParam<Real>(
"epsilon"))
84 const auto & secondary_ip_lowerd_map =
88 std::array<ADReal, 3> primary_disp_dot{
90 std::array<ADReal, 3> secondary_disp_dot{
96 const ADReal & prim_x_dot = primary_disp_dot[0];
97 const ADReal & prim_y_dot = primary_disp_dot[1];
98 const ADReal * prim_z_dot =
nullptr;
100 prim_z_dot = &primary_disp_dot[2];
102 const ADReal & sec_x_dot = secondary_disp_dot[0];
103 const ADReal & sec_y_dot = secondary_disp_dot[1];
104 const ADReal * sec_z_dot =
nullptr;
106 sec_z_dot = &secondary_disp_dot[2];
112 relative_velocity = {sec_x_dot - prim_x_dot, sec_y_dot - prim_y_dot, *sec_z_dot - *prim_z_dot};
114 relative_velocity = {sec_x_dot - prim_x_dot, sec_y_dot - prim_y_dot, 0.0};
126 const DofObject *
const dof =
157 const DofObject *
const dof = pr.first;
176 const std::unordered_set<const Node *> & inactive_lm_nodes)
186 const DofObject *
const dof = pr.first;
189 if ((inactive_lm_nodes.find(
static_cast<const Node *
>(dof)) != inactive_lm_nodes.end()) ||
206 const DofObject *
const dof)
208 using std::abs, std::sqrt, std::max, std::min;
216 const Real scaling_factor_x =
_lm_vars[0]->scalingFactor();
217 const Real scaling_factor_y =
_lm_vars[1]->scalingFactor();
218 Real scaling_factor_z = 1;
226 dof_id_type dof_index_z(-1);
233 scaling_factor_z =
_lm_vars[2]->scalingFactor();
236 ADReal normal_pressure_value =
238 ADReal tangential_pressure_value =
241 ADReal tangential_pressure_value_dir;
252 ADReal normal_dof_residual = min(normal_pressure_value, weighted_gap *
c);
253 ADReal tangential_dof_residual;
254 ADReal tangential_dof_residual_dir;
261 if (normal_pressure_value.value() <
_epsilon)
262 tangential_dof_residual = tangential_pressure_value;
265 const auto term_1 = max(
_mu * (normal_pressure_value +
c * weighted_gap),
266 abs(tangential_pressure_value + c_t * tangential_vel *
_dt)) *
267 tangential_pressure_value;
268 const auto term_2 =
_mu * max(0.0, normal_pressure_value +
c * weighted_gap) *
269 (tangential_pressure_value + c_t * tangential_vel *
_dt);
271 tangential_dof_residual = term_1 - term_2;
276 if (normal_pressure_value.value() <
_epsilon)
278 tangential_dof_residual = tangential_pressure_value;
279 tangential_dof_residual_dir = tangential_pressure_value_dir;
283 const Real epsilon_sqrt = 1.0e-48;
285 const auto lamdba_plus_cg = normal_pressure_value +
c * weighted_gap;
287 std::array<ADReal, 2> lambda_t_plus_ctu;
291 const auto term_1_x = max(
_mu * lamdba_plus_cg,
292 sqrt(lambda_t_plus_ctu[0] * lambda_t_plus_ctu[0] +
293 lambda_t_plus_ctu[1] * lambda_t_plus_ctu[1] + epsilon_sqrt)) *
294 tangential_pressure_value;
296 const auto term_1_y = max(
_mu * lamdba_plus_cg,
297 sqrt(lambda_t_plus_ctu[0] * lambda_t_plus_ctu[0] +
298 lambda_t_plus_ctu[1] * lambda_t_plus_ctu[1] + epsilon_sqrt)) *
299 tangential_pressure_value_dir;
301 const auto term_2_x =
_mu * max(0.0, lamdba_plus_cg) * lambda_t_plus_ctu[0];
303 const auto term_2_y =
_mu * max(0.0, lamdba_plus_cg) * lambda_t_plus_ctu[1];
305 tangential_dof_residual = term_1_x - term_2_x;
306 tangential_dof_residual_dir = term_1_y - term_2_y;
329 unsigned int component_normal = 0;
332 const Real threshold_for_Jacobian =
_has_disp_z ? 1.0 / sqrt(3.0) : 1.0 / sqrt(2.0);
334 if (abs(ny) > threshold_for_Jacobian)
335 component_normal = 1;
336 else if (abs(nz) > threshold_for_Jacobian)
337 component_normal = 2;
341 std::array<ADReal, 1>{{normal_dof_residual}},
342 std::array<dof_id_type, 1>{{component_normal == 0
344 : (component_normal == 1 ? dof_index_y : dof_index_z)}},
345 component_normal == 0 ? scaling_factor_x
346 : (component_normal == 1 ? scaling_factor_y : scaling_factor_z));
350 std::array<ADReal, 1>{{tangential_dof_residual}},
351 std::array<dof_id_type, 1>{
352 {(component_normal == 0 || component_normal == 2) ? dof_index_y : dof_index_x}},
353 (component_normal == 0 || component_normal == 2) ? scaling_factor_y : scaling_factor_x);
358 std::array<ADReal, 1>{{tangential_dof_residual_dir}},
359 std::array<dof_id_type, 1>{
360 {(component_normal == 0 || component_normal == 1) ? dof_index_z : dof_index_x}},
361 (component_normal == 0 || component_normal == 1) ? scaling_factor_z : scaling_factor_x);
DualNumber< Real, DNDerivativeType, true > ADReal
void mooseError(Args &&... args)
std::map< unsigned int, unsigned int > getSecondaryIpToLowerElementMap(const Elem &lower_secondary_elem) const
std::map< unsigned int, unsigned int > getPrimaryIpToLowerElementMap(const Elem &primary_elem, const Elem &primary_elem_ip, const Elem &lower_secondary_elem) const
std::array< MooseUtils::SemidynamicVector< Point, 9 >, 2 > getNodalTangents(const Elem &secondary_elem) const
const MooseArray< Real > & _coord
const VariableTestValue & _test
Elem const *const & _lower_secondary_elem
const AutomaticMortarGeneration & amg() const
Elem const *const & _lower_primary_elem
static void trimInteriorNodeDerivatives(const std::map< unsigned int, unsigned int > &primary_ip_lowerd_map, const Variables &moose_var, DualNumbers &ad_vars, const bool is_secondary)
const std::vector< Real > & _JxW_msm
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)
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)