https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SBMSurfaceDistance.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "SBMSurfaceDistance.h"
11#include "SurfaceElement.h"
12#include "MooseError.h"
13
14#include "libmesh/elem.h"
15#include "libmesh/string_to_enum.h"
16
17#include <algorithm>
18#include <limits>
19
20namespace SBMUtils
21{
22Point
23distanceFrom(const SurfaceElement & surface_elem, const Point & pt)
24{
25 const Elem & element = surface_elem.elem();
26 const Point & normal = surface_elem.normal();
27
28 // Precondition: this routine only handles EDGE2 and NODEELEM element sides.
29 // libMesh standard elements have uniform side types, so probing side(0) is
30 // sufficient. Validated once here as a debug assert; callers build these from
31 // supported surface meshes.
32 mooseAssert(
33 [&element]()
34 {
35 if (element.n_sides() == 0)
36 return true;
37 const auto t = element.build_side_ptr(0)->type();
38 return t == EDGE2 || t == NODEELEM;
39 }(),
40 "SBMUtils::distanceFrom only handles EDGE2 and NODEELEM element sides.");
41
42 // (a) Project pt onto the normal direction
43 const auto vec_to_first = element.point(0) - pt;
44 const auto scale = vec_to_first * normal;
45 const auto projection = normal * scale;
46
47 // Check if projection point lands inside the geometry
48 if (element.contains_point(pt + projection))
49 return projection;
50
51 // (b) Point to closest edge or node
52 Real min_dist = std::numeric_limits<Real>::max();
53 Point closest_vec;
54
55 const unsigned int n_edges = element.n_sides();
56 for (unsigned int j = 0; j < n_edges; ++j)
57 {
58 std::unique_ptr<const Elem> curr_edge = element.build_side_ptr(j);
59
60 switch (curr_edge->type())
61 {
62 case EDGE2:
63 {
64 const Point & p1 = *curr_edge->node_ptr(0);
65 const Point & p2 = *curr_edge->node_ptr(1);
66
67 const Point edge = p2 - p1;
68 Real t = ((pt - p1) * edge) / (edge * edge);
69 t = std::clamp(t, 0.0, 1.0);
70 const Point proj = p1 + t * edge;
71 const Real dist = (pt - proj).norm();
72
73 if (dist < min_dist)
74 {
75 min_dist = dist;
76 closest_vec = proj - pt;
77 }
78 break;
79 }
80
81 case NODEELEM:
82 {
83 const Point & p = *curr_edge->node_ptr(0);
84 const Real dist = (pt - p).norm();
85 if (dist < min_dist)
86 {
87 min_dist = dist;
88 closest_vec = p - pt;
89 }
90 break;
91 }
92
93 default:
94 mooseAssert(false, "unreachable: side type validated by the precondition above");
95 }
96 }
97
98 return closest_vec;
99}
100}
const Real p
Real scale
const Point & normal() const
const Elem & elem() const
libMesh::Point distanceFrom(const SurfaceElement &surface_elem, const libMesh::Point &pt)
Returns the vector from pt to the nearest point on the surface element: the normal projection if it f...