174 std::unique_ptr<PointLocatorBase> point_locator;
178 for (
const auto & node_id : range)
189 std::vector<PenetrationInfo *> p_info;
190 bool info_set(
false);
200 const Point contact_ref =
info->_closest_point_ref;
201 bool contact_point_on_side(
false);
205 std::vector<Point> points(1);
206 points[0] = contact_ref;
207 const std::vector<Point> & secondary_pos = fe_side->
get_xyz();
208 bool search_succeeded =
false;
217 contact_point_on_side,
221 info->_closest_point_ref = contact_ref;
224 info->_distance = 0.0;
229 Real old_tangential_distance(
info->_tangential_distance);
230 bool contact_point_on_side(
false);
231 bool search_succeeded =
false;
240 contact_point_on_side,
243 if (contact_point_on_side)
245 if (
info->_tangential_distance <= 0.0)
249 else if (
info->_tangential_distance > 0.0 && old_tangential_distance > 0.0)
251 if (
info->_side->dim() == 2 &&
info->_off_edge_nodes.size() < 2)
268 std::vector<dof_id_type> located_elem_ids;
269 const std::vector<dof_id_type> * closest_elems;
273 std::set<const Elem *> candidate_elements;
274 (*point_locator)(*closest_node, candidate_elements);
276 if (candidate_elements.empty())
277 mooseError(
"No proximate elements found at node ",
280 static_cast<const Point &
>(*closest_node),
283 ". This should never happen.");
285 for (
const Elem * elem : candidate_elements)
287 for (
auto s : elem->side_index_range())
290 located_elem_ids.push_back(elem->id());
295 if (located_elem_ids.empty())
296 mooseError(
"No proximate elements found at node ",
299 static_cast<const Point &
>(*closest_node),
302 " share that boundary. This may happen if the mesh uses the same boundary id " 303 "for a nodeset and an unrelated sideset.");
305 closest_elems = &located_elem_ids;
311 "Missing entry in node to elem map");
312 closest_elems = &(node_to_elem_pair->second);
315 for (
const auto & elem_id : *closest_elems)
319 std::vector<PenetrationInfo *> thisElemInfo;
321 std::vector<const Node *> nodesThatMustBeOnSide;
332 nodesThatMustBeOnSide.push_back(closest_node);
344 for (
unsigned int i = 0; i < p_info.size(); ++i)
346 const Point closest_point = closest_point_to_side(node, *p_info[i]->_side);
347 const Real distance_sq = (closest_point - node).
norm_sq();
348 if (distance_sq < min_distance_sq)
350 min_distance_sq = distance_sq;
351 best_point = closest_point;
356 p_info[best_i]->_closest_point = best_point;
357 p_info[best_i]->_distance =
358 (p_info[best_i]->_distance >= 0.0 ? 1.0 : -1.0) *
std::sqrt(min_distance_sq);
360 mooseError(
"Normal smoothing not implemented with point locator code");
361 Point normal = (best_point - node).unit();
362 const Real dot = normal * p_info[best_i]->_normal;
365 p_info[best_i]->_normal = normal;
372 if (p_info.size() == 1)
380 else if (p_info.size() > 1)
383 std::vector<RidgeData> ridgeDataVec;
384 for (
unsigned int i = 0; i + 1 < p_info.size(); ++i)
385 for (
unsigned int j = i + 1; j < p_info.size(); ++j)
388 Real tangential_distance(0.0);
389 const Node * closest_node_on_ridge = NULL;
390 unsigned int index = 0;
391 Point closest_coor_ref;
394 closest_node_on_ridge,
400 if (found_ridge_contact_point)
403 rpd._closest_coor = closest_coor;
404 rpd._tangential_distance = tangential_distance;
405 rpd._closest_node = closest_node_on_ridge;
407 rpd._closest_coor_ref = closest_coor_ref;
408 ridgeDataVec.push_back(rpd);
412 if (ridgeDataVec.size() > 0)
416 std::vector<RidgeSetData> ridgeSetDataVec;
417 for (
unsigned int i = 0; i < ridgeDataVec.size(); ++i)
419 bool foundSetWithMatchingNode =
false;
420 for (
unsigned int j = 0; j < ridgeSetDataVec.size(); ++j)
422 if (ridgeDataVec[i]._closest_node != NULL &&
423 ridgeDataVec[i]._closest_node == ridgeSetDataVec[j]._closest_node)
425 foundSetWithMatchingNode =
true;
426 ridgeSetDataVec[j]._ridge_data_vec.push_back(ridgeDataVec[i]);
430 if (!foundSetWithMatchingNode)
434 rsd._ridge_data_vec.push_back(ridgeDataVec[i]);
435 rsd._closest_node = ridgeDataVec[i]._closest_node;
436 ridgeSetDataVec.push_back(rsd);
440 for (
unsigned int i = 0; i < ridgeSetDataVec.size(); ++i)
442 if (ridgeSetDataVec[i]._closest_node !=
445 if (ridgeSetDataVec[i]._ridge_data_vec.size() == 1)
447 if (ridgeSetDataVec[i]._ridge_data_vec[0]._tangential_distance <=
450 ridgeSetDataVec[i]._closest_coor =
451 ridgeSetDataVec[i]._ridge_data_vec[0]._closest_coor;
452 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
453 ridgeSetDataVec[i]._distance = contact_point_vec.
norm();
459 ridgeSetDataVec[i]._closest_coor = *ridgeSetDataVec[i]._closest_node;
460 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
461 ridgeSetDataVec[i]._distance = contact_point_vec.
norm();
466 ridgeSetDataVec[i]._closest_coor =
467 ridgeSetDataVec[i]._ridge_data_vec[0]._closest_coor;
468 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
469 ridgeSetDataVec[i]._distance = contact_point_vec.
norm();
473 unsigned int closest_ridge_set_index(0);
474 Real closest_distance(ridgeSetDataVec[0]._distance);
475 Point closest_point(ridgeSetDataVec[0]._closest_coor);
476 for (
unsigned int i = 1; i < ridgeSetDataVec.size(); ++i)
478 if (ridgeSetDataVec[i]._distance < closest_distance)
480 closest_ridge_set_index = i;
481 closest_distance = ridgeSetDataVec[i]._distance;
482 closest_point = ridgeSetDataVec[i]._closest_coor;
486 if (closest_distance <
492 for (
unsigned int i = 0;
493 i < ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec.size();
496 if (ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[i]._index < face_index)
497 face_index = ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[i]._index;
501 "face_index invalid");
503 p_info[face_index]->_closest_point = closest_point;
504 p_info[face_index]->_distance =
505 (p_info[face_index]->_distance >= 0.0 ? 1.0 : -1.0) * closest_distance;
511 Point normal(closest_point - node);
517 const Real dot(normal * p_info[face_index]->_normal);
522 p_info[face_index]->_normal = normal;
524 p_info[face_index]->_tangential_distance = 0.0;
526 Point closest_point_ref;
527 if (ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec.size() ==
530 p_info[face_index]->_tangential_distance = ridgeSetDataVec[closest_ridge_set_index]
532 ._tangential_distance;
533 p_info[face_index]->_closest_point_ref =
534 ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[0]._closest_coor_ref;
538 const Node * closest_node_on_face;
540 closest_node_on_face,
541 p_info[face_index]->_side);
544 if (closest_node_on_face !=
545 ridgeSetDataVec[closest_ridge_set_index]._closest_node)
547 mooseError(
"Closest node when restricting point to face != closest node from " 554 std::vector<Point> points(1);
555 points[0] = p_info[face_index]->_closest_point_ref;
556 fe->
reinit(p_info[face_index]->_side, &points);
557 p_info[face_index]->_side_phi = fe->
get_phi();
558 p_info[face_index]->_side_grad_phi = fe->
get_dphi();
574 unsigned int best(0), i(1);
592 }
while (i < p_info.size() && best < p_info.size());
593 if (best < p_info.size())
626 for (
unsigned int j = 0; j < p_info.size(); ++j)
MooseVariable * _nodal_normal_z
auto norm() const -> decltype(std::norm(Real()))
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
const unsigned int invalid_uint
virtual_for_inffe const std::vector< RealGradient > & get_dxyzdeta() const
virtual Elem * elemPtr(const dof_id_type i)
bool findRidgeContactPoint(libMesh::Point &contact_point, Real &tangential_distance, const Node *&closest_node, unsigned int &index, libMesh::Point &contact_point_ref, std::vector< PenetrationInfo *> &p_info, const unsigned int index1, const unsigned int index2)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Data structure used to hold penetration information.
NearestNodeLocator & _nearest_node
bool _check_whether_reasonable
virtual_for_inffe const std::vector< RealGradient > & get_d2xyzdxideta() const
void createInfoForElem(std::vector< PenetrationInfo *> &thisElemInfo, std::vector< PenetrationInfo *> &p_info, const Node *secondary_node, const Elem *elem, const std::vector< const Node *> &nodes_that_must_be_on_side, const bool check_whether_reasonable=false)
Threads::spin_mutex pinfo_mutex
const BoundaryInfo & get_boundary_info() const
virtual const Node & nodeRef(const dof_id_type i) const
void smoothNormal(PenetrationInfo *info, std::vector< PenetrationInfo *> &p_info, const Node &node)
libMesh::FEType & _fe_type
auto max(const L &left, const R &right)
BoundaryID _primary_boundary
const std::vector< std::vector< OutputGradient > > & get_dphi() const
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
CompeteInteractionResult competeInteractions(PenetrationInfo *pi1, PenetrationInfo *pi2)
When interactions are identified between a node and two faces, compete between the faces to determine...
void computeSlip(libMesh::FEBase &fe, PenetrationInfo &info)
virtual void reinit(const Elem *elem, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr)=0
void findContactPoint(PenetrationInfo &p_info, libMesh::FEBase *fe_elem, libMesh::FEBase *fe_side, libMesh::FEType &fe_side_type, const libMesh::Point &secondary_point, bool start_with_centroid, const Real tangential_tolerance, bool &contact_point_on_side, bool &search_succeeded)
Finds the closest point (called the contact point) on the primary_elem on side "side" to the secondar...
std::vector< dof_id_type > _recheck_secondary_nodes
List of secondary nodes for which penetration was not detected in the current patch and for which pat...
virtual MooseVariable & getStandardVariable(const THREAD_ID tid, const std::string &var_name)=0
Returns the variable reference for requested MooseVariable which may be in any system.
virtual_for_inffe const std::vector< Point > & get_xyz() const
Real _tangential_tolerance
bool restrictPointToFace(libMesh::Point &p, const Node *&closest_node, const Elem *side)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::map< dof_id_type, PenetrationInfo * > & _penetration_info
const Node * nearestNode(dof_id_type node_id)
Valid to call this after findNodes() has been called to get a pointer to the nearest node...
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
MooseVariable * _nodal_normal_y
bool _do_normal_smoothing
virtual std::unique_ptr< libMesh::PointLocatorBase > getPointLocator() const
Proxy function to get a (sub)PointLocator from either the underlying libMesh mesh (default)...
const std::map< dof_id_type, std::vector< dof_id_type > > & _node_to_elem_map
void switchInfo(PenetrationInfo *&info, PenetrationInfo *&infoNew)
virtual_for_inffe const std::vector< RealGradient > & get_dxyzdxi() const
MooseVariable * _nodal_normal_x
std::vector< std::vector< libMesh::FEBase * > > & _fes
PenetrationLocator::NORMAL_SMOOTHING_METHOD _normal_smoothing_method
const std::vector< std::vector< OutputShape > > & get_phi() const