27 #include "libmesh/string_to_enum.h" 28 #include "libmesh/sparse_matrix.h" 41 params.
addParam<BoundaryName>(
"secondary",
"The secondary boundary");
43 "An integer corresponding to the direction " 44 "the variable this constraint acts on. (0 for x, " 49 "The displacements appropriate for the simulation geometry and coordinate system");
51 params.
addCoupledVar(
"secondary_gap_offset",
"offset to the gap distance from secondary side");
53 "offset to the gap distance mapped from primary side");
56 params.
set<
bool>(
"use_displaced_mesh") =
true;
60 "The penalty to apply. This can vary depending on the stiffness of your materials");
63 "The growth factor for the penalty applied at the end of each augmented " 64 "Lagrange update iteration");
65 params.
addParam<
Real>(
"friction_coefficient", 0,
"The friction coefficient");
67 "Tangential distance to extend edges of contact surfaces");
69 "capture_tolerance", 0,
"Normal distance from surface within which nodes are captured");
73 "Tension release threshold. A node in contact " 74 "will not be released if its tensile load is below " 75 "this value. No tension release if negative.");
80 "Whether to normalize the penalty parameter with the nodal area for penalty contact.");
82 "primary_secondary_jacobian",
84 "Whether to include jacobian entries coupling primary and secondary nodes.");
86 "connected_secondary_nodes_jacobian",
88 "Whether to include jacobian entries coupling nodes connected to secondary nodes.");
89 params.
addParam<
bool>(
"non_displacement_variables_jacobian",
91 "Whether to include jacobian entries coupling with variables that are not " 92 "displacement variables.");
93 params.
addParam<
unsigned int>(
"stick_lock_iterations",
94 std::numeric_limits<unsigned int>::max(),
95 "Number of times permitted to switch between sticking and slipping " 96 "in a solution before locking node in a sticked state.");
99 "Factor by which frictional capacity must be " 100 "exceeded to permit stick-locked node to slip " 103 "The tolerance of the penetration for augmented Lagrangian method.");
105 "The tolerance of the incremental slip for augmented Lagrangian method.");
108 "The tolerance of the frictional force for augmented Lagrangian method.");
110 "print_contact_nodes",
false,
"Whether to print the number of nodes in contact.");
113 "Apply non-penetration constraints on the mechanical deformation " 114 "using a node on face, primary/secondary algorithm, and multiple options " 115 "for the physical behavior on the interface and the mathematical " 116 "formulation for constraint enforcement");
125 _displaced_problem(parameters.
get<
FEProblemBase *>(
"_fe_problem_base")->getDisplacedProblem()),
126 _component(getParam<unsigned
int>(
"component")),
129 _normalize_penalty(getParam<bool>(
"normalize_penalty")),
130 _penalty(getParam<
Real>(
"penalty")),
131 _penalty_multiplier(getParam<
Real>(
"penalty_multiplier")),
132 _friction_coefficient(getParam<
Real>(
"friction_coefficient")),
133 _tension_release(getParam<
Real>(
"tension_release")),
134 _capture_tolerance(getParam<
Real>(
"capture_tolerance")),
135 _stick_lock_iterations(getParam<unsigned
int>(
"stick_lock_iterations")),
136 _stick_unlock_factor(getParam<
Real>(
"stick_unlock_factor")),
137 _update_stateful_data(true),
138 _residual_copy(_sys.residualGhosted()),
139 _mesh_dimension(_mesh.dimension()),
141 _var_objects(3, nullptr),
142 _has_secondary_gap_offset(isCoupled(
"secondary_gap_offset")),
143 _secondary_gap_offset_var(_has_secondary_gap_offset ? getVar(
"secondary_gap_offset", 0)
145 _has_mapped_primary_gap_offset(isCoupled(
"mapped_primary_gap_offset")),
146 _mapped_primary_gap_offset_var(
147 _has_mapped_primary_gap_offset ? getVar(
"mapped_primary_gap_offset", 0) : nullptr),
148 _nodal_area_var(getVar(
"nodal_area", 0)),
149 _aux_system(_nodal_area_var->sys()),
150 _aux_solution(_aux_system.currentSolution()),
151 _primary_secondary_jacobian(getParam<bool>(
"primary_secondary_jacobian")),
152 _connected_secondary_nodes_jacobian(getParam<bool>(
"connected_secondary_nodes_jacobian")),
153 _non_displacement_vars_jacobian(getParam<bool>(
"non_displacement_variables_jacobian")),
155 _print_contact_nodes(getParam<bool>(
"print_contact_nodes")),
156 _augmented_lagrange_problem(
158 _lagrangian_iteration_number(_augmented_lagrange_problem
159 ? _augmented_lagrange_problem->getLagrangianIterationNumber()
185 mooseError(
"The 'tangential_penalty' formulation can only be used with the 'coulomb' model");
191 mooseError(
"The friction coefficient must be nonnegative");
199 mooseError(
"The Augmented Lagrangian contact formulation does not support GLUED case.");
202 mooseError(
"The Augmented Lagrangian contact formulation must use " 203 "AugmentedLagrangianContactProblem.");
206 mooseError(
"For Augmented Lagrangian contact, al_penetration_tolerance must be provided.");
215 mooseError(
"For the Augmented Lagrangian frictional contact formualton, " 216 "al_incremental_slip_tolerance and " 217 "al_frictional_force_tolerance must be provided.");
271 pinfo->_lagrange_multiplier_slip.zero();
272 if (pinfo->isCaptured())
276 if (pinfo->isCaptured())
283 if (!beginning_of_step)
287 penalty * (-
distance) * pinfo->_normal + pinfo->_lagrange_multiplier * pinfo->_normal;
290 pinfo->_lagrange_multiplier += penalty * (-
distance);
294 ? -pen_force_normal * pinfo->_normal
298 pinfo->_incremental_slip -
299 (pinfo->_incremental_slip * pinfo->_normal) * pinfo->_normal;
304 pinfo->_lagrange_multiplier_slip + penalty_slip * tangential_inc_slip;
307 pinfo->_normal * (pinfo->_normal * pinfo->_contact_force_old);
309 RealVectorValue contact_force_tangential = inc_pen_force_tangential + tau_old;
310 const Real tan_mag(contact_force_tangential.
norm());
314 pinfo->_lagrange_multiplier_slip =
315 -tau_old + capacity * contact_force_tangential / tan_mag;
324 pinfo->_lagrange_multiplier_slip += penalty_slip * tangential_inc_slip;
335 Real contactResidual = 0.0;
351 if (pinfo->isCaptured())
353 if (contactResidual < std::abs(
distance))
354 contactResidual = std::abs(
distance);
365 RealVectorValue contact_force_normal((pinfo->_contact_force * pinfo->_normal) *
367 RealVectorValue contact_force_tangential(pinfo->_contact_force - contact_force_normal);
370 pinfo->_incremental_slip - (pinfo->_incremental_slip * pinfo->_normal) * pinfo->_normal;
372 const Real tan_mag(contact_force_tangential.
norm());
373 const Real tangential_inc_slip_mag = tangential_inc_slip.
norm();
376 (pinfo->_normal * (node - pinfo->_closest_point) +
gapOffset(node)) * pinfo->_normal;
380 penalty * distance_vec + pinfo->_lagrange_multiplier * pinfo->_normal;
384 ? -pen_force_normal * pinfo->_normal
413 _console <<
"The Augmented Lagrangian contact tangential sliding enforcement is NOT satisfied " 416 _console <<
"The Augmented Lagrangian contact tangential sliding enforcement is NOT satisfied " 419 _console <<
"The Augmented Lagrangian contact frictional force enforcement is NOT satisfied " 439 if (beginning_of_step)
443 pinfo->_contact_force_old = pinfo->_contact_force;
444 pinfo->_accumulated_slip_old = pinfo->_accumulated_slip;
445 pinfo->_frictional_energy_old = pinfo->_frictional_energy;
446 pinfo->_mech_status_old = pinfo->_mech_status;
457 pinfo->_locked_this_step = 0;
458 pinfo->_stick_locked_this_step = 0;
459 pinfo->_starting_elem = pinfo->_elem;
460 pinfo->_starting_side_num = pinfo->_side_num;
461 pinfo->_starting_closest_point_ref = pinfo->_closest_point_ref;
463 pinfo->_incremental_slip_prev_iter = pinfo->_incremental_slip;
470 bool in_contact =
false;
472 std::map<dof_id_type, PenetrationInfo *>::iterator found =
504 bool update_contact_set)
515 if (distance_vec.
norm() != 0)
518 const Real gap_size = -1.0 * pinfo->
_normal * distance_vec;
522 bool newly_captured =
false;
525 if (update_contact_set && !pinfo->
isCaptured() &&
528 newly_captured =
true;
591 const Real tan_mag(contact_force_tangential.
norm());
592 const Real tangential_inc_slip_mag = tangential_inc_slip.
norm();
593 const Real slip_tol = capacity / penalty;
596 if ((tangential_inc_slip_mag > slip_tol || tan_mag > capacity) &&
605 bool slipped_too_far =
false;
607 if (tangential_inc_slip_mag > slip_tol)
609 slip_inc_direction = tangential_inc_slip / tangential_inc_slip_mag;
610 Real slip_dot_tang_force = slip_inc_direction * contact_force_tangential;
611 if (slip_dot_tang_force < capacity)
612 slipped_too_far =
true;
616 pinfo->
_contact_force = contact_force_normal + capacity * slip_inc_direction;
621 contact_force_normal + capacity * contact_force_tangential / tan_mag;
645 pen_force = penalty * distance_vec;
649 (pen_force * pinfo->
_normal < 0 ? -pen_force * pinfo->
_normal : 0));
660 const Real tan_mag(contact_force_tangential.
norm());
662 if (tan_mag > capacity)
665 contact_force_normal + capacity * contact_force_tangential / tan_mag;
693 RealVectorValue inc_pen_force_tangential = penalty_slip * tangential_inc_slip;
697 contact_force_normal + contact_force_tangential + inc_pen_force_tangential;
699 pinfo->
_contact_force = contact_force_normal + contact_force_tangential;
715 inc_pen_force_tangential +
720 const Real tan_mag(contact_force_tangential.
norm());
722 if (tan_mag > capacity)
725 contact_force_normal + capacity * contact_force_tangential / tan_mag;
733 pinfo->
_contact_force = contact_force_normal + contact_force_tangential;
769 mooseError(
"Invalid or unavailable contact model");
804 if (distance_vec.
norm() != 0)
816 pen_force = penalty * distance_vec;
857 mooseError(
"Unhandled ConstraintJacobianType");
909 const Real curr_jac =
931 Real tang_comp = 0.0;
935 return normal_comp + tang_comp;
951 Real tang_comp = 0.0;
956 return normal_comp + tang_comp;
982 mooseError(
"Invalid or unavailable contact model");
999 jac_vec(i) = (*_jacobian)(dof_number,
1032 (*_jacobian)(dof_number,
1043 const Real curr_jac =
1065 Real tang_comp = 0.0;
1069 return normal_comp + tang_comp;
1080 jac_vec(i) = (*_jacobian)(dof_number,
1088 Real tang_comp = 0.0;
1093 return normal_comp + tang_comp;
1105 const Real curr_jac =
1121 mooseError(
"Invalid or unavailable contact model");
1171 const Real secondary_jac =
1193 Real tang_comp = 0.0;
1197 return normal_comp + tang_comp;
1212 Real tang_comp = 0.0;
1217 return normal_comp + tang_comp;
1229 const Real secondary_jac =
1245 mooseError(
"Invalid or unavailable contact model");
1285 Real tang_comp = 0.0;
1297 Real tang_comp = 0.0;
1301 return normal_comp + tang_comp;
1309 mooseError(
"Invalid or unavailable contact model");
1325 unsigned int coupled_component;
1326 Real normal_component_in_coupled_var_dir = 1.0;
1328 normal_component_in_coupled_var_dir = pinfo->
_normal(coupled_component);
1333 mooseError(
"Unhandled ConstraintJacobianType");
1393 Real tang_comp = 0.0;
1397 return normal_comp + tang_comp;
1414 mooseError(
"Invalid or unavailable contact model");
1431 jac_vec(i) = (*_jacobian)(dof_number,
1462 (*_jacobian)(dof_number, curr_primary_node->dof_number(0,
_vars[
_component], 0)) /
1480 Real tang_comp = 0.0;
1484 return normal_comp + tang_comp;
1493 mooseError(
"Invalid or unavailable contact model");
1543 const Real secondary_jac =
1565 Real tang_comp = 0.0;
1569 return normal_comp + tang_comp;
1599 const Real secondary_jac =
1615 mooseError(
"Invalid or unavailable contact model");
1669 Real tang_comp = 0.0;
1673 return normal_comp + tang_comp;
1679 mooseError(
"Invalid or unavailable contact model");
1705 Real area = (*_aux_solution)(dof);
1856 component = std::numeric_limits<unsigned int>::max();
1857 bool coupled_var_is_disp_var =
false;
1860 if (var_num ==
_vars[i])
1862 coupled_var_is_disp_var =
true;
1868 return coupled_var_is_disp_var;
1881 <<
" nodes in contact.\n";
1884 <<
" nodes in contact.\n";
virtual unsigned int coupled(const std::string &var_name, unsigned int comp=0) const
auto norm() const -> decltype(std::norm(Real()))
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
const unsigned int invalid_uint
void setNormalSmoothingDistance(Real normal_smoothing_distance)
unsigned int number() const
MooseVariable & _primary_var
static const std::string component
const Elem *const & _current_primary
DenseMatrix< Number > _Kne
static constexpr std::size_t dim
static InputParameters validParams()
MooseVariable * getVar(const std::string &var_name, unsigned int comp)
unsigned int _stick_locked_this_step
const Parallel::Communicator & _communicator
virtual const dof_id_type & nodalDofIndex() const=0
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
const VariableTestValue & _test_primary
bool computingNonlinearResid() const
std::map< dof_id_type, PenetrationInfo *> & _penetration_info
void setTangentialTolerance(Real tangential_tolerance)
RealVectorValue _contact_force_old
Real distance(const Point &p)
virtual const Node & nodeRef(const dof_id_type i) const
const Node *const & _current_node
DenseMatrix< Number > _Kee
bool converged(const std::vector< std::pair< unsigned int, Real >> &residuals, const std::vector< Real > &abs_tolerances)
Based on the residuals, determine if the iterative process converged or not.
unsigned int _locked_this_step
bool isParamValid(const std::string &name) const
void prepareMatrixTagNeighbor(Assembly &assembly, unsigned int ivar, unsigned int jvar, Moose::DGJacobianType type)
TypeVector< Real > unit() const
virtual void getConnectedDofIndices(unsigned int var_num)
bool absoluteFuzzyLessThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
const std::string & type() const
const VariableValue & _u_secondary
unsigned int number() const
void accumulateTaggedLocalMatrix()
RealVectorValue _contact_force
Executioner * getExecutioner() const
MECH_STATUS_ENUM _mech_status
OutputData getNodalValue(const Node &node) const
VariableTestValue _test_secondary
void setUpdate(bool update)
unsigned int coupledComponents(const std::string &var_name) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Real _lagrange_multiplier
void max(const T &r, T &o, Request &req) const
void resize(const unsigned int new_m, const unsigned int new_n)
IntRange< T > make_range(T beg, T end)
bool absoluteFuzzyGreaterEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
void mooseError(Args &&... args) const
std::vector< dof_id_type > _connected_dof_indices
const InputParameters & parameters() const
const VariablePhiValue & _phi_primary
bool _overwrite_secondary_residual
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
VariablePhiValue _phi_secondary
const ConsoleStream _console
void setNormalSmoothingMethod(std::string nsmString)
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
RealVectorValue _lagrange_multiplier_slip
virtual bool lastSolveConverged() const=0
PenetrationLocator & _penetration_locator
void ErrorVector unsigned int
const Elem & get(const ElemType type_in)
bool absoluteFuzzyGreaterThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
void scalingFactor(const std::vector< Real > &factor)
void set_union(T &data, const unsigned int root_id) const