www.mooseframework.org
Classes | Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes | List of all members
PenetrationThread Class Reference

#include <PenetrationThread.h>

Classes

struct  RidgeData
 
struct  RidgeSetData
 

Public Member Functions

 PenetrationThread (SubProblem &subproblem, const MooseMesh &mesh, BoundaryID master_boundary, BoundaryID slave_boundary, std::map< dof_id_type, PenetrationInfo * > &penetration_info, bool check_whether_reasonable, bool update_location, Real tangential_tolerance, bool do_normal_smoothing, Real normal_smoothing_distance, PenetrationLocator::NORMAL_SMOOTHING_METHOD normal_smoothing_method, std::vector< std::vector< FEBase * >> &fes, FEType &fe_type, NearestNodeLocator &nearest_node, const std::map< dof_id_type, std::vector< dof_id_type >> &node_to_elem_map, std::vector< dof_id_type > &elem_list, std::vector< unsigned short int > &side_list, std::vector< boundary_id_type > &id_list)
 
 PenetrationThread (PenetrationThread &x, Threads::split split)
 
void operator() (const NodeIdRange &range)
 
void join (const PenetrationThread &other)
 

Protected Types

enum  CompeteInteractionResult { FIRST_WINS, SECOND_WINS, NEITHER_WINS }
 
enum  CommonEdgeResult { NO_COMMON, COMMON_EDGE, COMMON_NODE, EDGE_AND_COMMON_NODE }
 

Protected Member Functions

CompeteInteractionResult competeInteractions (PenetrationInfo *pi1, PenetrationInfo *pi2)
 
CommonEdgeResult interactionsOffCommonEdge (PenetrationInfo *pi1, PenetrationInfo *pi2)
 
bool findRidgeContactPoint (Point &contact_point, Real &tangential_distance, const Node *&closest_node, unsigned int &index, Point &contact_point_ref, std::vector< PenetrationInfo * > &p_info, const unsigned int index1, const unsigned int index2)
 
void getSideCornerNodes (const Elem *side, std::vector< const Node * > &corner_nodes)
 
bool restrictPointToSpecifiedEdgeOfFace (Point &p, const Node *&closest_node, const Elem *side, const std::vector< const Node * > &edge_nodes)
 
bool restrictPointToFace (Point &p, const Node *&closest_node, const Elem *side)
 
bool isFaceReasonableCandidate (const Elem *master_elem, const Elem *side, FEBase *fe, const Point *slave_point, const Real tangential_tolerance)
 
void smoothNormal (PenetrationInfo *info, std::vector< PenetrationInfo * > &p_info)
 
void getSmoothingFacesAndWeights (PenetrationInfo *info, std::vector< PenetrationInfo * > &edge_face_info, std::vector< Real > &edge_face_weights, std::vector< PenetrationInfo * > &p_info)
 
void getSmoothingEdgeNodesAndWeights (const Point &p, const Elem *side, std::vector< std::vector< const Node * >> &edge_nodes, std::vector< Real > &edge_face_weights)
 
void getInfoForFacesWithCommonNodes (const Node *slave_node, const std::set< dof_id_type > &elems_to_exclude, const std::vector< const Node * > edge_nodes, std::vector< PenetrationInfo * > &face_info_comm_edge, std::vector< PenetrationInfo * > &p_info)
 
void getInfoForElem (std::vector< PenetrationInfo * > &thisElemInfo, std::vector< PenetrationInfo * > &p_info, const Elem *elem)
 
void createInfoForElem (std::vector< PenetrationInfo * > &thisElemInfo, std::vector< PenetrationInfo * > &p_info, const Node *slave_node, const Elem *elem, const std::vector< const Node * > &nodes_that_must_be_on_side, const bool check_whether_reasonable=false)
 
void getSidesOnMasterBoundary (std::vector< unsigned int > &sides, const Elem *const elem)
 
void computeSlip (FEBase &fe, PenetrationInfo &info)
 
void switchInfo (PenetrationInfo *&info, PenetrationInfo *&infoNew)
 

Protected Attributes

SubProblem_subproblem
 
const MooseMesh_mesh
 
BoundaryID _master_boundary
 
BoundaryID _slave_boundary
 
std::map< dof_id_type, PenetrationInfo * > & _penetration_info
 
bool _check_whether_reasonable
 
bool _update_location
 
Real _tangential_tolerance
 
bool _do_normal_smoothing
 
Real _normal_smoothing_distance
 
PenetrationLocator::NORMAL_SMOOTHING_METHOD _normal_smoothing_method
 
MooseVariable_nodal_normal_x
 
MooseVariable_nodal_normal_y
 
MooseVariable_nodal_normal_z
 
std::vector< std::vector< FEBase * > > & _fes
 
FEType & _fe_type
 
NearestNodeLocator_nearest_node
 
const std::map< dof_id_type, std::vector< dof_id_type > > & _node_to_elem_map
 
std::vector< dof_id_type > & _elem_list
 
std::vector< unsigned short int > & _side_list
 
std::vector< boundary_id_type > & _id_list
 
unsigned int _n_elems
 
THREAD_ID _tid
 

Detailed Description

Definition at line 25 of file PenetrationThread.h.

Member Enumeration Documentation

Enumerator
NO_COMMON 
COMMON_EDGE 
COMMON_NODE 
EDGE_AND_COMMON_NODE 

Definition at line 97 of file PenetrationThread.h.

Enumerator
FIRST_WINS 
SECOND_WINS 
NEITHER_WINS 

Definition at line 90 of file PenetrationThread.h.

Constructor & Destructor Documentation

PenetrationThread::PenetrationThread ( SubProblem subproblem,
const MooseMesh mesh,
BoundaryID  master_boundary,
BoundaryID  slave_boundary,
std::map< dof_id_type, PenetrationInfo * > &  penetration_info,
bool  check_whether_reasonable,
bool  update_location,
Real  tangential_tolerance,
bool  do_normal_smoothing,
Real  normal_smoothing_distance,
PenetrationLocator::NORMAL_SMOOTHING_METHOD  normal_smoothing_method,
std::vector< std::vector< FEBase * >> &  fes,
FEType &  fe_type,
NearestNodeLocator nearest_node,
const std::map< dof_id_type, std::vector< dof_id_type >> &  node_to_elem_map,
std::vector< dof_id_type > &  elem_list,
std::vector< unsigned short int > &  side_list,
std::vector< boundary_id_type > &  id_list 
)

Definition at line 31 of file PenetrationThread.C.

50  : _subproblem(subproblem),
51  _mesh(mesh),
52  _master_boundary(master_boundary),
53  _slave_boundary(slave_boundary),
54  _penetration_info(penetration_info),
55  _check_whether_reasonable(check_whether_reasonable),
56  _update_location(update_location),
57  _tangential_tolerance(tangential_tolerance),
58  _do_normal_smoothing(do_normal_smoothing),
59  _normal_smoothing_distance(normal_smoothing_distance),
60  _normal_smoothing_method(normal_smoothing_method),
61  _nodal_normal_x(NULL),
62  _nodal_normal_y(NULL),
63  _nodal_normal_z(NULL),
64  _fes(fes),
65  _fe_type(fe_type),
66  _nearest_node(nearest_node),
67  _node_to_elem_map(node_to_elem_map),
68  _elem_list(elem_list),
69  _side_list(side_list),
70  _id_list(id_list),
71  _n_elems(elem_list.size())
72 {
73 }
MooseVariable * _nodal_normal_z
unsigned int _n_elems
BoundaryID _master_boundary
NearestNodeLocator & _nearest_node
std::vector< unsigned short int > & _side_list
SubProblem & _subproblem
const MooseMesh & _mesh
std::vector< std::vector< FEBase * > > & _fes
std::vector< dof_id_type > & _elem_list
std::map< dof_id_type, PenetrationInfo * > & _penetration_info
MooseVariable * _nodal_normal_y
std::vector< boundary_id_type > & _id_list
const std::map< dof_id_type, std::vector< dof_id_type > > & _node_to_elem_map
MooseVariable * _nodal_normal_x
PenetrationLocator::NORMAL_SMOOTHING_METHOD _normal_smoothing_method
BoundaryID _slave_boundary
PenetrationThread::PenetrationThread ( PenetrationThread x,
Threads::split  split 
)

Definition at line 76 of file PenetrationThread.C.

78  _mesh(x._mesh),
88  _fes(x._fes),
89  _fe_type(x._fe_type),
94  _id_list(x._id_list),
96 {
97 }
unsigned int _n_elems
BoundaryID _master_boundary
NearestNodeLocator & _nearest_node
std::vector< unsigned short int > & _side_list
SubProblem & _subproblem
const MooseMesh & _mesh
std::vector< std::vector< FEBase * > > & _fes
std::vector< dof_id_type > & _elem_list
std::map< dof_id_type, PenetrationInfo * > & _penetration_info
std::vector< boundary_id_type > & _id_list
const std::map< dof_id_type, std::vector< dof_id_type > > & _node_to_elem_map
PenetrationLocator::NORMAL_SMOOTHING_METHOD _normal_smoothing_method
BoundaryID _slave_boundary

Member Function Documentation

PenetrationThread::CompeteInteractionResult PenetrationThread::competeInteractions ( PenetrationInfo pi1,
PenetrationInfo pi2 
)
protected

Definition at line 507 of file PenetrationThread.C.

Referenced by operator()().

508 {
509 
511 
513  pi2->_tangential_distance > _tangential_tolerance) // out of tol on both faces
514  result = NEITHER_WINS;
515 
516  else if (pi1->_tangential_distance == 0.0 &&
517  pi2->_tangential_distance > 0.0) // on face 1, off face 2
518  result = FIRST_WINS;
519 
520  else if (pi2->_tangential_distance == 0.0 &&
521  pi1->_tangential_distance > 0.0) // on face 2, off face 1
522  result = SECOND_WINS;
523 
524  else if (pi1->_tangential_distance <= _tangential_tolerance &&
525  pi2->_tangential_distance > _tangential_tolerance) // in face 1 tol, out of face 2 tol
526  result = FIRST_WINS;
527 
528  else if (pi2->_tangential_distance <= _tangential_tolerance &&
529  pi1->_tangential_distance > _tangential_tolerance) // in face 2 tol, out of face 1 tol
530  result = SECOND_WINS;
531 
532  else if (pi1->_tangential_distance == 0.0 && pi2->_tangential_distance == 0.0) // on both faces
533  {
534  if (pi1->_distance >= 0.0 &&
535  pi2->_distance < 0.0) // favor face with positive distance (penetrated)
536  result = FIRST_WINS;
537 
538  else if (pi2->_distance >= 0.0 && pi1->_distance < 0.0)
539  result = SECOND_WINS;
540 
541  else if (std::abs(pi1->_distance) < std::abs(pi2->_distance)) // otherwise, favor the closer
542  // face
543  {
544  // TODO: This could cause an abrupt jump from one face to the other. Smooth this transition
545  // Moose::out<<"Case1: n: "<<pi1->_node->id()<<" e1: "<<pi1->_elem->id()<<" e2:
546  // "<<pi2->_elem->id()<<std::endl;
547  result = FIRST_WINS;
548  }
549  else if (std::abs(pi2->_distance) < std::abs(pi1->_distance)) // otherwise, favor the closer
550  // face
551  {
552  // TODO: This could cause an abrupt jump from one face to the other. Smooth this transition
553  // Moose::out<<"Case2: n: "<<pi1->_node->id()<<" e1: "<<pi1->_elem->id()<<" e2:
554  // "<<pi2->_elem->id()<<std::endl;
555  result = SECOND_WINS;
556  }
557  else // completely equal. Favor the one with a smaller element id (for repeatibility)
558  {
559  // TODO: This could cause an abrupt jump from one face to the other. Smooth this transition
560  // Moose::out<<"Case3: n: "<<pi1->_node->id()<<" e1: "<<pi1->_elem->id()<<" e2:
561  // "<<pi2->_elem->id()<<std::endl;
562  if (pi1->_elem->id() < pi2->_elem->id())
563  result = FIRST_WINS;
564 
565  else
566  result = SECOND_WINS;
567  }
568  }
569  else if (pi1->_tangential_distance <= _tangential_tolerance &&
570  pi2->_tangential_distance <= _tangential_tolerance) // off but within tol of both faces
571  {
573  if (cer == COMMON_EDGE || cer == COMMON_NODE) // ridge case.
574  {
575  // We already checked for ridges, and it got rejected, so neither face must be valid
576  result = NEITHER_WINS;
577  // mooseError("Erroneously encountered ridge case");
578  }
579  else if (cer == EDGE_AND_COMMON_NODE) // off side of face, off corner of another face. Favor
580  // the off-side face
581  {
582  if (pi1->_off_edge_nodes.size() == pi2->_off_edge_nodes.size())
583  mooseError("Invalid off_edge_nodes counts");
584 
585  else if (pi1->_off_edge_nodes.size() == 2)
586  result = FIRST_WINS;
587 
588  else if (pi2->_off_edge_nodes.size() == 2)
589  result = SECOND_WINS;
590 
591  else
592  mooseError("Invalid off_edge_nodes counts");
593  }
594  else // Use the same logic as in the on-face condition (above). A little copy-paste can't
595  // hurt...
596  {
597  if (pi1->_distance >= 0.0 &&
598  pi2->_distance < 0.0) // favor face with positive distance (penetrated)
599  result = FIRST_WINS;
600 
601  else if (pi2->_distance >= 0.0 && pi1->_distance < 0.0)
602  result = SECOND_WINS;
603 
604  else if (std::abs(pi1->_distance) <
605  std::abs(pi2->_distance)) // otherwise, favor the closer face
606  result = FIRST_WINS;
607 
608  else if (std::abs(pi2->_distance) <
609  std::abs(pi1->_distance)) // otherwise, favor the closer face
610  result = SECOND_WINS;
611 
612  else // completely equal. Favor the one with a smaller element id (for repeatibility)
613  {
614  if (pi1->_elem->id() < pi2->_elem->id())
615  result = FIRST_WINS;
616 
617  else
618  result = SECOND_WINS;
619  }
620  }
621  }
622 
623  return result;
624 }
void mooseError(Args &&...args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:182
const Elem * _elem
std::vector< const Node * > _off_edge_nodes
CommonEdgeResult interactionsOffCommonEdge(PenetrationInfo *pi1, PenetrationInfo *pi2)
void PenetrationThread::computeSlip ( FEBase &  fe,
PenetrationInfo info 
)
protected

Definition at line 1234 of file PenetrationThread.C.

Referenced by operator()().

1235 {
1236  // Slip is current projected position of slave node minus
1237  // original projected position of slave node
1238  std::vector<Point> points(1);
1239  points[0] = info._starting_closest_point_ref;
1240  std::unique_ptr<const Elem> side =
1241  info._starting_elem->build_side_ptr(info._starting_side_num, false);
1242  fe.reinit(side.get(), &points);
1243  const std::vector<Point> & starting_point = fe.get_xyz();
1244  info._incremental_slip = info._closest_point - starting_point[0];
1245  if (info.isCaptured())
1246  {
1247  info._frictional_energy =
1249  info._accumulated_slip = info._accumulated_slip_old + info._incremental_slip.norm();
1250  }
1251 }
const Elem * _starting_elem
bool isCaptured() const
unsigned int _starting_side_num
RealVectorValue _contact_force
Point _starting_closest_point_ref
void PenetrationThread::createInfoForElem ( std::vector< PenetrationInfo * > &  thisElemInfo,
std::vector< PenetrationInfo * > &  p_info,
const Node *  slave_node,
const Elem *  elem,
const std::vector< const Node * > &  nodes_that_must_be_on_side,
const bool  check_whether_reasonable = false 
)
protected

Definition at line 1649 of file PenetrationThread.C.

Referenced by getInfoForFacesWithCommonNodes(), and operator()().

1655 {
1656  std::vector<unsigned int> sides;
1657  // TODO: After libMesh update, add this line to MooseMesh.h, call sidesWithBoundaryID, delete
1658  // getSidesOnMasterBoundary, and delete vectors used by it
1659  // void sidesWithBoundaryID(std::vector<unsigned int>& sides, const Elem * const elem, const
1660  // BoundaryID boundary_id) const
1661  // {
1662  // _mesh.get_boundary_info().sides_with_boundary_id(sides, elem, boundary_id);
1663  // }
1664  getSidesOnMasterBoundary(sides, elem);
1665  // _mesh.sidesWithBoundaryID(sides, elem, _master_boundary);
1666 
1667  for (unsigned int i = 0; i < sides.size(); ++i)
1668  {
1669  // Don't create info for this side if one already exists
1670  bool already_have_info_this_side = false;
1671  for (const auto & pi : thisElemInfo)
1672  if (pi->_side_num == sides[i])
1673  {
1674  already_have_info_this_side = true;
1675  break;
1676  }
1677 
1678  if (already_have_info_this_side)
1679  break;
1680 
1681  const Elem * side = (elem->build_side_ptr(sides[i], false)).release();
1682 
1683  // Only continue with creating info for this side if the side contains
1684  // all of the nodes in nodes_that_must_be_on_side
1685  std::vector<const Node *> nodevec;
1686  for (unsigned int ni = 0; ni < side->n_nodes(); ++ni)
1687  nodevec.push_back(side->node_ptr(ni));
1688 
1689  std::sort(nodevec.begin(), nodevec.end());
1690  std::vector<const Node *> common_nodes;
1691  std::set_intersection(nodes_that_must_be_on_side.begin(),
1692  nodes_that_must_be_on_side.end(),
1693  nodevec.begin(),
1694  nodevec.end(),
1695  std::inserter(common_nodes, common_nodes.end()));
1696  if (common_nodes.size() != nodes_that_must_be_on_side.size())
1697  {
1698  delete side;
1699  break;
1700  }
1701 
1702  FEBase * fe_elem = _fes[_tid][elem->dim()];
1703  FEBase * fe_side = _fes[_tid][side->dim()];
1704 
1705  // Optionally check to see whether face is reasonable candidate based on an
1706  // estimate of how closely it is likely to project to the face
1707  if (check_whether_reasonable)
1708  if (!isFaceReasonableCandidate(elem, side, fe_side, slave_node, _tangential_tolerance))
1709  {
1710  delete side;
1711  break;
1712  }
1713 
1714  Point contact_phys;
1715  Point contact_ref;
1716  Point contact_on_face_ref;
1717  Real distance = 0.;
1718  Real tangential_distance = 0.;
1719  RealGradient normal;
1720  bool contact_point_on_side;
1721  std::vector<const Node *> off_edge_nodes;
1722  std::vector<std::vector<Real>> side_phi;
1723  std::vector<std::vector<RealGradient>> side_grad_phi;
1724  std::vector<RealGradient> dxyzdxi;
1725  std::vector<RealGradient> dxyzdeta;
1726  std::vector<RealGradient> d2xyzdxideta;
1727 
1728  PenetrationInfo * pen_info = new PenetrationInfo(slave_node,
1729  elem,
1730  side,
1731  sides[i],
1732  normal,
1733  distance,
1734  tangential_distance,
1735  contact_phys,
1736  contact_ref,
1737  contact_on_face_ref,
1738  off_edge_nodes,
1739  side_phi,
1740  side_grad_phi,
1741  dxyzdxi,
1742  dxyzdeta,
1743  d2xyzdxideta);
1744 
1745  Moose::findContactPoint(*pen_info,
1746  fe_elem,
1747  fe_side,
1748  _fe_type,
1749  *slave_node,
1750  true,
1752  contact_point_on_side);
1753 
1754  thisElemInfo.push_back(pen_info);
1755 
1756  p_info.push_back(pen_info);
1757  }
1758 }
RealVectorValue RealGradient
Definition: Assembly.h:43
void getSidesOnMasterBoundary(std::vector< unsigned int > &sides, const Elem *const elem)
FEGenericBase< Real > FEBase
Definition: Assembly.h:34
Data structure used to hold penetration information.
void findContactPoint(PenetrationInfo &p_info, FEBase *fe_elem, FEBase *fe_side, FEType &fe_side_type, const Point &slave_point, bool start_with_centroid, const Real tangential_tolerance, bool &contact_point_on_side)
Finds the closest point (called the contact point) on the master_elem on side "side" to the slave_poi...
std::vector< std::vector< FEBase * > > & _fes
bool isFaceReasonableCandidate(const Elem *master_elem, const Elem *side, FEBase *fe, const Point *slave_point, const Real tangential_tolerance)
bool PenetrationThread::findRidgeContactPoint ( Point &  contact_point,
Real &  tangential_distance,
const Node *&  closest_node,
unsigned int &  index,
Point &  contact_point_ref,
std::vector< PenetrationInfo * > &  p_info,
const unsigned int  index1,
const unsigned int  index2 
)
protected

Definition at line 681 of file PenetrationThread.C.

Referenced by operator()().

689 {
690  tangential_distance = 0.0;
691  closest_node = NULL;
692  PenetrationInfo * pi1 = p_info[index1];
693  PenetrationInfo * pi2 = p_info[index2];
694  const unsigned sidedim(pi1->_side->dim());
695  mooseAssert(sidedim == pi2->_side->dim(), "Incompatible dimensionalities");
696 
697  // Nodes on faces for the two interactions
698  std::vector<const Node *> side1_nodes;
699  getSideCornerNodes(pi1->_side, side1_nodes);
700  std::vector<const Node *> side2_nodes;
701  getSideCornerNodes(pi2->_side, side2_nodes);
702 
703  std::sort(side1_nodes.begin(), side1_nodes.end());
704  std::sort(side2_nodes.begin(), side2_nodes.end());
705 
706  // Find nodes shared by the two faces
707  std::vector<const Node *> common_nodes;
708  std::set_intersection(side1_nodes.begin(),
709  side1_nodes.end(),
710  side2_nodes.begin(),
711  side2_nodes.end(),
712  std::inserter(common_nodes, common_nodes.end()));
713 
714  if (common_nodes.size() != sidedim)
715  return false;
716 
717  bool found_point1, found_point2;
718  Point closest_coor_ref1(pi1->_closest_point_ref);
719  const Node * closest_node1;
720  found_point1 = restrictPointToSpecifiedEdgeOfFace(
721  closest_coor_ref1, closest_node1, pi1->_side, common_nodes);
722 
723  Point closest_coor_ref2(pi2->_closest_point_ref);
724  const Node * closest_node2;
725  found_point2 = restrictPointToSpecifiedEdgeOfFace(
726  closest_coor_ref2, closest_node2, pi2->_side, common_nodes);
727 
728  if (!found_point1 || !found_point2)
729  return false;
730 
731  // if (sidedim == 2)
732  // {
733  // TODO:
734  // We have the parametric coordinates of the closest intersection point for both faces.
735  // We need to find a point somewhere in the middle of them so there's not an abrupt jump.
736  // Find that point by taking dot products of vector from contact point to slave node point
737  // with face normal vectors to see which face we're closer to.
738  // }
739 
740  FEBase * fe = NULL;
741  std::vector<Point> points(1);
742 
743  // We have to pick one of the two faces to own the contact point. It doesn't really matter
744  // which one we pick. For repeatibility, pick the face with the lowest index.
745  if (index1 < index2)
746  {
747  fe = _fes[_tid][pi1->_side->dim()];
748  contact_point_ref = closest_coor_ref1;
749  points[0] = closest_coor_ref1;
750  fe->reinit(pi1->_side, &points);
751  index = index1;
752  }
753  else
754  {
755  fe = _fes[_tid][pi2->_side->dim()];
756  contact_point_ref = closest_coor_ref2;
757  points[0] = closest_coor_ref2;
758  fe->reinit(pi2->_side, &points);
759  index = index2;
760  }
761 
762  contact_point = fe->get_xyz()[0];
763 
764  if (sidedim == 2)
765  {
766  if (closest_node1) // point is off the ridge between the two elements
767  {
768  mooseAssert((closest_node1 == closest_node2 || closest_node2 == NULL),
769  "If off edge of ridge, closest node must be the same on both elements");
770  closest_node = closest_node1;
771 
772  RealGradient off_face = *closest_node1 - contact_point;
773  tangential_distance = off_face.norm();
774  }
775  }
776 
777  return true;
778 }
RealVectorValue RealGradient
Definition: Assembly.h:43
FEGenericBase< Real > FEBase
Definition: Assembly.h:34
Data structure used to hold penetration information.
void getSideCornerNodes(const Elem *side, std::vector< const Node * > &corner_nodes)
bool restrictPointToSpecifiedEdgeOfFace(Point &p, const Node *&closest_node, const Elem *side, const std::vector< const Node * > &edge_nodes)
std::vector< std::vector< FEBase * > > & _fes
const Elem * _side
void PenetrationThread::getInfoForElem ( std::vector< PenetrationInfo * > &  thisElemInfo,
std::vector< PenetrationInfo * > &  p_info,
const Elem *  elem 
)
protected

Definition at line 1634 of file PenetrationThread.C.

Referenced by getInfoForFacesWithCommonNodes().

1637 {
1638  for (const auto & pi : p_info)
1639  {
1640  if (!pi)
1641  continue;
1642 
1643  if (pi->_elem == elem)
1644  thisElemInfo.push_back(pi);
1645  }
1646 }
void PenetrationThread::getInfoForFacesWithCommonNodes ( const Node *  slave_node,
const std::set< dof_id_type > &  elems_to_exclude,
const std::vector< const Node * >  edge_nodes,
std::vector< PenetrationInfo * > &  face_info_comm_edge,
std::vector< PenetrationInfo * > &  p_info 
)
protected

Definition at line 1545 of file PenetrationThread.C.

Referenced by getSmoothingFacesAndWeights().

1551 {
1552  // elems connected to a node on this edge, find one that has the same corners as this, and is not
1553  // the current elem
1554  auto node_to_elem_pair = _node_to_elem_map.find(edge_nodes[0]->id()); // just need one of the
1555  // nodes
1556  mooseAssert(node_to_elem_pair != _node_to_elem_map.end(), "Missing entry in node to elem map");
1557  const std::vector<dof_id_type> & elems_connected_to_node = node_to_elem_pair->second;
1558 
1559  std::vector<const Elem *> elems_connected_to_edge;
1560 
1561  for (unsigned int ecni = 0; ecni < elems_connected_to_node.size(); ecni++)
1562  {
1563  if (elems_to_exclude.find(elems_connected_to_node[ecni]) != elems_to_exclude.end())
1564  continue;
1565  const Elem * elem = _mesh.elemPtr(elems_connected_to_node[ecni]);
1566 
1567  std::vector<const Node *> nodevec;
1568  for (unsigned int ni = 0; ni < elem->n_nodes(); ++ni)
1569  if (elem->is_vertex(ni))
1570  nodevec.push_back(elem->node_ptr(ni));
1571 
1572  std::vector<const Node *> common_nodes;
1573  std::sort(nodevec.begin(), nodevec.end());
1574  std::set_intersection(edge_nodes.begin(),
1575  edge_nodes.end(),
1576  nodevec.begin(),
1577  nodevec.end(),
1578  std::inserter(common_nodes, common_nodes.end()));
1579 
1580  if (common_nodes.size() == edge_nodes.size())
1581  elems_connected_to_edge.push_back(elem);
1582  }
1583 
1584  if (elems_connected_to_edge.size() > 0)
1585  {
1586 
1587  // There are potentially multiple elements that share a common edge
1588  // 2D:
1589  // There can only be one element on the same surface
1590  // 3D:
1591  // If there are two edge nodes, there can only be one element on the same surface
1592  // If there is only one edge node (a corner), there could be multiple elements on the same
1593  // surface
1594  bool allowMultipleNeighbors = false;
1595 
1596  if (elems_connected_to_edge[0]->dim() == 3)
1597  {
1598  if (edge_nodes.size() == 1)
1599  {
1600  allowMultipleNeighbors = true;
1601  }
1602  }
1603 
1604  for (unsigned int i = 0; i < elems_connected_to_edge.size(); ++i)
1605  {
1606  std::vector<PenetrationInfo *> thisElemInfo;
1607  getInfoForElem(thisElemInfo, p_info, elems_connected_to_edge[i]);
1608  if (thisElemInfo.size() > 0 && !allowMultipleNeighbors)
1609  {
1610  if (thisElemInfo.size() > 1)
1611  mooseError(
1612  "Found multiple neighbors to current edge/face on surface when only one is allowed");
1613  face_info_comm_edge.push_back(thisElemInfo[0]);
1614  break;
1615  }
1616 
1617  createInfoForElem(thisElemInfo, p_info, slave_node, elems_connected_to_edge[i], edge_nodes);
1618  if (thisElemInfo.size() > 0 && !allowMultipleNeighbors)
1619  {
1620  if (thisElemInfo.size() > 1)
1621  mooseError(
1622  "Found multiple neighbors to current edge/face on surface when only one is allowed");
1623  face_info_comm_edge.push_back(thisElemInfo[0]);
1624  break;
1625  }
1626 
1627  for (unsigned int j = 0; j < thisElemInfo.size(); ++j)
1628  face_info_comm_edge.push_back(thisElemInfo[j]);
1629  }
1630  }
1631 }
virtual Elem * elemPtr(const dof_id_type i)
Definition: MooseMesh.C:2062
void mooseError(Args &&...args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:182
const MooseMesh & _mesh
void getInfoForElem(std::vector< PenetrationInfo * > &thisElemInfo, std::vector< PenetrationInfo * > &p_info, const Elem *elem)
void createInfoForElem(std::vector< PenetrationInfo * > &thisElemInfo, std::vector< PenetrationInfo * > &p_info, const Node *slave_node, const Elem *elem, const std::vector< const Node * > &nodes_that_must_be_on_side, const bool check_whether_reasonable=false)
const std::map< dof_id_type, std::vector< dof_id_type > > & _node_to_elem_map
void PenetrationThread::getSideCornerNodes ( const Elem *  side,
std::vector< const Node * > &  corner_nodes 
)
protected

Definition at line 781 of file PenetrationThread.C.

Referenced by findRidgeContactPoint().

782 {
783  const ElemType t(side->type());
784  corner_nodes.clear();
785 
786  corner_nodes.push_back(side->node_ptr(0));
787  corner_nodes.push_back(side->node_ptr(1));
788  switch (t)
789  {
790  case EDGE2:
791  case EDGE3:
792  case EDGE4:
793  {
794  break;
795  }
796 
797  case TRI3:
798  case TRI6:
799  {
800  corner_nodes.push_back(side->node_ptr(2));
801  break;
802  }
803 
804  case QUAD4:
805  case QUAD8:
806  case QUAD9:
807  {
808  corner_nodes.push_back(side->node_ptr(2));
809  corner_nodes.push_back(side->node_ptr(3));
810  break;
811  }
812 
813  default:
814  {
815  mooseError("Unsupported face type: ", t);
816  break;
817  }
818  }
819 }
void mooseError(Args &&...args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:182
void PenetrationThread::getSidesOnMasterBoundary ( std::vector< unsigned int > &  sides,
const Elem *const  elem 
)
protected

Definition at line 1763 of file PenetrationThread.C.

Referenced by createInfoForElem().

1765 {
1766  sides.clear();
1767  for (unsigned int m = 0; m < _n_elems; ++m)
1768  if (_elem_list[m] == elem->id())
1769  if (_id_list[m] == static_cast<short>(_master_boundary))
1770  sides.push_back(_side_list[m]);
1771 }
unsigned int _n_elems
BoundaryID _master_boundary
std::vector< unsigned short int > & _side_list
PetscInt m
std::vector< dof_id_type > & _elem_list
std::vector< boundary_id_type > & _id_list
void PenetrationThread::getSmoothingEdgeNodesAndWeights ( const Point &  p,
const Elem *  side,
std::vector< std::vector< const Node * >> &  edge_nodes,
std::vector< Real > &  edge_face_weights 
)
protected

Definition at line 1405 of file PenetrationThread.C.

Referenced by getSmoothingFacesAndWeights().

1410 {
1411  const ElemType t(side->type());
1412  const Real & xi = p(0);
1413  const Real & eta = p(1);
1414 
1415  Real smooth_limit = 1.0 - _normal_smoothing_distance;
1416 
1417  switch (t)
1418  {
1419  case EDGE2:
1420  case EDGE3:
1421  case EDGE4:
1422  {
1423  if (xi < -smooth_limit)
1424  {
1425  std::vector<const Node *> en;
1426  en.push_back(side->node_ptr(0));
1427  edge_nodes.push_back(en);
1428  Real fw = 0.5 - (1.0 + xi) / (2.0 * _normal_smoothing_distance);
1429  if (fw > 0.5)
1430  fw = 0.5;
1431  edge_face_weights.push_back(fw);
1432  }
1433  else if (xi > smooth_limit)
1434  {
1435  std::vector<const Node *> en;
1436  en.push_back(side->node_ptr(1));
1437  edge_nodes.push_back(en);
1438  Real fw = 0.5 - (1.0 - xi) / (2.0 * _normal_smoothing_distance);
1439  if (fw > 0.5)
1440  fw = 0.5;
1441  edge_face_weights.push_back(fw);
1442  }
1443  break;
1444  }
1445 
1446  case TRI3:
1447  case TRI6:
1448  {
1449  if (eta < -smooth_limit)
1450  {
1451  std::vector<const Node *> en;
1452  en.push_back(side->node_ptr(0));
1453  en.push_back(side->node_ptr(1));
1454  edge_nodes.push_back(en);
1455  Real fw = 0.5 - (1.0 + eta) / (2.0 * _normal_smoothing_distance);
1456  if (fw > 0.5)
1457  fw = 0.5;
1458  edge_face_weights.push_back(fw);
1459  }
1460  if ((xi + eta) > smooth_limit)
1461  {
1462  std::vector<const Node *> en;
1463  en.push_back(side->node_ptr(1));
1464  en.push_back(side->node_ptr(2));
1465  edge_nodes.push_back(en);
1466  Real fw = 0.5 - (1.0 - xi - eta) / (2.0 * _normal_smoothing_distance);
1467  if (fw > 0.5)
1468  fw = 0.5;
1469  edge_face_weights.push_back(fw);
1470  }
1471  if (xi < -smooth_limit)
1472  {
1473  std::vector<const Node *> en;
1474  en.push_back(side->node_ptr(2));
1475  en.push_back(side->node_ptr(0));
1476  edge_nodes.push_back(en);
1477  Real fw = 0.5 - (1.0 + xi) / (2.0 * _normal_smoothing_distance);
1478  if (fw > 0.5)
1479  fw = 0.5;
1480  edge_face_weights.push_back(fw);
1481  }
1482  break;
1483  }
1484 
1485  case QUAD4:
1486  case QUAD8:
1487  case QUAD9:
1488  {
1489  if (eta < -smooth_limit)
1490  {
1491  std::vector<const Node *> en;
1492  en.push_back(side->node_ptr(0));
1493  en.push_back(side->node_ptr(1));
1494  edge_nodes.push_back(en);
1495  Real fw = 0.5 - (1.0 + eta) / (2.0 * _normal_smoothing_distance);
1496  if (fw > 0.5)
1497  fw = 0.5;
1498  edge_face_weights.push_back(fw);
1499  }
1500  if (xi > smooth_limit)
1501  {
1502  std::vector<const Node *> en;
1503  en.push_back(side->node_ptr(1));
1504  en.push_back(side->node_ptr(2));
1505  edge_nodes.push_back(en);
1506  Real fw = 0.5 - (1.0 - xi) / (2.0 * _normal_smoothing_distance);
1507  if (fw > 0.5)
1508  fw = 0.5;
1509  edge_face_weights.push_back(fw);
1510  }
1511  if (eta > smooth_limit)
1512  {
1513  std::vector<const Node *> en;
1514  en.push_back(side->node_ptr(2));
1515  en.push_back(side->node_ptr(3));
1516  edge_nodes.push_back(en);
1517  Real fw = 0.5 - (1.0 - eta) / (2.0 * _normal_smoothing_distance);
1518  if (fw > 0.5)
1519  fw = 0.5;
1520  edge_face_weights.push_back(fw);
1521  }
1522  if (xi < -smooth_limit)
1523  {
1524  std::vector<const Node *> en;
1525  en.push_back(side->node_ptr(3));
1526  en.push_back(side->node_ptr(0));
1527  edge_nodes.push_back(en);
1528  Real fw = 0.5 - (1.0 + xi) / (2.0 * _normal_smoothing_distance);
1529  if (fw > 0.5)
1530  fw = 0.5;
1531  edge_face_weights.push_back(fw);
1532  }
1533  break;
1534  }
1535 
1536  default:
1537  {
1538  mooseError("Unsupported face type: ", t);
1539  break;
1540  }
1541  }
1542 }
void mooseError(Args &&...args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:182
void PenetrationThread::getSmoothingFacesAndWeights ( PenetrationInfo info,
std::vector< PenetrationInfo * > &  edge_face_info,
std::vector< Real > &  edge_face_weights,
std::vector< PenetrationInfo * > &  p_info 
)
protected

Definition at line 1310 of file PenetrationThread.C.

Referenced by smoothNormal().

1314 {
1315  const Elem * side = info->_side;
1316  const Point & p = info->_closest_point_ref;
1317  std::set<dof_id_type> elems_to_exclude;
1318  elems_to_exclude.insert(info->_elem->id());
1319  const Node * slave_node = info->_node;
1320 
1321  std::vector<std::vector<const Node *>> edge_nodes;
1322 
1323  // Get the pairs of nodes along every edge that we are close enough to smooth with
1324  getSmoothingEdgeNodesAndWeights(p, side, edge_nodes, edge_face_weights);
1325  std::vector<Elem *> edge_neighbor_elems;
1326  edge_face_info.resize(edge_nodes.size(), NULL);
1327 
1328  std::vector<unsigned int> edges_without_neighbors;
1329 
1330  for (unsigned int i = 0; i < edge_nodes.size(); ++i)
1331  {
1332  // Sort all sets of edge nodes (needed for comparing edges)
1333  std::sort(edge_nodes[i].begin(), edge_nodes[i].end());
1334 
1335  std::vector<PenetrationInfo *> face_info_comm_edge;
1337  slave_node, elems_to_exclude, edge_nodes[i], face_info_comm_edge, p_info);
1338 
1339  if (face_info_comm_edge.size() == 0)
1340  edges_without_neighbors.push_back(i);
1341  else if (face_info_comm_edge.size() > 1)
1342  mooseError("Only one neighbor allowed per edge");
1343  else
1344  edge_face_info[i] = face_info_comm_edge[0];
1345  }
1346 
1347  // Remove edges without neighbors from the vector, starting from end
1348  std::vector<unsigned int>::reverse_iterator rit;
1349  for (rit = edges_without_neighbors.rbegin(); rit != edges_without_neighbors.rend(); ++rit)
1350  {
1351  unsigned int index = *rit;
1352  edge_nodes.erase(edge_nodes.begin() + index);
1353  edge_face_weights.erase(edge_face_weights.begin() + index);
1354  edge_face_info.erase(edge_face_info.begin() + index);
1355  }
1356 
1357  // Handle corner case
1358  if (edge_nodes.size() > 1)
1359  {
1360  if (edge_nodes.size() != 2)
1361  mooseError("Invalid number of smoothing edges");
1362 
1363  // find common node
1364  std::vector<const Node *> common_nodes;
1365  std::set_intersection(edge_nodes[0].begin(),
1366  edge_nodes[0].end(),
1367  edge_nodes[1].begin(),
1368  edge_nodes[1].end(),
1369  std::inserter(common_nodes, common_nodes.end()));
1370 
1371  if (common_nodes.size() != 1)
1372  mooseError("Invalid number of common nodes");
1373 
1374  for (const auto & pinfo : edge_face_info)
1375  elems_to_exclude.insert(pinfo->_elem->id());
1376 
1377  std::vector<PenetrationInfo *> face_info_comm_edge;
1379  slave_node, elems_to_exclude, common_nodes, face_info_comm_edge, p_info);
1380 
1381  unsigned int num_corner_neighbors = face_info_comm_edge.size();
1382 
1383  if (num_corner_neighbors > 0)
1384  {
1385  Real fw0 = edge_face_weights[0];
1386  Real fw1 = edge_face_weights[1];
1387 
1388  // Corner weight is product of edge weights. Spread out over multiple neighbors.
1389  Real fw_corner = (fw0 * fw1) / static_cast<Real>(num_corner_neighbors);
1390 
1391  // Adjust original edge weights
1392  edge_face_weights[0] *= (1.0 - fw1);
1393  edge_face_weights[1] *= (1.0 - fw0);
1394 
1395  for (unsigned int i = 0; i < num_corner_neighbors; ++i)
1396  {
1397  edge_face_weights.push_back(fw_corner);
1398  edge_face_info.push_back(face_info_comm_edge[i]);
1399  }
1400  }
1401  }
1402 }
void mooseError(Args &&...args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:182
void getSmoothingEdgeNodesAndWeights(const Point &p, const Elem *side, std::vector< std::vector< const Node * >> &edge_nodes, std::vector< Real > &edge_face_weights)
const Elem * _elem
const Elem * _side
void getInfoForFacesWithCommonNodes(const Node *slave_node, const std::set< dof_id_type > &elems_to_exclude, const std::vector< const Node * > edge_nodes, std::vector< PenetrationInfo * > &face_info_comm_edge, std::vector< PenetrationInfo * > &p_info)
const Node * _node
PenetrationThread::CommonEdgeResult PenetrationThread::interactionsOffCommonEdge ( PenetrationInfo pi1,
PenetrationInfo pi2 
)
protected

Definition at line 627 of file PenetrationThread.C.

Referenced by competeInteractions().

628 {
629  CommonEdgeResult common_edge(NO_COMMON);
630  const std::vector<const Node *> & off_edge_nodes1 = pi1->_off_edge_nodes;
631  const std::vector<const Node *> & off_edge_nodes2 = pi2->_off_edge_nodes;
632  const unsigned dim1 = pi1->_side->dim();
633 
634  if (dim1 == 1)
635  {
636  mooseAssert(pi2->_side->dim() == 1, "Incompatible dimensions.");
637  mooseAssert(off_edge_nodes1.size() < 2 && off_edge_nodes2.size() < 2,
638  "off_edge_nodes size should be <2 for 2D contact");
639  if (off_edge_nodes1.size() == 1 && off_edge_nodes2.size() == 1 &&
640  off_edge_nodes1[0] == off_edge_nodes2[0])
641  common_edge = COMMON_EDGE;
642  }
643  else
644  {
645  mooseAssert(dim1 == 2 && pi2->_side->dim() == 2, "Incompatible dimensions.");
646  mooseAssert(off_edge_nodes1.size() < 3 && off_edge_nodes2.size() < 3,
647  "off_edge_nodes size should be <3 for 3D contact");
648  if (off_edge_nodes1.size() == 1)
649  {
650  if (off_edge_nodes2.size() == 1)
651  {
652  if (off_edge_nodes1[0] == off_edge_nodes2[0])
653  common_edge = COMMON_NODE;
654  }
655  else if (off_edge_nodes2.size() == 2)
656  {
657  if (off_edge_nodes1[0] == off_edge_nodes2[0] || off_edge_nodes1[0] == off_edge_nodes2[1])
658  common_edge = EDGE_AND_COMMON_NODE;
659  }
660  }
661  else if (off_edge_nodes1.size() == 2)
662  {
663  if (off_edge_nodes2.size() == 1)
664  {
665  if (off_edge_nodes1[0] == off_edge_nodes2[0] || off_edge_nodes1[1] == off_edge_nodes2[0])
666  common_edge = EDGE_AND_COMMON_NODE;
667  }
668  else if (off_edge_nodes2.size() == 2)
669  {
670  if ((off_edge_nodes1[0] == off_edge_nodes2[0] &&
671  off_edge_nodes1[1] == off_edge_nodes2[1]) ||
672  (off_edge_nodes1[1] == off_edge_nodes2[0] && off_edge_nodes1[0] == off_edge_nodes2[1]))
673  common_edge = COMMON_EDGE;
674  }
675  }
676  }
677  return common_edge;
678 }
const Elem * _side
std::vector< const Node * > _off_edge_nodes
bool PenetrationThread::isFaceReasonableCandidate ( const Elem *  master_elem,
const Elem *  side,
FEBase *  fe,
const Point *  slave_point,
const Real  tangential_tolerance 
)
protected

Definition at line 1175 of file PenetrationThread.C.

Referenced by createInfoForElem().

1180 {
1181  unsigned int dim = master_elem->dim();
1182 
1183  const std::vector<Point> & phys_point = fe->get_xyz();
1184 
1185  const std::vector<RealGradient> & dxyz_dxi = fe->get_dxyzdxi();
1186  const std::vector<RealGradient> & dxyz_deta = fe->get_dxyzdeta();
1187 
1188  Point ref_point;
1189 
1190  std::vector<Point> points(1); // Default constructor gives us a point at 0,0,0
1191 
1192  fe->reinit(side, &points);
1193 
1194  RealGradient d = *slave_point - phys_point[0];
1195 
1196  const Real twosqrt2 = 2.8284; // way more precision than we actually need here
1197  Real max_face_length = side->hmax() + twosqrt2 * tangential_tolerance;
1198 
1199  RealVectorValue normal;
1200  if (dim - 1 == 2)
1201  {
1202  normal = dxyz_dxi[0].cross(dxyz_deta[0]);
1203  }
1204  else if (dim - 1 == 1)
1205  {
1206  normal = RealGradient(dxyz_dxi[0](1), -dxyz_dxi[0](0));
1207  }
1208  else
1209  {
1210  return true;
1211  }
1212  normal /= normal.norm();
1213 
1214  const Real dot(d * normal);
1215 
1216  const RealGradient normcomp = dot * normal;
1217  const RealGradient tangcomp = d - normcomp;
1218 
1219  const Real tangdist = tangcomp.norm();
1220 
1221  // Increase the size of the zone that we consider if the vector from the face
1222  // to the node has a larger normal component
1223  const Real faceExpansionFactor = 2.0 * (1.0 + normcomp.norm() / d.norm());
1224 
1225  bool isReasonableCandidate = true;
1226  if (tangdist > faceExpansionFactor * max_face_length)
1227  {
1228  isReasonableCandidate = false;
1229  }
1230  return isReasonableCandidate;
1231 }
RealVectorValue RealGradient
Definition: Assembly.h:43
VectorValue< Real > RealVectorValue
Definition: Assembly.h:40
void PenetrationThread::join ( const PenetrationThread other)

Definition at line 467 of file PenetrationThread.C.

468 {
469 }
void PenetrationThread::operator() ( const NodeIdRange range)

Definition at line 100 of file PenetrationThread.C.

101 {
102  ParallelUniqueId puid;
103  _tid = puid.id;
104 
105  // Must get the variables every time this is run because _tid can change
106  if (_do_normal_smoothing &&
108  {
109  _nodal_normal_x = &_subproblem.getVariable(_tid, "nodal_normal_x");
110  _nodal_normal_y = &_subproblem.getVariable(_tid, "nodal_normal_y");
111  _nodal_normal_z = &_subproblem.getVariable(_tid, "nodal_normal_z");
112  }
113 
114  for (const auto & node_id : range)
115  {
116  const Node & node = _mesh.nodeRef(node_id);
117 
118  // We're going to get a reference to the pointer for the pinfo for this node
119  // This will allow us to manipulate this pointer without having to go through
120  // the _penetration_info map... meaning this is the only mutex we'll have to do!
121  pinfo_mutex.lock();
122  PenetrationInfo *& info = _penetration_info[node.id()];
123  pinfo_mutex.unlock();
124 
125  std::vector<PenetrationInfo *> p_info;
126  bool info_set(false);
127 
128  // See if we already have info about this node
129  if (info)
130  {
131  FEBase * fe_elem = _fes[_tid][info->_elem->dim()];
132  FEBase * fe_side = _fes[_tid][info->_side->dim()];
133 
134  if (!_update_location && (info->_distance >= 0 || info->isCaptured()))
135  {
136  const Point contact_ref = info->_closest_point_ref;
137  bool contact_point_on_side(false);
138 
139  // Slave position must be the previous contact point
140  // Use the previous reference coordinates
141  std::vector<Point> points(1);
142  points[0] = contact_ref;
143  fe_side->reinit(info->_side, &points);
144  const std::vector<Point> slave_pos = fe_side->get_xyz();
146  fe_elem,
147  fe_side,
148  _fe_type,
149  slave_pos[0],
150  false,
152  contact_point_on_side);
153 
154  // Restore the original reference coordinates
155  info->_closest_point_ref = contact_ref;
156  // Just calculated as the distance of the contact point off the surface (0). Set to 0 to
157  // avoid round-off.
158  info->_distance = 0.0;
159  info_set = true;
160  }
161  else
162  {
163  Real old_tangential_distance(info->_tangential_distance);
164  bool contact_point_on_side(false);
165 
167  fe_elem,
168  fe_side,
169  _fe_type,
170  node,
171  false,
173  contact_point_on_side);
174 
175  if (contact_point_on_side)
176  {
177  if (info->_tangential_distance <= 0.0) // on the face
178  {
179  info_set = true;
180  }
181  else if (info->_tangential_distance > 0.0 && old_tangential_distance > 0.0)
182  { // off the face but within tolerance, was that way on the last step too
183  if (info->_side->dim() == 2 && info->_off_edge_nodes.size() < 2)
184  { // Closest point on face is on a node rather than an edge. Another
185  // face might be a better candidate.
186  }
187  else
188  {
189  info_set = true;
190  }
191  }
192  }
193  }
194  }
195 
196  if (!info_set)
197  {
198  const Node * closest_node = _nearest_node.nearestNode(node.id());
199  auto node_to_elem_pair = _node_to_elem_map.find(closest_node->id());
200  mooseAssert(node_to_elem_pair != _node_to_elem_map.end(),
201  "Missing entry in node to elem map");
202  const std::vector<dof_id_type> & closest_elems = node_to_elem_pair->second;
203 
204  for (const auto & elem_id : closest_elems)
205  {
206  const Elem * elem = _mesh.elemPtr(elem_id);
207 
208  std::vector<PenetrationInfo *> thisElemInfo;
209  std::vector<const Node *> nodesThatMustBeOnSide;
210  nodesThatMustBeOnSide.push_back(closest_node);
212  thisElemInfo, p_info, &node, elem, nodesThatMustBeOnSide, _check_whether_reasonable);
213  }
214 
215  if (p_info.size() == 1)
216  {
217  if (p_info[0]->_tangential_distance <= _tangential_tolerance)
218  {
219  switchInfo(info, p_info[0]);
220  info_set = true;
221  }
222  }
223  else if (p_info.size() > 1)
224  {
225 
226  // Loop through all pairs of faces, and check for contact on ridge betweeen each face pair
227  std::vector<RidgeData> ridgeDataVec;
228  for (unsigned int i = 0; i + 1 < p_info.size(); ++i)
229  for (unsigned int j = i + 1; j < p_info.size(); ++j)
230  {
231  Point closest_coor;
232  Real tangential_distance(0.0);
233  const Node * closest_node_on_ridge = NULL;
234  unsigned int index = 0;
235  Point closest_coor_ref;
236  bool found_ridge_contact_point = findRidgeContactPoint(closest_coor,
237  tangential_distance,
238  closest_node_on_ridge,
239  index,
240  closest_coor_ref,
241  p_info,
242  i,
243  j);
244  if (found_ridge_contact_point)
245  {
246  RidgeData rpd;
247  rpd._closest_coor = closest_coor;
248  rpd._tangential_distance = tangential_distance;
249  rpd._closest_node = closest_node_on_ridge;
250  rpd._index = index;
251  rpd._closest_coor_ref = closest_coor_ref;
252  ridgeDataVec.push_back(rpd);
253  }
254  }
255 
256  if (ridgeDataVec.size() > 0) // Either find the ridge pair that is the best or find a peak
257  {
258  // Group together ridges for which we are off the edge of a common node.
259  // Those are peaks.
260  std::vector<RidgeSetData> ridgeSetDataVec;
261  for (unsigned int i = 0; i < ridgeDataVec.size(); ++i)
262  {
263  bool foundSetWithMatchingNode = false;
264  for (unsigned int j = 0; j < ridgeSetDataVec.size(); ++j)
265  {
266  if (ridgeDataVec[i]._closest_node != NULL &&
267  ridgeDataVec[i]._closest_node == ridgeSetDataVec[j]._closest_node)
268  {
269  foundSetWithMatchingNode = true;
270  ridgeSetDataVec[j]._ridge_data_vec.push_back(ridgeDataVec[i]);
271  break;
272  }
273  }
274  if (!foundSetWithMatchingNode)
275  {
276  RidgeSetData rsd;
277  rsd._distance = std::numeric_limits<Real>::max();
278  rsd._ridge_data_vec.push_back(ridgeDataVec[i]);
279  rsd._closest_node = ridgeDataVec[i]._closest_node;
280  ridgeSetDataVec.push_back(rsd);
281  }
282  }
283  // Compute distance to each set of ridges
284  for (unsigned int i = 0; i < ridgeSetDataVec.size(); ++i)
285  {
286  if (ridgeSetDataVec[i]._closest_node !=
287  NULL) // Either a peak or off the edge of single ridge
288  {
289  if (ridgeSetDataVec[i]._ridge_data_vec.size() == 1) // off edge of single ridge
290  {
291  if (ridgeSetDataVec[i]._ridge_data_vec[0]._tangential_distance <=
292  _tangential_tolerance) // off within tolerance
293  {
294  ridgeSetDataVec[i]._closest_coor =
295  ridgeSetDataVec[i]._ridge_data_vec[0]._closest_coor;
296  Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
297  ridgeSetDataVec[i]._distance = contact_point_vec.norm();
298  }
299  }
300  else // several ridges join at common node to make peak. The common node is the
301  // contact point
302  {
303  ridgeSetDataVec[i]._closest_coor = *ridgeSetDataVec[i]._closest_node;
304  Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
305  ridgeSetDataVec[i]._distance = contact_point_vec.norm();
306  }
307  }
308  else // on a single ridge
309  {
310  ridgeSetDataVec[i]._closest_coor =
311  ridgeSetDataVec[i]._ridge_data_vec[0]._closest_coor;
312  Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
313  ridgeSetDataVec[i]._distance = contact_point_vec.norm();
314  }
315  }
316  // Find the set of ridges closest to us.
317  unsigned int closest_ridge_set_index(0);
318  Real closest_distance(ridgeSetDataVec[0]._distance);
319  Point closest_point(ridgeSetDataVec[0]._closest_coor);
320  for (unsigned int i = 1; i < ridgeSetDataVec.size(); ++i)
321  {
322  if (ridgeSetDataVec[i]._distance < closest_distance)
323  {
324  closest_ridge_set_index = i;
325  closest_distance = ridgeSetDataVec[i]._distance;
326  closest_point = ridgeSetDataVec[i]._closest_coor;
327  }
328  }
329 
330  if (closest_distance <
331  std::numeric_limits<Real>::max()) // contact point is on the closest ridge set
332  {
333  // find the face in the ridge set with the smallest index, assign that one to the
334  // interaction
335  unsigned int face_index(std::numeric_limits<unsigned int>::max());
336  for (unsigned int i = 0;
337  i < ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec.size();
338  ++i)
339  {
340  if (ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[i]._index < face_index)
341  face_index = ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[i]._index;
342  }
343 
344  mooseAssert(face_index < std::numeric_limits<unsigned int>::max(),
345  "face_index invalid");
346 
347  p_info[face_index]->_closest_point = closest_point;
348  p_info[face_index]->_distance =
349  (p_info[face_index]->_distance >= 0.0 ? 1.0 : -1.0) * closest_distance;
350  // Calculate the normal as the vector from the ridge to the point only if we're not
351  // doing normal
352  // smoothing. Normal smoothing will average out the normals on its own.
354  {
355  Point normal(closest_point - node);
356  const Real len(normal.norm());
357  if (len > 0)
358  {
359  normal /= len;
360  }
361  const Real dot(normal * p_info[face_index]->_normal);
362  if (dot < 0)
363  {
364  normal *= -1;
365  }
366  p_info[face_index]->_normal = normal;
367  }
368  p_info[face_index]->_tangential_distance = 0.0;
369 
370  Point closest_point_ref;
371  if (ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec.size() ==
372  1) // contact with a single ridge rather than a peak
373  {
374  p_info[face_index]->_tangential_distance =
375  ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[0]._tangential_distance;
376  p_info[face_index]->_closest_point_ref =
377  ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[0]._closest_coor_ref;
378  }
379  else
380  { // peak
381  const Node * closest_node_on_face;
382  bool restricted = restrictPointToFace(p_info[face_index]->_closest_point_ref,
383  closest_node_on_face,
384  p_info[face_index]->_side);
385  if (restricted)
386  {
387  if (closest_node_on_face != ridgeSetDataVec[closest_ridge_set_index]._closest_node)
388  {
389  mooseError("Closest node when restricting point to face != closest node from "
390  "RidgeSetData");
391  }
392  }
393  }
394 
395  FEBase * fe = _fes[_tid][p_info[face_index]->_side->dim()];
396  std::vector<Point> points(1);
397  points[0] = p_info[face_index]->_closest_point_ref;
398  fe->reinit(p_info[face_index]->_side, &points);
399  p_info[face_index]->_side_phi = fe->get_phi();
400  p_info[face_index]->_side_grad_phi = fe->get_dphi();
401  p_info[face_index]->_dxyzdxi = fe->get_dxyzdxi();
402  p_info[face_index]->_dxyzdeta = fe->get_dxyzdeta();
403  p_info[face_index]->_d2xyzdxideta = fe->get_d2xyzdxideta();
404 
405  switchInfo(info, p_info[face_index]);
406  info_set = true;
407  }
408  else
409  { // todo:remove invalid ridge cases so they don't mess up individual face competition????
410  }
411  }
412 
413  if (!info_set) // contact wasn't on a ridge -- compete individual interactions
414  {
415  unsigned int best(0), i(1);
416  do
417  {
418  CompeteInteractionResult CIResult = competeInteractions(p_info[best], p_info[i]);
419  if (CIResult == FIRST_WINS)
420  {
421  i++;
422  }
423  else if (CIResult == SECOND_WINS)
424  {
425  best = i;
426  i++;
427  }
428  else if (CIResult == NEITHER_WINS)
429  {
430  best = i + 1;
431  i += 2;
432  }
433  } while (i < p_info.size() && best < p_info.size());
434  if (best < p_info.size())
435  {
436  switchInfo(info, p_info[best]);
437  info_set = true;
438  }
439  }
440  }
441  }
442 
443  if (!info_set)
444  {
445  delete info;
446  info = NULL;
447  }
448  else
449  {
450  smoothNormal(info, p_info);
451  FEBase * fe = _fes[_tid][info->_side->dim()];
452  computeSlip(*fe, *info);
453  }
454 
455  for (unsigned int j = 0; j < p_info.size(); ++j)
456  {
457  if (p_info[j])
458  {
459  delete p_info[j];
460  p_info[j] = NULL;
461  }
462  }
463  }
464 }
MooseVariable * _nodal_normal_z
FEGenericBase< Real > FEBase
Definition: Assembly.h:34
virtual Elem * elemPtr(const dof_id_type i)
Definition: MooseMesh.C:2062
virtual MooseVariable & getVariable(THREAD_ID tid, const std::string &var_name)=0
Returns the variable reference for requested variable which may be in any system. ...
void smoothNormal(PenetrationInfo *info, std::vector< PenetrationInfo * > &p_info)
Data structure used to hold penetration information.
NearestNodeLocator & _nearest_node
void mooseError(Args &&...args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:182
bool isCaptured() const
bool restrictPointToFace(Point &p, const Node *&closest_node, const Elem *side)
void findContactPoint(PenetrationInfo &p_info, FEBase *fe_elem, FEBase *fe_side, FEType &fe_side_type, const Point &slave_point, bool start_with_centroid, const Real tangential_tolerance, bool &contact_point_on_side)
Finds the closest point (called the contact point) on the master_elem on side "side" to the slave_poi...
Threads::spin_mutex pinfo_mutex
SubProblem & _subproblem
const MooseMesh & _mesh
std::vector< std::vector< FEBase * > > & _fes
const Elem * _elem
CompeteInteractionResult competeInteractions(PenetrationInfo *pi1, PenetrationInfo *pi2)
bool findRidgeContactPoint(Point &contact_point, Real &tangential_distance, const Node *&closest_node, unsigned int &index, Point &contact_point_ref, std::vector< PenetrationInfo * > &p_info, const unsigned int index1, const unsigned int index2)
const Elem * _side
std::vector< const Node * > _off_edge_nodes
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...
MooseVariable * _nodal_normal_y
void createInfoForElem(std::vector< PenetrationInfo * > &thisElemInfo, std::vector< PenetrationInfo * > &p_info, const Node *slave_node, const Elem *elem, const std::vector< const Node * > &nodes_that_must_be_on_side, const bool check_whether_reasonable=false)
virtual const Node & nodeRef(const dof_id_type i) const
Definition: MooseMesh.C:398
void computeSlip(FEBase &fe, PenetrationInfo &info)
const std::map< dof_id_type, std::vector< dof_id_type > > & _node_to_elem_map
void switchInfo(PenetrationInfo *&info, PenetrationInfo *&infoNew)
MooseVariable * _nodal_normal_x
PenetrationLocator::NORMAL_SMOOTHING_METHOD _normal_smoothing_method
bool PenetrationThread::restrictPointToFace ( Point &  p,
const Node *&  closest_node,
const Elem *  side 
)
protected

Definition at line 995 of file PenetrationThread.C.

Referenced by operator()().

996 {
997  const ElemType t(side->type());
998  Real & xi = p(0);
999  Real & eta = p(1);
1000  closest_node = NULL;
1001 
1002  bool off_of_this_face(false);
1003 
1004  switch (t)
1005  {
1006  case EDGE2:
1007  case EDGE3:
1008  case EDGE4:
1009  {
1010  if (xi < -1.0)
1011  {
1012  xi = -1.0;
1013  off_of_this_face = true;
1014  closest_node = side->node_ptr(0);
1015  }
1016  else if (xi > 1.0)
1017  {
1018  xi = 1.0;
1019  off_of_this_face = true;
1020  closest_node = side->node_ptr(1);
1021  }
1022  break;
1023  }
1024 
1025  case TRI3:
1026  case TRI6:
1027  {
1028  if (eta < 0.0)
1029  {
1030  eta = 0.0;
1031  off_of_this_face = true;
1032  if (xi < 0.5)
1033  {
1034  closest_node = side->node_ptr(0);
1035  if (xi < 0.0)
1036  xi = 0.0;
1037  }
1038  else
1039  {
1040  closest_node = side->node_ptr(1);
1041  if (xi > 1.0)
1042  xi = 1.0;
1043  }
1044  }
1045  else if ((xi + eta) > 1.0)
1046  {
1047  Real delta = (xi + eta - 1.0) / 2.0;
1048  xi -= delta;
1049  eta -= delta;
1050  off_of_this_face = true;
1051  if (xi > 0.5)
1052  {
1053  closest_node = side->node_ptr(1);
1054  if (xi > 1.0)
1055  {
1056  xi = 1.0;
1057  eta = 0.0;
1058  }
1059  }
1060  else
1061  {
1062  closest_node = side->node_ptr(2);
1063  if (xi < 0.0)
1064  {
1065  xi = 0.0;
1066  eta = 1.0;
1067  }
1068  }
1069  }
1070  else if (xi < 0.0)
1071  {
1072  xi = 0.0;
1073  off_of_this_face = true;
1074  if (eta > 0.5)
1075  {
1076  closest_node = side->node_ptr(2);
1077  if (eta > 1.0)
1078  eta = 1.0;
1079  }
1080  else
1081  {
1082  closest_node = side->node_ptr(0);
1083  if (eta < 0.0)
1084  eta = 0.0;
1085  }
1086  }
1087  break;
1088  }
1089 
1090  case QUAD4:
1091  case QUAD8:
1092  case QUAD9:
1093  {
1094  if (eta < -1.0)
1095  {
1096  eta = -1.0;
1097  off_of_this_face = true;
1098  if (xi < 0.0)
1099  {
1100  closest_node = side->node_ptr(0);
1101  if (xi < -1.0)
1102  xi = -1.0;
1103  }
1104  else
1105  {
1106  closest_node = side->node_ptr(1);
1107  if (xi > 1.0)
1108  xi = 1.0;
1109  }
1110  }
1111  else if (xi > 1.0)
1112  {
1113  xi = 1.0;
1114  off_of_this_face = true;
1115  if (eta < 0.0)
1116  {
1117  closest_node = side->node_ptr(1);
1118  if (eta < -1.0)
1119  eta = -1.0;
1120  }
1121  else
1122  {
1123  closest_node = side->node_ptr(2);
1124  if (eta > 1.0)
1125  eta = 1.0;
1126  }
1127  }
1128  else if (eta > 1.0)
1129  {
1130  eta = 1.0;
1131  off_of_this_face = true;
1132  if (xi < 0.0)
1133  {
1134  closest_node = side->node_ptr(3);
1135  if (xi < -1.0)
1136  xi = -1.0;
1137  }
1138  else
1139  {
1140  closest_node = side->node_ptr(2);
1141  if (xi > 1.0)
1142  xi = 1.0;
1143  }
1144  }
1145  else if (xi < -1.0)
1146  {
1147  xi = -1.0;
1148  off_of_this_face = true;
1149  if (eta < 0.0)
1150  {
1151  closest_node = side->node_ptr(0);
1152  if (eta < -1.0)
1153  eta = -1.0;
1154  }
1155  else
1156  {
1157  closest_node = side->node_ptr(3);
1158  if (eta > 1.0)
1159  eta = 1.0;
1160  }
1161  }
1162  break;
1163  }
1164 
1165  default:
1166  {
1167  mooseError("Unsupported face type: ", t);
1168  break;
1169  }
1170  }
1171  return off_of_this_face;
1172 }
void mooseError(Args &&...args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:182
bool PenetrationThread::restrictPointToSpecifiedEdgeOfFace ( Point &  p,
const Node *&  closest_node,
const Elem *  side,
const std::vector< const Node * > &  edge_nodes 
)
protected

Definition at line 822 of file PenetrationThread.C.

Referenced by findRidgeContactPoint().

826 {
827  const ElemType t = side->type();
828  Real & xi = p(0);
829  Real & eta = p(1);
830  closest_node = NULL;
831 
832  std::vector<unsigned int> local_node_indices;
833  for (const auto & edge_node : edge_nodes)
834  {
835  unsigned int local_index = side->get_node_index(edge_node);
836  if (local_index == libMesh::invalid_uint)
837  mooseError("Side does not contain node");
838  local_node_indices.push_back(local_index);
839  }
840  mooseAssert(local_node_indices.size() == side->dim(),
841  "Number of edge nodes must match side dimensionality");
842  std::sort(local_node_indices.begin(), local_node_indices.end());
843 
844  bool off_of_this_edge = false;
845 
846  switch (t)
847  {
848  case EDGE2:
849  case EDGE3:
850  case EDGE4:
851  {
852  if (local_node_indices[0] == 0)
853  {
854  if (xi <= -1.0)
855  {
856  xi = -1.0;
857  off_of_this_edge = true;
858  closest_node = side->node_ptr(0);
859  }
860  }
861  else if (local_node_indices[0] == 1)
862  {
863  if (xi >= 1.0)
864  {
865  xi = 1.0;
866  off_of_this_edge = true;
867  closest_node = side->node_ptr(1);
868  }
869  }
870  else
871  {
872  mooseError("Invalid local node indices");
873  }
874  break;
875  }
876 
877  case TRI3:
878  case TRI6:
879  {
880  if ((local_node_indices[0] == 0) && (local_node_indices[1] == 1))
881  {
882  if (eta <= 0.0)
883  {
884  eta = 0.0;
885  off_of_this_edge = true;
886  if (xi < 0.0)
887  closest_node = side->node_ptr(0);
888  else if (xi > 1.0)
889  closest_node = side->node_ptr(1);
890  }
891  }
892  else if ((local_node_indices[0] == 1) && (local_node_indices[1] == 2))
893  {
894  if ((xi + eta) > 1.0)
895  {
896  Real delta = (xi + eta - 1.0) / 2.0;
897  xi -= delta;
898  eta -= delta;
899  off_of_this_edge = true;
900  if (xi > 1.0)
901  closest_node = side->node_ptr(1);
902  else if (xi < 0.0)
903  closest_node = side->node_ptr(2);
904  }
905  }
906  else if ((local_node_indices[0] == 0) && (local_node_indices[1] == 2))
907  {
908  if (xi <= 0.0)
909  {
910  xi = 0.0;
911  off_of_this_edge = true;
912  if (eta > 1.0)
913  closest_node = side->node_ptr(2);
914  else if (eta < 0.0)
915  closest_node = side->node_ptr(0);
916  }
917  }
918  else
919  {
920  mooseError("Invalid local node indices");
921  }
922 
923  break;
924  }
925 
926  case QUAD4:
927  case QUAD8:
928  case QUAD9:
929  {
930  if ((local_node_indices[0] == 0) && (local_node_indices[1] == 1))
931  {
932  if (eta <= -1.0)
933  {
934  eta = -1.0;
935  off_of_this_edge = true;
936  if (xi < -1.0)
937  closest_node = side->node_ptr(0);
938  else if (xi > 1.0)
939  closest_node = side->node_ptr(1);
940  }
941  }
942  else if ((local_node_indices[0] == 1) && (local_node_indices[1] == 2))
943  {
944  if (xi >= 1.0)
945  {
946  xi = 1.0;
947  off_of_this_edge = true;
948  if (eta < -1.0)
949  closest_node = side->node_ptr(1);
950  else if (eta > 1.0)
951  closest_node = side->node_ptr(2);
952  }
953  }
954  else if ((local_node_indices[0] == 2) && (local_node_indices[1] == 3))
955  {
956  if (eta >= 1.0)
957  {
958  eta = 1.0;
959  off_of_this_edge = true;
960  if (xi < -1.0)
961  closest_node = side->node_ptr(3);
962  else if (xi > 1.0)
963  closest_node = side->node_ptr(2);
964  }
965  }
966  else if ((local_node_indices[0] == 0) && (local_node_indices[1] == 3))
967  {
968  if (xi <= -1.0)
969  {
970  xi = -1.0;
971  off_of_this_edge = true;
972  if (eta < -1.0)
973  closest_node = side->node_ptr(0);
974  else if (eta > 1.0)
975  closest_node = side->node_ptr(3);
976  }
977  }
978  else
979  {
980  mooseError("Invalid local node indices");
981  }
982  break;
983  }
984 
985  default:
986  {
987  mooseError("Unsupported face type: ", t);
988  break;
989  }
990  }
991  return off_of_this_edge;
992 }
void mooseError(Args &&...args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:182
void PenetrationThread::smoothNormal ( PenetrationInfo info,
std::vector< PenetrationInfo * > &  p_info 
)
protected

Definition at line 1254 of file PenetrationThread.C.

Referenced by operator()().

1255 {
1257  {
1259  {
1260  // If we are within the smoothing distance of any edges or corners, find the
1261  // corner nodes for those edges/corners, and weights from distance to edge/corner
1262  std::vector<Real> edge_face_weights;
1263  std::vector<PenetrationInfo *> edge_face_info;
1264 
1265  getSmoothingFacesAndWeights(info, edge_face_info, edge_face_weights, p_info);
1266 
1267  mooseAssert(edge_face_info.size() == edge_face_weights.size(),
1268  "edge_face_info.size() != edge_face_weights.size()");
1269 
1270  if (edge_face_info.size() > 0)
1271  {
1272  // Smooth the normal using the weighting functions for all participating faces.
1273  RealVectorValue new_normal;
1274  Real this_face_weight = 1.0;
1275 
1276  for (unsigned int efwi = 0; efwi < edge_face_weights.size(); ++efwi)
1277  {
1278  PenetrationInfo * npi = edge_face_info[efwi];
1279  if (npi)
1280  new_normal += npi->_normal * edge_face_weights[efwi];
1281 
1282  this_face_weight -= edge_face_weights[efwi];
1283  }
1284  mooseAssert(this_face_weight >= (0.25 - 1e-8),
1285  "Sum of weights of other faces shouldn't exceed 0.75");
1286  new_normal += info->_normal * this_face_weight;
1287 
1288  const Real len = new_normal.norm();
1289  if (len > 0)
1290  new_normal /= len;
1291 
1292  info->_normal = new_normal;
1293  }
1294  }
1296  {
1297  // params.addParam<VariableName>("var_name","description");
1298  // getParam<VariableName>("var_name")
1299  info->_normal(0) = _nodal_normal_x->getValue(info->_side, info->_side_phi);
1300  info->_normal(1) = _nodal_normal_y->getValue(info->_side, info->_side_phi);
1301  info->_normal(2) = _nodal_normal_z->getValue(info->_side, info->_side_phi);
1302  const Real len(info->_normal.norm());
1303  if (len > 0)
1304  info->_normal /= len;
1305  }
1306  }
1307 }
MooseVariable * _nodal_normal_z
VectorValue< Real > RealVectorValue
Definition: Assembly.h:40
RealVectorValue _normal
Data structure used to hold penetration information.
std::vector< std::vector< Real > > _side_phi
const Elem * _side
Real getValue(const Elem *elem, const std::vector< std::vector< Real >> &phi) const
Compute the variable value at a point on an element.
MooseVariable * _nodal_normal_y
MooseVariable * _nodal_normal_x
void getSmoothingFacesAndWeights(PenetrationInfo *info, std::vector< PenetrationInfo * > &edge_face_info, std::vector< Real > &edge_face_weights, std::vector< PenetrationInfo * > &p_info)
PenetrationLocator::NORMAL_SMOOTHING_METHOD _normal_smoothing_method
void PenetrationThread::switchInfo ( PenetrationInfo *&  info,
PenetrationInfo *&  infoNew 
)
protected

Definition at line 472 of file PenetrationThread.C.

Referenced by operator()().

473 {
474  mooseAssert(infoNew != NULL, "infoNew object is null");
475  if (info)
476  {
477  infoNew->_starting_elem = info->_starting_elem;
478  infoNew->_starting_side_num = info->_starting_side_num;
480  infoNew->_incremental_slip = info->_incremental_slip;
481  infoNew->_accumulated_slip = info->_accumulated_slip;
483  infoNew->_frictional_energy = info->_frictional_energy;
485  infoNew->_contact_force = info->_contact_force;
486  infoNew->_contact_force_old = info->_contact_force_old;
489  infoNew->_locked_this_step = info->_locked_this_step;
491  infoNew->_mech_status = info->_mech_status;
492  infoNew->_mech_status_old = info->_mech_status_old;
493  }
494  else
495  {
496  infoNew->_starting_elem = infoNew->_elem;
497  infoNew->_starting_side_num = infoNew->_side_num;
499  }
500  delete info;
501  info = infoNew;
502  infoNew = NULL; // Set this to NULL so that we don't delete it (now owned by _penetration_info).
503 }
const Elem * _starting_elem
unsigned int _stick_locked_this_step
RealVectorValue _contact_force_old
unsigned int _locked_this_step
const Elem * _elem
unsigned int _starting_side_num
unsigned int _side_num
RealVectorValue _contact_force
MECH_STATUS_ENUM _mech_status
Point _starting_closest_point_ref
MECH_STATUS_ENUM _mech_status_old
RealVectorValue _lagrange_multiplier_slip

Member Data Documentation

bool PenetrationThread::_check_whether_reasonable
protected

Definition at line 64 of file PenetrationThread.h.

Referenced by operator()().

bool PenetrationThread::_do_normal_smoothing
protected

Definition at line 67 of file PenetrationThread.h.

Referenced by operator()(), and smoothNormal().

std::vector<dof_id_type>& PenetrationThread::_elem_list
protected

Definition at line 82 of file PenetrationThread.h.

Referenced by getSidesOnMasterBoundary().

FEType& PenetrationThread::_fe_type
protected

Definition at line 76 of file PenetrationThread.h.

Referenced by createInfoForElem(), and operator()().

std::vector<std::vector<FEBase *> >& PenetrationThread::_fes
protected

Definition at line 74 of file PenetrationThread.h.

Referenced by createInfoForElem(), findRidgeContactPoint(), and operator()().

std::vector<boundary_id_type>& PenetrationThread::_id_list
protected

Definition at line 84 of file PenetrationThread.h.

Referenced by getSidesOnMasterBoundary().

BoundaryID PenetrationThread::_master_boundary
protected

Definition at line 58 of file PenetrationThread.h.

Referenced by getSidesOnMasterBoundary().

const MooseMesh& PenetrationThread::_mesh
protected

Definition at line 57 of file PenetrationThread.h.

Referenced by getInfoForFacesWithCommonNodes(), and operator()().

unsigned int PenetrationThread::_n_elems
protected

Definition at line 86 of file PenetrationThread.h.

Referenced by getSidesOnMasterBoundary().

NearestNodeLocator& PenetrationThread::_nearest_node
protected

Definition at line 78 of file PenetrationThread.h.

Referenced by operator()().

MooseVariable* PenetrationThread::_nodal_normal_x
protected

Definition at line 70 of file PenetrationThread.h.

Referenced by operator()(), and smoothNormal().

MooseVariable* PenetrationThread::_nodal_normal_y
protected

Definition at line 71 of file PenetrationThread.h.

Referenced by operator()(), and smoothNormal().

MooseVariable* PenetrationThread::_nodal_normal_z
protected

Definition at line 72 of file PenetrationThread.h.

Referenced by operator()(), and smoothNormal().

const std::map<dof_id_type, std::vector<dof_id_type> >& PenetrationThread::_node_to_elem_map
protected

Definition at line 80 of file PenetrationThread.h.

Referenced by getInfoForFacesWithCommonNodes(), and operator()().

Real PenetrationThread::_normal_smoothing_distance
protected

Definition at line 68 of file PenetrationThread.h.

Referenced by getSmoothingEdgeNodesAndWeights().

PenetrationLocator::NORMAL_SMOOTHING_METHOD PenetrationThread::_normal_smoothing_method
protected

Definition at line 69 of file PenetrationThread.h.

Referenced by operator()(), and smoothNormal().

std::map<dof_id_type, PenetrationInfo *>& PenetrationThread::_penetration_info
protected

Definition at line 62 of file PenetrationThread.h.

Referenced by operator()().

std::vector<unsigned short int>& PenetrationThread::_side_list
protected

Definition at line 83 of file PenetrationThread.h.

Referenced by getSidesOnMasterBoundary().

BoundaryID PenetrationThread::_slave_boundary
protected

Definition at line 59 of file PenetrationThread.h.

SubProblem& PenetrationThread::_subproblem
protected

Definition at line 55 of file PenetrationThread.h.

Referenced by operator()().

Real PenetrationThread::_tangential_tolerance
protected

Definition at line 66 of file PenetrationThread.h.

Referenced by competeInteractions(), createInfoForElem(), and operator()().

THREAD_ID PenetrationThread::_tid
protected

Definition at line 88 of file PenetrationThread.h.

Referenced by createInfoForElem(), findRidgeContactPoint(), and operator()().

bool PenetrationThread::_update_location
protected

Definition at line 65 of file PenetrationThread.h.

Referenced by operator()().


The documentation for this class was generated from the following files: