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" 55 bool start_with_centroid,
56 const Real tangential_tolerance,
57 bool & contact_point_on_side,
58 bool & search_succeeded)
61 search_succeeded =
true;
65 unsigned int dim = primary_elem->
dim();
69 const std::vector<libMesh::Point> & phys_point = fe_side->
get_xyz();
71 const std::vector<RealGradient> & dxyz_dxi = fe_side->
get_dxyzdxi();
72 const std::vector<RealGradient> & d2xyz_dxi2 = fe_side->
get_d2xyzdxi2();
73 const std::vector<RealGradient> & d2xyz_dxieta = fe_side->
get_d2xyzdxideta();
75 const std::vector<RealGradient> & dxyz_deta = fe_side->
get_dxyzdeta();
76 const std::vector<RealGradient> & d2xyz_deta2 = fe_side->
get_d2xyzdeta2();
77 const std::vector<RealGradient> & d2xyz_detaxi = fe_side->
get_d2xyzdxideta();
87 const std::vector<RealGradient> & elem_dxyz_dxi = fe_elem->
get_dxyzdxi();
89 fe_elem->
reinit(primary_elem, &elem_points);
90 fe_side->
reinit(side, &elem_points);
92 p_info.
_normal = elem_dxyz_dxi[0];
93 if (nearest_node->
id() == primary_elem->
node_id(0))
106 contact_point_on_side =
true;
112 if (start_with_centroid)
117 std::vector<libMesh::Point> points = {ref_point};
118 fe_side->
reinit(side, &points);
124 for (
unsigned int it = 0; it < 3 && update_size >
TOLERANCE * 1e3; ++it)
127 jac(0, 0) = -(dxyz_dxi[0] * dxyz_dxi[0]);
131 jac(1, 0) = -(dxyz_dxi[0] * dxyz_deta[0]);
132 jac(0, 1) = -(dxyz_deta[0] * dxyz_dxi[0]);
133 jac(1, 1) = -(dxyz_deta[0] * dxyz_deta[0]);
137 rhs(0) = dxyz_dxi[0] * d;
140 rhs(1) = dxyz_deta[0] * d;
145 ref_point(0) -= update(0);
148 ref_point(1) -= update(1);
150 points[0] = ref_point;
151 fe_side->
reinit(side, &points);
152 d = secondary_point - phys_point[0];
154 update_size = update.
l2_norm();
162 const auto max_newton_its = 25;
164 for (; nit < max_newton_its && update_size > tolerance_newton; nit++)
166 d = secondary_point - phys_point[0];
169 jac(0, 0) = (d2xyz_dxi2[0] * d) - (dxyz_dxi[0] * dxyz_dxi[0]);
173 jac(1, 0) = (d2xyz_dxieta[0] * d) - (dxyz_dxi[0] * dxyz_deta[0]);
175 jac(0, 1) = (d2xyz_detaxi[0] * d) - (dxyz_deta[0] * dxyz_dxi[0]);
176 jac(1, 1) = (d2xyz_deta2[0] * d) - (dxyz_deta[0] * dxyz_deta[0]);
180 rhs(0) = -dxyz_dxi[0] * d;
183 rhs(1) = -dxyz_deta[0] * d;
195 ref_point(0) += mult * update(0);
198 ref_point(1) += mult * update(1);
200 points[0] = ref_point;
201 fe_side->
reinit(side, &points);
202 d = secondary_point - phys_point[0];
205 update_size = update.l2_norm();
210 ref_point(0) -= mult * update(0);
212 ref_point(1) -= mult * update(1);
218 mooseWarning(
"We could not solve for the contact point.", e.what());
220 update_size = update.l2_norm();
221 d = (secondary_point - phys_point[0]) * mult;
229 nit = max_newton_its;
235 if (nit == max_newton_its && update_size > tolerance_newton)
237 search_succeeded =
false;
239 const auto initial_point =
241 Moose::err <<
"Warning! Newton solve for contact point failed to converge!\nLast update " 243 << update_size <<
"\nInitial point guess: " << initial_point
244 <<
"\nLast considered point: " << phys_point[0]
245 <<
"\nThis potential contact pair (face, point) will be discarded." << std::endl;
263 const libMesh::Point in_plane_vector1 = *elem_nodes[1] - *elem_nodes[0];
264 const libMesh::Point in_plane_vector2 = *elem_nodes[2] - *elem_nodes[0];
267 out_of_plane_normal /= out_of_plane_normal.
norm();
269 p_info.
_normal = dxyz_dxi[0].
cross(out_of_plane_normal);
283 if (!contact_point_on_side)
289 fe_side->
reinit(side, &points);
293 Real tangential_distance = off_face.
norm();
295 if (tangential_distance <= tangential_tolerance)
297 contact_point_on_side =
true;
301 const std::vector<std::vector<Real>> & phi = fe_side->
get_phi();
302 const std::vector<std::vector<RealGradient>> & grad_phi = fe_side->
get_dphi();
305 fe_side->
reinit(side, &points);
317 std::vector<const Node *> & off_edge_nodes)
320 off_edge_nodes.clear();
334 off_edge_nodes.push_back(side->
node_ptr(0));
339 off_edge_nodes.push_back(side->
node_ptr(1));
351 if (xi <= 0.0 && eta <= 0.0)
355 off_edge_nodes.push_back(side->
node_ptr(0));
357 else if (xi > 0.0 && xi < 1.0 && eta < 0.0)
360 off_edge_nodes.push_back(side->
node_ptr(0));
361 off_edge_nodes.push_back(side->
node_ptr(1));
363 else if (eta > 0.0 && eta < 1.0 && xi < 0.0)
366 off_edge_nodes.push_back(side->
node_ptr(2));
367 off_edge_nodes.push_back(side->
node_ptr(0));
369 else if (xi >= 1.0 && (eta - xi) <= -1.0)
373 off_edge_nodes.push_back(side->
node_ptr(1));
375 else if (eta >= 1.0 && (eta - xi) >= 1.0)
379 off_edge_nodes.push_back(side->
node_ptr(2));
381 else if ((xi + eta) > 1.0)
383 Real delta = (xi + eta - 1.0) / 2.0;
386 off_edge_nodes.push_back(side->
node_ptr(1));
387 off_edge_nodes.push_back(side->
node_ptr(2));
403 off_edge_nodes.push_back(side->
node_ptr(0));
408 off_edge_nodes.push_back(side->
node_ptr(3));
412 off_edge_nodes.push_back(side->
node_ptr(3));
413 off_edge_nodes.push_back(side->
node_ptr(0));
422 off_edge_nodes.push_back(side->
node_ptr(1));
427 off_edge_nodes.push_back(side->
node_ptr(2));
431 off_edge_nodes.push_back(side->
node_ptr(1));
432 off_edge_nodes.push_back(side->
node_ptr(2));
440 off_edge_nodes.push_back(side->
node_ptr(0));
441 off_edge_nodes.push_back(side->
node_ptr(1));
446 off_edge_nodes.push_back(side->
node_ptr(2));
447 off_edge_nodes.push_back(side->
node_ptr(3));
std::vector< RealGradient > _d2xyzdxideta
auto norm() const -> decltype(std::norm(Real()))
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
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