26#include "libmesh/id_types.h"
27#include "libmesh/string_to_enum.h"
28#include "libmesh/sparse_matrix.h"
42 params.
addParam<BoundaryName>(
"secondary",
"The secondary boundary");
44 "An integer corresponding to the direction "
45 "the variable this constraint acts on. (0 for x, "
49 "The displacements appropriate for the simulation geometry and coordinate system");
50 params.
addCoupledVar(
"secondary_gap_offset",
"offset to the gap distance from secondary side");
52 "offset to the gap distance mapped from primary side");
53 params.
set<
bool>(
"use_displaced_mesh") =
true;
56 "The penalty to apply. Its optimal value can vary depending on the "
57 "stiffness of the materials");
58 params.
addParam<Real>(
"friction_coefficient", 0,
"The friction coefficient");
59 params.
addParam<Real>(
"tangential_tolerance",
60 "Tangential distance to extend edges of contact surfaces");
62 "print_contact_nodes",
false,
"Whether to print the number of nodes in contact.");
65 "Apply non-penetration constraints on the mechanical deformation in explicit dynamics "
66 "using a node on face formulation by solving uncoupled momentum-balance equations.");
74 _displaced_problem(parameters.get<
FEProblemBase *>(
"_fe_problem_base")->getDisplacedProblem()),
75 _component(getParam<unsigned
int>(
"component")),
77 _update_stateful_data(true),
78 _mesh_dimension(_mesh.dimension()),
79 _vars(3,
libMesh::invalid_uint),
80 _var_objects(3, nullptr),
81 _has_secondary_gap_offset(isCoupled(
"secondary_gap_offset")),
82 _secondary_gap_offset_var(_has_secondary_gap_offset ? getVar(
"secondary_gap_offset", 0)
84 _has_mapped_primary_gap_offset(isCoupled(
"mapped_primary_gap_offset")),
85 _mapped_primary_gap_offset_var(
86 _has_mapped_primary_gap_offset ? getVar(
"mapped_primary_gap_offset", 0) : nullptr),
87 _penalty(getParam<Real>(
"penalty")),
88 _print_contact_nodes(getParam<bool>(
"print_contact_nodes")),
89 _residual_copy(_sys.residualGhosted()),
90 _gap_rate(&writableVariable(
"gap_rate")),
91 _neighbor_vel_x(isCoupled(
"vel_x") ? coupledNeighborValue(
"vel_x") : _zero),
92 _neighbor_vel_y(isCoupled(
"vel_y") ? coupledNeighborValue(
"vel_y") : _zero),
93 _neighbor_vel_z((_mesh.dimension() == 3 && isCoupled(
"vel_z")) ? coupledNeighborValue(
"vel_z")
126 "Velocities vel_x and vel_y (also vel_z in three dimensions) need to be provided "
127 "for the 'balance' option of solving normal contact in explicit dynamics.");
154 if (beginning_of_step)
158 pinfo->_contact_force_old = pinfo->_contact_force;
159 pinfo->_accumulated_slip_old = pinfo->_accumulated_slip;
160 pinfo->_frictional_energy_old = pinfo->_frictional_energy;
161 pinfo->_mech_status_old = pinfo->_mech_status;
166 mooseWarning(
"Previous step did not converge. Check results");
173 pinfo->_starting_elem = pinfo->_elem;
174 pinfo->_starting_side_num = pinfo->_side_num;
175 pinfo->_starting_closest_point_ref = pinfo->_closest_point_ref;
177 pinfo->_incremental_slip_prev_iter = pinfo->_incremental_slip;
187 bool in_contact =
false;
189 std::map<dof_id_type, PenetrationInfo *>::iterator found =
194 if (pinfo !=
nullptr)
212 bool update_contact_set)
224 distance_vec += udotvec;
226 if (distance_vec.norm() != 0)
229 const Real gap_size = -1.0 * pinfo->
_normal * distance_vec;
233 bool newly_captured =
false;
236 if (update_contact_set && !pinfo->
isCaptured() &&
237 MooseUtils::absoluteFuzzyGreaterEqual(gap_size, 0.0, 0.0))
239 newly_captured =
true;
251 RealVectorValue pen_force(penalty * distance_vec);
259 mooseError(
"Invalid or unavailable contact model");
263 if (update_contact_set && pinfo->
isCaptured() && !newly_captured)
266 if (-contact_pressure >= 0.0)
277 const RealVectorValue & )
290 const auto & diag =
_sys.
getVector(
"mass_matrix_diag_inverted");
292 Real mass_node = 1.0 / diag(dof_x);
295 Real mass_eff = (mass_face * mass_node) / (mass_face + mass_node);
307 RealVectorValue secondary_velocity(
308 velocity_x, velocity_y,
_mesh.
dimension() == 3 ? velocity_z : 0.0);
309 RealVectorValue closest_point_velocity(
310 n_velocity_x, n_velocity_y,
_mesh.
dimension() == 3 ? n_velocity_z : 0.0);
312 Real gap_rate = pinfo->
_normal * (secondary_velocity - closest_point_velocity);
315 RealVectorValue impulse_force = pinfo->
_normal * (gap_rate * mass_eff) /
_dt;
319 velocity_x -=
_dt / mass_eff * impulse_force(0);
320 velocity_y -=
_dt / mass_eff * impulse_force(1);
321 velocity_z -=
_dt / mass_eff * impulse_force(2);
324 secondary_velocity = {velocity_x, velocity_y,
_mesh.
dimension() == 3 ? velocity_z : 0.0};
325 gap_rate = pinfo->
_normal * (secondary_velocity - closest_point_velocity);
387 std::vector<dof_id_type> face_dofs;
391 for (
const auto dof : face_dofs)
392 mass_face += 1.0 / lumped_mass(dof);
394 mass_face /= face_dofs.size();
void ErrorVector unsigned int
const unsigned int & neighborSide() const
MooseVariable * getVar(const std::string &var_name, unsigned int comp)
unsigned int coupledComponents(const std::string &var_name) const
virtual unsigned int coupled(const std::string &var_name, unsigned int comp=0) const
virtual bool isCoupled(const std::string &var_name, unsigned int i=0) const
virtual bool lastSolveConverged() const=0
Executioner * getExecutioner() const
const InputParameters & parameters() const
const std::string & type() const
void paramError(const std::string ¶m, Args... args) const
void mooseError(Args &&... args) const
void mooseWarning(Args &&... args) const
bool isParamValid(const std::string &name) const
virtual const Node & nodeRef(const dof_id_type i) const
virtual unsigned int dimension() const
DofValue getNodalValue(const Node &node) const
virtual void getDofIndices(const Elem *elem, std::vector< dof_id_type > &dof_indices) const override
virtual void setNodalValue(const OutputType &value, unsigned int idx=0)=0
PenetrationLocator & _penetration_locator
const Node *const & _current_node
VariableTestValue _test_secondary
const Elem *const & _current_primary
const VariableTestValue & _test_primary
bool _overwrite_secondary_residual
static InputParameters validParams()
const VariableValue & _u_secondary
MooseVariable & _primary_var
RealVectorValue _contact_force
void setNormalSmoothingMethod(std::string nsmString)
void setTangentialTolerance(Real tangential_tolerance)
void setNormalSmoothingDistance(Real normal_smoothing_distance)
std::map< dof_id_type, PenetrationInfo * > & _penetration_info
FEProblemBase & _fe_problem
virtual NumericVector< Number > * solutionUDot()
unsigned int number() const
virtual NumericVector< Number > & getVector(const std::string &name)
static InputParameters validParams()
processor_id_type processor_id() const
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...