160{
163
164
167 {
171 }
172
174 std::unique_ptr<PointLocatorBase> point_locator;
177
178 for (const auto & node_id : range)
179 {
181
182
183
184
188
189 std::vector<PenetrationInfo *> p_info;
190 bool info_set(false);
191
192
193 if (info)
194 {
197
199 {
200 const Point contact_ref =
info->_closest_point_ref;
201 bool contact_point_on_side(false);
202
203
204
205 std::vector<Point> points(1);
206 points[0] = contact_ref;
207 const std::vector<Point> & secondary_pos = fe_side->
get_xyz();
208 bool search_succeeded = false;
209
211 fe_elem,
212 fe_side,
214 secondary_pos[0],
215 false,
217 contact_point_on_side,
218 search_succeeded);
219
220
221 info->_closest_point_ref = contact_ref;
222
223
224 info->_distance = 0.0;
225 info_set = true;
226 }
227 else
228 {
229 Real old_tangential_distance(
info->_tangential_distance);
230 bool contact_point_on_side(false);
231 bool search_succeeded = false;
232
234 fe_elem,
235 fe_side,
237 node,
238 false,
240 contact_point_on_side,
241 search_succeeded);
242
243 if (contact_point_on_side)
244 {
245 if (
info->_tangential_distance <= 0.0)
246 {
247 info_set = true;
248 }
249 else if (
info->_tangential_distance > 0.0 && old_tangential_distance > 0.0)
250 {
251 if (
info->_side->dim() == 2 &&
info->_off_edge_nodes.size() < 2)
252 {
253
254 }
255 else
256 {
257 info_set = true;
258 }
259 }
260 }
261 }
262 }
263
264 if (!info_set)
265 {
267
268 std::vector<dof_id_type> located_elem_ids;
269 const std::vector<dof_id_type> * closest_elems;
270
272 {
273 std::set<const Elem *> candidate_elements;
274 (*point_locator)(*closest_node, candidate_elements);
275
276 if (candidate_elements.empty())
277 mooseError(
"No proximate elements found at node ",
278 closest_node->id(),
279 " at ",
280 static_cast<const Point &
>(*closest_node),
281 " on boundary ",
283 ". This should never happen.");
284
285 for (
const Elem * elem : candidate_elements)
286 {
287 for (auto s : elem->side_index_range())
289 {
290 located_elem_ids.push_back(elem->id());
291 break;
292 }
293 }
294
295 if (located_elem_ids.empty())
296 mooseError(
"No proximate elements found at node ",
297 closest_node->id(),
298 " at ",
299 static_cast<const Point &
>(*closest_node),
300 " on boundary ",
302 " share that boundary. This may happen if the mesh uses the same boundary id "
303 "for a nodeset and an unrelated sideset.");
304
305 closest_elems = &located_elem_ids;
306 }
307 else
308 {
311 "Missing entry in node to elem map");
312 closest_elems = &(node_to_elem_pair->second);
313 }
314
315 for (const auto & elem_id : *closest_elems)
316 {
318
319 std::vector<PenetrationInfo *> thisElemInfo;
320
321 std::vector<const Node *> nodesThatMustBeOnSide;
322
323
324
325
326
327
328
329
330
332 nodesThatMustBeOnSide.push_back(closest_node);
335 }
336
338 {
339 Real min_distance_sq = std::numeric_limits<Real>::max();
342
343
344 for (unsigned int i = 0; i < p_info.size(); ++i)
345 {
346 const Point closest_point = closest_point_to_side(node, *p_info[i]->_side);
347 const Real distance_sq = (closest_point - node).
norm_sq();
348 if (distance_sq < min_distance_sq)
349 {
350 min_distance_sq = distance_sq;
351 best_point = closest_point;
352 best_i = i;
353 }
354 }
355
356 p_info[best_i]->_closest_point = best_point;
357 p_info[best_i]->_distance =
358 (p_info[best_i]->_distance >= 0.0 ? 1.0 : -1.0) * std::sqrt(min_distance_sq);
360 mooseError(
"Normal smoothing not implemented with point locator code");
361 Point normal = (best_point - node).unit();
362 const Real dot = normal * p_info[best_i]->_normal;
363 if (dot < 0)
364 normal *= -1;
365 p_info[best_i]->_normal = normal;
366
368 info_set = true;
369 }
370 else
371 {
372 if (p_info.size() == 1)
373 {
375 {
377 info_set = true;
378 }
379 }
380 else if (p_info.size() > 1)
381 {
382
383 std::vector<RidgeData> ridgeDataVec;
384 for (unsigned int i = 0; i + 1 < p_info.size(); ++i)
385 for (unsigned int j = i + 1; j < p_info.size(); ++j)
386 {
388 Real tangential_distance(0.0);
389 const Node * closest_node_on_ridge = NULL;
390 unsigned int index = 0;
391 Point closest_coor_ref;
393 tangential_distance,
394 closest_node_on_ridge,
395 index,
396 closest_coor_ref,
397 p_info,
398 i,
399 j);
400 if (found_ridge_contact_point)
401 {
402 RidgeData rpd;
403 rpd._closest_coor = closest_coor;
404 rpd._tangential_distance = tangential_distance;
405 rpd._closest_node = closest_node_on_ridge;
406 rpd._index = index;
407 rpd._closest_coor_ref = closest_coor_ref;
408 ridgeDataVec.push_back(rpd);
409 }
410 }
411
412 if (ridgeDataVec.size() > 0)
413 {
414
415
416 std::vector<RidgeSetData> ridgeSetDataVec;
417 for (unsigned int i = 0; i < ridgeDataVec.size(); ++i)
418 {
419 bool foundSetWithMatchingNode = false;
420 for (unsigned int j = 0; j < ridgeSetDataVec.size(); ++j)
421 {
422 if (ridgeDataVec[i]._closest_node != NULL &&
423 ridgeDataVec[i]._closest_node == ridgeSetDataVec[j]._closest_node)
424 {
425 foundSetWithMatchingNode = true;
426 ridgeSetDataVec[j]._ridge_data_vec.push_back(ridgeDataVec[i]);
427 break;
428 }
429 }
430 if (!foundSetWithMatchingNode)
431 {
432 RidgeSetData rsd;
433 rsd._distance = std::numeric_limits<Real>::max();
434 rsd._ridge_data_vec.push_back(ridgeDataVec[i]);
435 rsd._closest_node = ridgeDataVec[i]._closest_node;
436 ridgeSetDataVec.push_back(rsd);
437 }
438 }
439
440 for (unsigned int i = 0; i < ridgeSetDataVec.size(); ++i)
441 {
442 if (ridgeSetDataVec[i]._closest_node !=
443 NULL)
444 {
445 if (ridgeSetDataVec[i]._ridge_data_vec.size() == 1)
446 {
447 if (ridgeSetDataVec[i]._ridge_data_vec[0]._tangential_distance <=
449 {
450 ridgeSetDataVec[i]._closest_coor =
451 ridgeSetDataVec[i]._ridge_data_vec[0]._closest_coor;
452 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
453 ridgeSetDataVec[i]._distance = contact_point_vec.
norm();
454 }
455 }
456 else
457
458 {
459 ridgeSetDataVec[i]._closest_coor = *ridgeSetDataVec[i]._closest_node;
460 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
461 ridgeSetDataVec[i]._distance = contact_point_vec.
norm();
462 }
463 }
464 else
465 {
466 ridgeSetDataVec[i]._closest_coor =
467 ridgeSetDataVec[i]._ridge_data_vec[0]._closest_coor;
468 Point contact_point_vec = node - ridgeSetDataVec[i]._closest_coor;
469 ridgeSetDataVec[i]._distance = contact_point_vec.
norm();
470 }
471 }
472
473 unsigned int closest_ridge_set_index(0);
474 Real closest_distance(ridgeSetDataVec[0]._distance);
475 Point closest_point(ridgeSetDataVec[0]._closest_coor);
476 for (unsigned int i = 1; i < ridgeSetDataVec.size(); ++i)
477 {
478 if (ridgeSetDataVec[i]._distance < closest_distance)
479 {
480 closest_ridge_set_index = i;
481 closest_distance = ridgeSetDataVec[i]._distance;
482 closest_point = ridgeSetDataVec[i]._closest_coor;
483 }
484 }
485
486 if (closest_distance <
487 std::numeric_limits<Real>::max())
488 {
489
490
491
492
493
494
495
496 unsigned int face_index(std::numeric_limits<unsigned int>::max());
497 for (unsigned int i = 0;
498 i < ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec.size();
499 ++i)
500 {
501 if (ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[i]._index < face_index)
502 face_index = ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[i]._index;
503 }
504
505 mooseAssert(face_index < std::numeric_limits<unsigned int>::max(),
506 "face_index invalid");
507
508 p_info[face_index]->_closest_point = closest_point;
509 p_info[face_index]->_distance =
510 (p_info[face_index]->_distance >= 0.0 ? 1.0 : -1.0) * closest_distance;
511
512
513
515 {
516 Point normal(closest_point - node);
518 if (len > 0)
519 {
520 normal /= len;
521 }
522 const Real dot(normal * p_info[face_index]->_normal);
523 if (dot < 0)
524 normal *= -1;
525 p_info[face_index]->_normal = normal;
526 }
527 p_info[face_index]->_tangential_distance = 0.0;
528
529 Point closest_point_ref;
530 if (ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec.size() ==
531 1)
532 {
533 p_info[face_index]->_tangential_distance = ridgeSetDataVec[closest_ridge_set_index]
534 ._ridge_data_vec[0]
535 ._tangential_distance;
536 p_info[face_index]->_closest_point_ref =
537 ridgeSetDataVec[closest_ridge_set_index]._ridge_data_vec[0]._closest_coor_ref;
538 }
539 else
540 {
541 const Node * closest_node_on_face;
543 closest_node_on_face,
544 p_info[face_index]->_side);
545 if (restricted)
546 {
547 if (closest_node_on_face !=
548 ridgeSetDataVec[closest_ridge_set_index]._closest_node)
549 {
550 mooseError(
"Closest node when restricting point to face != closest node from "
551 "RidgeSetData");
552 }
553 }
554 }
555
557 std::vector<Point> points(1);
558 points[0] = p_info[face_index]->_closest_point_ref;
559 fe->
reinit(p_info[face_index]->_side, &points);
560 p_info[face_index]->_side_phi = fe->
get_phi();
561 p_info[face_index]->_side_grad_phi = fe->
get_dphi();
565
567 info_set = true;
568 }
569 else
570 {
571
572 }
573 }
574
575 if (!info_set)
576 {
577 unsigned int best(0), i(1);
578 do
579 {
582 {
583 i++;
584 }
586 {
587 best = i;
588 i++;
589 }
591 {
592 best = i + 1;
593 i += 2;
594 }
595 } while (i < p_info.size() && best < p_info.size());
596 if (best < p_info.size())
597 {
598
600 {
602 info_set = true;
603 }
604 }
605 }
606 }
607 }
608 }
609
610 if (!info_set)
611 {
612
613
614
615
616
618
621 }
622 else
623 {
627 }
628
629 for (unsigned int j = 0; j < p_info.size(); ++j)
630 {
631 if (p_info[j])
632 {
633 delete p_info[j];
634 p_info[j] = NULL;
635 }
636 }
637 }
638}
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.
virtual_for_inffe const std::vector< RealGradient > & get_d2xyzdxideta() const
const std::vector< std::vector< OutputShape > > & get_phi() const
const std::vector< std::vector< OutputGradient > > & get_dphi() const
const unsigned int invalid_uint