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);
124 Real update_size = std::numeric_limits<Real>::max();
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();
160 update_size = std::numeric_limits<Real>::max();
165 const auto max_newton_its = 25;
166 const auto tolerance_newton = 1e3 * TOLERANCE * TOLERANCE;
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)
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));
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...