158{
161
162
165 {
169 }
170
171 const BoundaryInfo & boundary_info =
_mesh.
getMesh().get_boundary_info();
172 std::unique_ptr<PointLocatorBase> point_locator;
175
176 for (const auto & node_id : range)
177 {
179
180
181
182
186
187 std::vector<PenetrationInfo *> p_info;
188 bool info_set(false);
189
190
191 if (info)
192 {
195
197 {
198 const Point contact_ref =
info->_closest_point_ref;
199 bool contact_point_on_side(false);
200
201
202
203 std::vector<Point> points(1);
204 points[0] = contact_ref;
205 const std::vector<Point> & secondary_pos = fe_side->get_xyz();
206 bool search_succeeded = false;
207
209 fe_elem,
210 fe_side,
212 secondary_pos[0],
213 false,
215 contact_point_on_side,
216 search_succeeded);
217
218
219 info->_closest_point_ref = contact_ref;
220
221
222 info->_distance = 0.0;
223 info_set = true;
224 }
225 else
226 {
227 Real old_tangential_distance(
info->_tangential_distance);
228 bool contact_point_on_side(false);
229 bool search_succeeded = false;
230
232 fe_elem,
233 fe_side,
235 node,
236 false,
238 contact_point_on_side,
239 search_succeeded);
240
241 if (contact_point_on_side)
242 {
243 if (
info->_tangential_distance <= 0.0)
244 {
245 info_set = true;
246 }
247 else if (
info->_tangential_distance > 0.0 && old_tangential_distance > 0.0)
248 {
249 if (
info->_side->dim() == 2 &&
info->_off_edge_nodes.size() < 2)
250 {
251
252 }
253 else
254 {
255 info_set = true;
256 }
257 }
258 }
259 }
260 }
261
262 if (!info_set)
263 {
265
266 std::vector<dof_id_type> located_elem_ids;
267 const std::vector<dof_id_type> * closest_elems;
268
270 {
271 std::set<const Elem *> candidate_elements;
272 (*point_locator)(*closest_node, candidate_elements);
273
274 if (candidate_elements.empty())
275 mooseError(
"No proximate elements found at node ",
276 closest_node->id(),
277 " at ",
278 cast_ref<const Point &>(*closest_node),
279 " on boundary ",
281 ". This should never happen.");
282
283 for (const Elem * elem : candidate_elements)
284 {
285 for (auto s : elem->side_index_range())
287 {
288 located_elem_ids.push_back(elem->id());
289 break;
290 }
291 }
292
293 if (located_elem_ids.empty())
294 mooseError(
"No proximate elements found at node ",
295 closest_node->id(),
296 " at ",
297 cast_ref<const Point &>(*closest_node),
298 " on boundary ",
300 " share that boundary. This may happen if the mesh uses the same boundary id "
301 "for a nodeset and an unrelated sideset.");
302
303 closest_elems = &located_elem_ids;
304 }
305 else
306 {
309 "Missing entry in node to elem map");
310 closest_elems = &(node_to_elem_pair->second);
311 }
312
313 for (const auto & elem_id : *closest_elems)
314 {
316
317 std::vector<PenetrationInfo *> thisElemInfo;
318
319 std::vector<const Node *> nodesThatMustBeOnSide;
320
321
322
323
324
325
326
327
328
330 nodesThatMustBeOnSide.push_back(closest_node);
333 }
334
336 {
337 Real min_distance_sq = std::numeric_limits<Real>::max();
338 Point best_point;
340
341
342 for (unsigned int i = 0; i < p_info.size(); ++i)
343 {
344 const Point closest_point = closest_point_to_side(node, *p_info[i]->_side);
345 const Real distance_sq = (closest_point - node).
norm_sq();
346 if (distance_sq < min_distance_sq)
347 {
348 min_distance_sq = distance_sq;
349 best_point = closest_point;
350 best_i = i;
351 }
352 }
353
354 p_info[best_i]->_closest_point = best_point;
355 p_info[best_i]->_distance =
356 (p_info[best_i]->_distance >= 0.0 ? 1.0 : -1.0) * std::sqrt(min_distance_sq);
358 mooseError(
"Normal smoothing not implemented with point locator code");
359 Point normal = (best_point - node).unit();
360 const Real dot = normal * p_info[best_i]->_normal;
361 if (dot < 0)
362 normal *= -1;
363 p_info[best_i]->_normal = normal;
364
366 info_set = true;
367 }
368 else
369 {
370 if (p_info.size() == 1)
371 {
373 {
375 info_set = true;
376 }
377 }
378 else if (p_info.size() > 1)
379 {
380
381 std::vector<RidgeData> ridgeDataVec;
382 for (unsigned int i = 0; i + 1 < p_info.size(); ++i)
383 for (unsigned int j = i + 1; j < p_info.size(); ++j)
384 {
385 Point closest_coor;
386 Real tangential_distance(0.0);
387 const Node * closest_node_on_ridge = NULL;
388 unsigned int index = 0;
389 Point closest_coor_ref;
391 tangential_distance,
392 closest_node_on_ridge,
393 index,
394 closest_coor_ref,
395 p_info,
396 i,
397 j);
398 if (found_ridge_contact_point)
399 {
400 RidgeData rpd;
401 rpd._closest_coor = closest_coor;
402 rpd._tangential_distance = tangential_distance;
403 rpd._closest_node = closest_node_on_ridge;
404 rpd._index = index;
405 rpd._closest_coor_ref = closest_coor_ref;
406 ridgeDataVec.push_back(rpd);
407 }
408 }
409
410 if (ridgeDataVec.size() > 0)
411 {
412
413
414 std::vector<RidgeSetData> ridgeSetDataVec;
415 for (unsigned int i = 0; i < ridgeDataVec.size(); ++i)
416 {
417 bool foundSetWithMatchingNode = false;
418 for (unsigned int j = 0; j < ridgeSetDataVec.size(); ++j)
419 {
420 if (ridgeDataVec[i]._closest_node != NULL &&
421 ridgeDataVec[i]._closest_node == ridgeSetDataVec[j]._closest_node)
422 {
423 foundSetWithMatchingNode = true;
424 ridgeSetDataVec[j]._ridge_data_vec.push_back(ridgeDataVec[i]);
425 break;
426 }
427 }
428 if (!foundSetWithMatchingNode)
429 {
430 RidgeSetData rsd;
431 rsd._distance = std::numeric_limits<Real>::max();
432 rsd._ridge_data_vec.push_back(ridgeDataVec[i]);
433 rsd._closest_node = ridgeDataVec[i]._closest_node;
434 ridgeSetDataVec.push_back(rsd);
435 }
436 }
437
438 for (unsigned int i = 0; i < ridgeSetDataVec.size(); ++i)
439 {
440 if (ridgeSetDataVec[i]._closest_node !=
441 NULL)
442 {
443 if (ridgeSetDataVec[i]._ridge_data_vec.size() == 1)
444 {
445 if (ridgeSetDataVec[i]._ridge_data_vec[0]._tangential_distance <=
447 {
448 ridgeSetDataVec[i]._closest_coor =
449 ridgeSetDataVec[i]._ridge_data_vec[0]._closest_coor;
450 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
451 ridgeSetDataVec[i]._distance = contact_point_vec.norm();
452 }
453 }
454 else
455
456 {
457 ridgeSetDataVec[i]._closest_coor = *ridgeSetDataVec[i]._closest_node;
458 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
459 ridgeSetDataVec[i]._distance = contact_point_vec.norm();
460 }
461 }
462 else
463 {
464 ridgeSetDataVec[i]._closest_coor =
465 ridgeSetDataVec[i]._ridge_data_vec[0]._closest_coor;
466 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
467 ridgeSetDataVec[i]._distance = contact_point_vec.norm();
468 }
469 }
470
471 unsigned int closest_ridge_set_index(0);
472 Real closest_distance(ridgeSetDataVec[0]._distance);
473 Point closest_point(ridgeSetDataVec[0]._closest_coor);
474 for (unsigned int i = 1; i < ridgeSetDataVec.size(); ++i)
475 {
476 if (ridgeSetDataVec[i]._distance < closest_distance)
477 {
478 closest_ridge_set_index = i;
479 closest_distance = ridgeSetDataVec[i]._distance;
480 closest_point = ridgeSetDataVec[i]._closest_coor;
481 }
482 }
483
484 if (closest_distance <
485 std::numeric_limits<Real>::max())
486 {
487
488
489
490
491
492
493
494 unsigned int face_index(std::numeric_limits<unsigned int>::max());
495 for (unsigned int i = 0;
496 i < ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec.size();
497 ++i)
498 {
499 if (ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[i]._index < face_index)
500 face_index = ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[i]._index;
501 }
502
503 mooseAssert(face_index < std::numeric_limits<unsigned int>::max(),
504 "face_index invalid");
505
506 p_info[face_index]->_closest_point = closest_point;
507 p_info[face_index]->_distance =
508 (p_info[face_index]->_distance >= 0.0 ? 1.0 : -1.0) * closest_distance;
509
510
511
513 {
514 Point normal(closest_point - node);
515 const Real len(normal.norm());
516 if (len > 0)
517 {
518 normal /= len;
519 }
520 const Real dot(normal * p_info[face_index]->_normal);
521 if (dot < 0)
522 normal *= -1;
523 p_info[face_index]->_normal = normal;
524 }
525 p_info[face_index]->_tangential_distance = 0.0;
526
527 Point closest_point_ref;
528 if (ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec.size() ==
529 1)
530 {
531 p_info[face_index]->_tangential_distance = ridgeSetDataVec[closest_ridge_set_index]
532 ._ridge_data_vec[0]
533 ._tangential_distance;
534 p_info[face_index]->_closest_point_ref =
535 ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[0]._closest_coor_ref;
536 }
537 else
538 {
539 const Node * closest_node_on_face;
541 closest_node_on_face,
542 p_info[face_index]->_side);
543 if (restricted)
544 {
545 if (closest_node_on_face !=
546 ridgeSetDataVec[closest_ridge_set_index]._closest_node)
547 {
548 mooseError(
"Closest node when restricting point to face != closest node from "
549 "RidgeSetData");
550 }
551 }
552 }
553
555 std::vector<Point> points(1);
556 points[0] = p_info[face_index]->_closest_point_ref;
557 fe->reinit(p_info[face_index]->_side, &points);
558 p_info[face_index]->_side_phi = fe->get_phi();
559 p_info[face_index]->_side_grad_phi = fe->get_dphi();
560 p_info[face_index]->_dxyzdxi = fe->get_dxyzdxi();
561 p_info[face_index]->_dxyzdeta = fe->get_dxyzdeta();
562 p_info[face_index]->_d2xyzdxideta = fe->get_d2xyzdxideta();
563
565 info_set = true;
566 }
567 else
568 {
569
570 }
571 }
572
573 if (!info_set)
574 {
575 unsigned int best(0), i(1);
576 do
577 {
580 {
581 i++;
582 }
584 {
585 best = i;
586 i++;
587 }
589 {
590 best = i + 1;
591 i += 2;
592 }
593 } while (i < p_info.size() && best < p_info.size());
594 if (best < p_info.size())
595 {
596
598 {
600 info_set = true;
601 }
602 }
603 }
604 }
605 }
606 }
607
608 if (!info_set)
609 {
610
611
612
613
614
616
619 }
620 else
621 {
625 }
626
627 for (unsigned int j = 0; j < p_info.size(); ++j)
628 {
629 if (p_info[j])
630 {
631 delete p_info[j];
632 p_info[j] = NULL;
633 }
634 }
635 }
636}
Threads::spin_mutex pinfo_mutex
virtual const Node & nodeRef(const dof_id_type i) const
virtual std::unique_ptr< libMesh::PointLocatorBase > getPointLocator() const
Proxy function to get a (sub)PointLocator from either the underlying libMesh mesh (default),...
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.
void computeSlip(libMesh::FEBase &fe, PenetrationInfo &info)
MooseVariable * _nodal_normal_x
MooseVariable * _nodal_normal_z
MooseVariable * _nodal_normal_y
bool findRidgeContactPoint(libMesh::Point &contact_point, Real &tangential_distance, const Node *&closest_node, unsigned int &index, libMesh::Point &contact_point_ref, std::vector< PenetrationInfo * > &p_info, const unsigned int index1, const unsigned int index2)
void switchInfo(PenetrationInfo *&info, PenetrationInfo *&infoNew)
bool restrictPointToFace(libMesh::Point &p, const Node *&closest_node, const Elem *side)
void smoothNormal(PenetrationInfo *info, std::vector< PenetrationInfo * > &p_info, const Node &node)
CompeteInteractionResult competeInteractions(PenetrationInfo *pi1, PenetrationInfo *pi2)
When interactions are identified between a node and two faces, compete between the faces to determine...
virtual MooseVariable & getStandardVariable(const THREAD_ID tid, const std::string &var_name)=0
Returns the variable reference for requested MooseVariable which may be in any system.
const unsigned int invalid_uint