56 bool start_with_centroid,
57 const Real tangential_tolerance,
58 bool & contact_point_on_side,
59 bool & search_succeeded)
62 search_succeeded =
true;
64 const Elem * primary_elem = p_info.
_elem;
66 unsigned int dim = primary_elem->dim();
68 const Elem * side = p_info.
_side;
70 const std::vector<libMesh::Point> & phys_point = fe_side->get_xyz();
72 const std::vector<RealGradient> & dxyz_dxi = fe_side->get_dxyzdxi();
73 const std::vector<RealGradient> & d2xyz_dxi2 = fe_side->get_d2xyzdxi2();
74 const std::vector<RealGradient> & d2xyz_dxieta = fe_side->get_d2xyzdxideta();
76 const std::vector<RealGradient> & dxyz_deta = fe_side->get_dxyzdeta();
77 const std::vector<RealGradient> & d2xyz_deta2 = fe_side->get_d2xyzdeta2();
78 const std::vector<RealGradient> & d2xyz_detaxi = fe_side->get_d2xyzdxideta();
82 const Node * nearest_node = side->node_ptr(0);
85 primary_elem->master_point(primary_elem->get_node_index(nearest_node));
88 const std::vector<RealGradient> & elem_dxyz_dxi = fe_elem->get_dxyzdxi();
90 fe_elem->reinit(primary_elem, &elem_points);
91 fe_side->reinit(side, &elem_points);
93 p_info.
_normal = elem_dxyz_dxi[0];
94 if (nearest_node->id() == primary_elem->node_id(0))
107 contact_point_on_side =
true;
113 if (start_with_centroid)
114 ref_point = FEMap::inverse_map(
dim - 1, side, side->vertex_average(), TOLERANCE,
false);
118 std::vector<libMesh::Point> points = {ref_point};
119 fe_side->reinit(side, &points);
120 RealGradient d = secondary_point - phys_point[0];
122 Real update_size = std::numeric_limits<Real>::max();
125 for (
unsigned int it = 0; it < 3 && update_size > TOLERANCE * 1e3; ++it)
127 DenseMatrix<Real> jac(
dim - 1,
dim - 1);
128 jac(0, 0) = -(dxyz_dxi[0] * dxyz_dxi[0]);
132 jac(1, 0) = -(dxyz_dxi[0] * dxyz_deta[0]);
133 jac(0, 1) = -(dxyz_deta[0] * dxyz_dxi[0]);
134 jac(1, 1) = -(dxyz_deta[0] * dxyz_deta[0]);
137 DenseVector<Real> rhs(
dim - 1);
138 rhs(0) = dxyz_dxi[0] * d;
141 rhs(1) = dxyz_deta[0] * d;
143 DenseVector<Real> update(
dim - 1);
144 jac.lu_solve(rhs, update);
146 ref_point(0) -= update(0);
149 ref_point(1) -= update(1);
151 points[0] = ref_point;
152 fe_side->reinit(side, &points);
153 d = secondary_point - phys_point[0];
155 update_size = update.l2_norm();
158 update_size = std::numeric_limits<Real>::max();
163 const auto max_newton_its = 25;
164 const auto tolerance_newton = 1e3 * TOLERANCE * TOLERANCE;
165 for (; nit < max_newton_its && update_size > tolerance_newton; nit++)
167 d = secondary_point - phys_point[0];
169 DenseMatrix<Real> jac(
dim - 1,
dim - 1);
170 jac(0, 0) = (d2xyz_dxi2[0] * d) - (dxyz_dxi[0] * dxyz_dxi[0]);
174 jac(1, 0) = (d2xyz_dxieta[0] * d) - (dxyz_dxi[0] * dxyz_deta[0]);
176 jac(0, 1) = (d2xyz_detaxi[0] * d) - (dxyz_deta[0] * dxyz_dxi[0]);
177 jac(1, 1) = (d2xyz_deta2[0] * d) - (dxyz_deta[0] * dxyz_deta[0]);
180 DenseVector<Real> rhs(
dim - 1);
181 rhs(0) = -dxyz_dxi[0] * d;
184 rhs(1) = -dxyz_deta[0] * d;
186 DenseVector<Real> update(
dim - 1);
187 jac.lu_solve(rhs, update);
196 ref_point(0) += mult * update(0);
199 ref_point(1) += mult * update(1);
201 points[0] = ref_point;
202 fe_side->reinit(side, &points);
203 d = secondary_point - phys_point[0];
206 update_size = update.l2_norm();
210 catch (std::exception & e)
213 if (!strstr(e.what(),
"Jacobian") && !strstr(e.what(),
"det != 0"))
216 ref_point(0) -= mult * update(0);
218 ref_point(1) -= mult * update(1);
224 mooseWarning(
"We could not solve for the contact point.", e.what());
226 update_size = update.l2_norm();
227 d = (secondary_point - phys_point[0]) * mult;
235 nit = max_newton_its;
241 if (nit == max_newton_its && update_size > tolerance_newton)
243 search_succeeded =
false;
245 const auto initial_point =
247 Moose::err <<
"Warning! Newton solve for contact point failed to converge!\nLast update "
249 << update_size <<
"\nInitial point guess: " << initial_point
250 <<
"\nLast considered point: " << phys_point[0]
251 <<
"\nThis potential contact pair (face, point) will be discarded." << std::endl;
262 p_info.
_normal = dxyz_dxi[0].cross(dxyz_deta[0]);
263 if (!MooseUtils::absoluteFuzzyEqual(p_info.
_normal.norm(), 0))
268 const Node *
const * elem_nodes = primary_elem->get_nodes();
269 const libMesh::Point in_plane_vector1 = *elem_nodes[1] - *elem_nodes[0];
270 const libMesh::Point in_plane_vector2 = *elem_nodes[2] - *elem_nodes[0];
273 out_of_plane_normal /= out_of_plane_normal.
norm();
275 p_info.
_normal = dxyz_dxi[0].cross(out_of_plane_normal);
276 if (std::fabs(p_info.
_normal.norm()) > 1e-15)
281 const Real dot(d * p_info.
_normal);
285 contact_point_on_side = side->on_reference_element(ref_point);
289 if (!contact_point_on_side)
295 fe_side->reinit(side, &points);
298 RealGradient off_face = closest_point_on_face - p_info.
_closest_point;
299 Real tangential_distance = off_face.norm();
301 if (tangential_distance <= tangential_tolerance)
303 contact_point_on_side =
true;
307 const std::vector<std::vector<Real>> & phi = fe_side->get_phi();
308 const std::vector<std::vector<RealGradient>> & grad_phi = fe_side->get_dphi();
311 fe_side->reinit(side, &points);
323 std::vector<const Node *> & off_edge_nodes)
325 const ElemType t(side->type());
326 off_edge_nodes.clear();
340 off_edge_nodes.push_back(side->node_ptr(0));
345 off_edge_nodes.push_back(side->node_ptr(1));
357 if (
xi <= 0.0 &&
eta <= 0.0)
361 off_edge_nodes.push_back(side->node_ptr(0));
363 else if (
xi > 0.0 &&
xi < 1.0 &&
eta < 0.0)
366 off_edge_nodes.push_back(side->node_ptr(0));
367 off_edge_nodes.push_back(side->node_ptr(1));
369 else if (
eta > 0.0 &&
eta < 1.0 &&
xi < 0.0)
372 off_edge_nodes.push_back(side->node_ptr(2));
373 off_edge_nodes.push_back(side->node_ptr(0));
375 else if (
xi >= 1.0 && (
eta -
xi) <= -1.0)
379 off_edge_nodes.push_back(side->node_ptr(1));
381 else if (
eta >= 1.0 && (
eta -
xi) >= 1.0)
385 off_edge_nodes.push_back(side->node_ptr(2));
387 else if ((
xi +
eta) > 1.0)
389 Real delta = (
xi +
eta - 1.0) / 2.0;
392 off_edge_nodes.push_back(side->node_ptr(1));
393 off_edge_nodes.push_back(side->node_ptr(2));
409 off_edge_nodes.push_back(side->node_ptr(0));
414 off_edge_nodes.push_back(side->node_ptr(3));
418 off_edge_nodes.push_back(side->node_ptr(3));
419 off_edge_nodes.push_back(side->node_ptr(0));
428 off_edge_nodes.push_back(side->node_ptr(1));
433 off_edge_nodes.push_back(side->node_ptr(2));
437 off_edge_nodes.push_back(side->node_ptr(1));
438 off_edge_nodes.push_back(side->node_ptr(2));
446 off_edge_nodes.push_back(side->node_ptr(0));
447 off_edge_nodes.push_back(side->node_ptr(1));
452 off_edge_nodes.push_back(side->node_ptr(2));
453 off_edge_nodes.push_back(side->node_ptr(3));