17 #include "libmesh/fe_base.h" 18 #include "libmesh/boundary_info.h" 19 #include "libmesh/elem.h" 20 #include "libmesh/plane.h" 21 #include "libmesh/fe_interface.h" 22 #include "libmesh/dense_vector.h" 23 #include "libmesh/fe_base.h" 24 #include "libmesh/vector_value.h" 58 bool start_with_centroid,
59 const Real tangential_tolerance,
60 bool & contact_point_on_side,
61 bool & search_succeeded)
64 search_succeeded =
true;
68 unsigned int dim = primary_elem->
dim();
72 const std::vector<libMesh::Point> & phys_point = fe_side->
get_xyz();
74 const std::vector<RealGradient> & dxyz_dxi = fe_side->
get_dxyzdxi();
75 const std::vector<RealGradient> & d2xyz_dxi2 = fe_side->
get_d2xyzdxi2();
76 const std::vector<RealGradient> & d2xyz_dxieta = fe_side->
get_d2xyzdxideta();
78 const std::vector<RealGradient> & dxyz_deta = fe_side->
get_dxyzdeta();
79 const std::vector<RealGradient> & d2xyz_deta2 = fe_side->
get_d2xyzdeta2();
80 const std::vector<RealGradient> & d2xyz_detaxi = fe_side->
get_d2xyzdxideta();
90 const std::vector<RealGradient> & elem_dxyz_dxi = fe_elem->
get_dxyzdxi();
92 fe_elem->
reinit(primary_elem, &elem_points);
93 fe_side->
reinit(side, &elem_points);
95 p_info.
_normal = elem_dxyz_dxi[0];
96 if (nearest_node->
id() == primary_elem->
node_id(0))
109 contact_point_on_side =
true;
115 if (start_with_centroid)
120 std::vector<libMesh::Point> points = {ref_point};
121 fe_side->
reinit(side, &points);
127 for (
unsigned int it = 0; it < 3 && update_size >
TOLERANCE * 1e3; ++it)
130 jac(0, 0) = -(dxyz_dxi[0] * dxyz_dxi[0]);
134 jac(1, 0) = -(dxyz_dxi[0] * dxyz_deta[0]);
135 jac(0, 1) = -(dxyz_deta[0] * dxyz_dxi[0]);
136 jac(1, 1) = -(dxyz_deta[0] * dxyz_deta[0]);
140 rhs(0) = dxyz_dxi[0] * d;
143 rhs(1) = dxyz_deta[0] * d;
148 ref_point(0) -= update(0);
151 ref_point(1) -= update(1);
153 points[0] = ref_point;
154 fe_side->
reinit(side, &points);
155 d = secondary_point - phys_point[0];
157 update_size = update.
l2_norm();
165 const auto max_newton_its = 25;
167 for (; nit < max_newton_its && update_size > tolerance_newton; nit++)
169 d = secondary_point - phys_point[0];
172 jac(0, 0) = (d2xyz_dxi2[0] * d) - (dxyz_dxi[0] * dxyz_dxi[0]);
176 jac(1, 0) = (d2xyz_dxieta[0] * d) - (dxyz_dxi[0] * dxyz_deta[0]);
178 jac(0, 1) = (d2xyz_detaxi[0] * d) - (dxyz_deta[0] * dxyz_dxi[0]);
179 jac(1, 1) = (d2xyz_deta2[0] * d) - (dxyz_deta[0] * dxyz_deta[0]);
183 rhs(0) = -dxyz_dxi[0] * d;
186 rhs(1) = -dxyz_deta[0] * d;
198 ref_point(0) += mult * update(0);
201 ref_point(1) += mult * update(1);
203 points[0] = ref_point;
204 fe_side->
reinit(side, &points);
205 d = secondary_point - phys_point[0];
208 update_size = update.l2_norm();
212 catch (std::exception & e)
215 if (!strstr(e.what(),
"Jacobian") && !strstr(e.what(),
"det != 0"))
218 ref_point(0) -= mult * update(0);
220 ref_point(1) -= mult * update(1);
226 mooseWarning(
"We could not solve for the contact point.", e.what());
228 update_size = update.l2_norm();
229 d = (secondary_point - phys_point[0]) * mult;
237 nit = max_newton_its;
243 if (nit == max_newton_its && update_size > tolerance_newton)
245 search_succeeded =
false;
247 const auto initial_point =
249 Moose::err <<
"Warning! Newton solve for contact point failed to converge!\nLast update " 251 << update_size <<
"\nInitial point guess: " << initial_point
252 <<
"\nLast considered point: " << phys_point[0]
253 <<
"\nThis potential contact pair (face, point) will be discarded." << std::endl;
265 if (!MooseUtils::absoluteFuzzyEqual(p_info.
_normal.
norm(), 0))
271 const libMesh::Point in_plane_vector1 = *elem_nodes[1] - *elem_nodes[0];
272 const libMesh::Point in_plane_vector2 = *elem_nodes[2] - *elem_nodes[0];
275 out_of_plane_normal /= out_of_plane_normal.
norm();
277 p_info.
_normal = dxyz_dxi[0].
cross(out_of_plane_normal);
291 if (!contact_point_on_side)
297 fe_side->
reinit(side, &points);
301 Real tangential_distance = off_face.
norm();
303 if (tangential_distance <= tangential_tolerance)
305 contact_point_on_side =
true;
309 const std::vector<std::vector<Real>> & phi = fe_side->
get_phi();
310 const std::vector<std::vector<RealGradient>> & grad_phi = fe_side->
get_dphi();
313 fe_side->
reinit(side, &points);
325 std::vector<const Node *> & off_edge_nodes)
328 off_edge_nodes.clear();
342 off_edge_nodes.push_back(side->
node_ptr(0));
347 off_edge_nodes.push_back(side->
node_ptr(1));
359 if (xi <= 0.0 && eta <= 0.0)
363 off_edge_nodes.push_back(side->
node_ptr(0));
365 else if (xi > 0.0 && xi < 1.0 && eta < 0.0)
368 off_edge_nodes.push_back(side->
node_ptr(0));
369 off_edge_nodes.push_back(side->
node_ptr(1));
371 else if (eta > 0.0 && eta < 1.0 && xi < 0.0)
374 off_edge_nodes.push_back(side->
node_ptr(2));
375 off_edge_nodes.push_back(side->
node_ptr(0));
377 else if (xi >= 1.0 && (eta - xi) <= -1.0)
381 off_edge_nodes.push_back(side->
node_ptr(1));
383 else if (eta >= 1.0 && (eta - xi) >= 1.0)
387 off_edge_nodes.push_back(side->
node_ptr(2));
389 else if ((xi + eta) > 1.0)
391 Real delta = (xi + eta - 1.0) / 2.0;
394 off_edge_nodes.push_back(side->
node_ptr(1));
395 off_edge_nodes.push_back(side->
node_ptr(2));
411 off_edge_nodes.push_back(side->
node_ptr(0));
416 off_edge_nodes.push_back(side->
node_ptr(3));
420 off_edge_nodes.push_back(side->
node_ptr(3));
421 off_edge_nodes.push_back(side->
node_ptr(0));
430 off_edge_nodes.push_back(side->
node_ptr(1));
435 off_edge_nodes.push_back(side->
node_ptr(2));
439 off_edge_nodes.push_back(side->
node_ptr(1));
440 off_edge_nodes.push_back(side->
node_ptr(2));
448 off_edge_nodes.push_back(side->
node_ptr(0));
449 off_edge_nodes.push_back(side->
node_ptr(1));
454 off_edge_nodes.push_back(side->
node_ptr(2));
455 off_edge_nodes.push_back(side->
node_ptr(3));
std::vector< RealGradient > _d2xyzdxideta
unsigned int get_node_index(const Node *node_ptr) const
virtual_for_inffe const std::vector< RealGradient > & get_dxyzdeta() const
virtual_for_inffe const std::vector< RealGradient > & get_d2xyzdxi2() const
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.
static constexpr Real TOLERANCE
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Point _closest_point_on_face_ref
virtual bool on_reference_element(const Point &p, const Real eps=TOLERANCE) const=0
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
virtual_for_inffe const std::vector< RealGradient > & get_d2xyzdxideta() const
std::vector< std::vector< RealGradient > > _side_grad_phi
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
std::vector< std::vector< Real > > _side_phi
virtual_for_inffe const std::vector< RealGradient > & get_d2xyzdeta2() const
auto max(const L &left, const R &right)
const std::vector< std::vector< OutputGradient > > & get_dphi() const
const Node *const * get_nodes() const
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...
virtual_for_inffe const std::vector< Point > & get_xyz() const
std::vector< RealGradient > _dxyzdxi
TypeVector< typename CompareTypes< Real, T2 >::supertype > cross(const TypeVector< T2 > &v) const
std::vector< const Node * > _off_edge_nodes
void restrictPointToFace(libMesh::Point &p, const libMesh::Elem *side, std::vector< const libMesh::Node *> &off_edge_nodes)
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
Real _tangential_distance
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual unsigned short dim() const=0
const Node * node_ptr(const unsigned int i) const
virtual Point master_point(const unsigned int i) const=0
std::vector< RealGradient > _dxyzdeta
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
virtual_for_inffe const std::vector< RealGradient > & get_dxyzdxi() const
virtual ElemType type() const=0
dof_id_type node_id(const unsigned int i) const
Point vertex_average() const
const std::vector< std::vector< OutputShape > > & get_phi() const