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);
275 for (
const Elem * elem : candidate_elements)
277 for (
auto s : elem->side_index_range())
280 located_elem_ids.push_back(elem->id());
284 closest_elems = &located_elem_ids;
290 "Missing entry in node to elem map");
291 closest_elems = &(node_to_elem_pair->second);
294 for (
const auto & elem_id : *closest_elems)
298 std::vector<PenetrationInfo *> thisElemInfo;
300 std::vector<const Node *> nodesThatMustBeOnSide;
311 nodesThatMustBeOnSide.push_back(closest_node);
323 for (
unsigned int i = 0; i < p_info.size(); ++i)
325 const Point closest_point = closest_point_to_side(node, *p_info[i]->_side);
326 const Real distance_sq = (closest_point - node).
norm_sq();
327 if (distance_sq < min_distance_sq)
329 min_distance_sq = distance_sq;
330 best_point = closest_point;
335 p_info[best_i]->_closest_point = best_point;
336 p_info[best_i]->_distance =
337 (p_info[best_i]->_distance >= 0.0 ? 1.0 : -1.0) *
std::sqrt(min_distance_sq);
339 mooseError(
"Normal smoothing not implemented with point locator code");
340 Point normal = (best_point - node).unit();
341 const Real dot = normal * p_info[best_i]->_normal;
344 p_info[best_i]->_normal = normal;
351 if (p_info.size() == 1)
359 else if (p_info.size() > 1)
362 std::vector<RidgeData> ridgeDataVec;
363 for (
unsigned int i = 0; i + 1 < p_info.size(); ++i)
364 for (
unsigned int j = i + 1; j < p_info.size(); ++j)
367 Real tangential_distance(0.0);
368 const Node * closest_node_on_ridge = NULL;
369 unsigned int index = 0;
370 Point closest_coor_ref;
373 closest_node_on_ridge,
379 if (found_ridge_contact_point)
382 rpd._closest_coor = closest_coor;
383 rpd._tangential_distance = tangential_distance;
384 rpd._closest_node = closest_node_on_ridge;
386 rpd._closest_coor_ref = closest_coor_ref;
387 ridgeDataVec.push_back(rpd);
391 if (ridgeDataVec.size() > 0)
395 std::vector<RidgeSetData> ridgeSetDataVec;
396 for (
unsigned int i = 0; i < ridgeDataVec.size(); ++i)
398 bool foundSetWithMatchingNode =
false;
399 for (
unsigned int j = 0; j < ridgeSetDataVec.size(); ++j)
401 if (ridgeDataVec[i]._closest_node != NULL &&
402 ridgeDataVec[i]._closest_node == ridgeSetDataVec[j]._closest_node)
404 foundSetWithMatchingNode =
true;
405 ridgeSetDataVec[j]._ridge_data_vec.push_back(ridgeDataVec[i]);
409 if (!foundSetWithMatchingNode)
413 rsd._ridge_data_vec.push_back(ridgeDataVec[i]);
414 rsd._closest_node = ridgeDataVec[i]._closest_node;
415 ridgeSetDataVec.push_back(rsd);
419 for (
unsigned int i = 0; i < ridgeSetDataVec.size(); ++i)
421 if (ridgeSetDataVec[i]._closest_node !=
424 if (ridgeSetDataVec[i]._ridge_data_vec.size() == 1)
426 if (ridgeSetDataVec[i]._ridge_data_vec[0]._tangential_distance <=
429 ridgeSetDataVec[i]._closest_coor =
430 ridgeSetDataVec[i]._ridge_data_vec[0]._closest_coor;
431 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
432 ridgeSetDataVec[i]._distance = contact_point_vec.
norm();
438 ridgeSetDataVec[i]._closest_coor = *ridgeSetDataVec[i]._closest_node;
439 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
440 ridgeSetDataVec[i]._distance = contact_point_vec.
norm();
445 ridgeSetDataVec[i]._closest_coor =
446 ridgeSetDataVec[i]._ridge_data_vec[0]._closest_coor;
447 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
448 ridgeSetDataVec[i]._distance = contact_point_vec.
norm();
452 unsigned int closest_ridge_set_index(0);
453 Real closest_distance(ridgeSetDataVec[0]._distance);
454 Point closest_point(ridgeSetDataVec[0]._closest_coor);
455 for (
unsigned int i = 1; i < ridgeSetDataVec.size(); ++i)
457 if (ridgeSetDataVec[i]._distance < closest_distance)
459 closest_ridge_set_index = i;
460 closest_distance = ridgeSetDataVec[i]._distance;
461 closest_point = ridgeSetDataVec[i]._closest_coor;
465 if (closest_distance <
471 for (
unsigned int i = 0;
472 i < ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec.size();
475 if (ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[i]._index < face_index)
476 face_index = ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[i]._index;
480 "face_index invalid");
482 p_info[face_index]->_closest_point = closest_point;
483 p_info[face_index]->_distance =
484 (p_info[face_index]->_distance >= 0.0 ? 1.0 : -1.0) * closest_distance;
490 Point normal(closest_point - node);
496 const Real dot(normal * p_info[face_index]->_normal);
501 p_info[face_index]->_normal = normal;
503 p_info[face_index]->_tangential_distance = 0.0;
505 Point closest_point_ref;
506 if (ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec.size() ==
509 p_info[face_index]->_tangential_distance = ridgeSetDataVec[closest_ridge_set_index]
511 ._tangential_distance;
512 p_info[face_index]->_closest_point_ref =
513 ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[0]._closest_coor_ref;
517 const Node * closest_node_on_face;
519 closest_node_on_face,
520 p_info[face_index]->_side);
523 if (closest_node_on_face !=
524 ridgeSetDataVec[closest_ridge_set_index]._closest_node)
526 mooseError(
"Closest node when restricting point to face != closest node from " 533 std::vector<Point> points(1);
534 points[0] = p_info[face_index]->_closest_point_ref;
535 fe->
reinit(p_info[face_index]->_side, &points);
536 p_info[face_index]->_side_phi = fe->
get_phi();
537 p_info[face_index]->_side_grad_phi = fe->
get_dphi();
553 unsigned int best(0), i(1);
571 }
while (i < p_info.size() && best < p_info.size());
572 if (best < p_info.size())
605 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