https://mooseframework.inl.gov
SBMBndElementBase.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 "SBMBndElementBase.h"
11 #include "Ball.h"
12 #include "GeometryBase.h"
13 #include "LineSegment.h"
14 #include "libmesh/string_to_enum.h"
15 
16 SBMBndElementBase::SBMBndElementBase(const Elem * elem, const Point & normal)
17  : _elem(elem), _normal(normal)
18 {
19  mooseAssert(elem, "Element must not be null");
20  mooseAssert(MooseUtils::absoluteFuzzyEqual(_normal.norm(), 1),
21  "normal vector must be unit length, length = " << _normal.norm());
22 
23  // Validate side type once, here, so distanceFrom() can trust the invariant
24  // without paying a per-call check. libMesh standard elements have uniform
25  // side types, so probing side(0) is sufficient.
26  if (elem && elem->n_sides() > 0)
27  {
28  const auto t = elem->build_side_ptr(0)->type();
29  if (t != EDGE2 && t != NODEELEM)
30  mooseError("SBMBndElementBase: unsupported side type ",
32  " (from element type ",
34  "). distanceFrom() only handles EDGE2 and NODEELEM sides.");
35  }
36 }
37 
38 Point
39 SBMBndElementBase::distanceFrom(const Point & pt) const
40 {
41  // Side-type precondition is validated once in the base ctor; no per-call
42  // check needed here.
43 
44  // (a) Project pt onto the normal direction
45  const auto vec_to_first = _elem->point(0) - pt;
46  const auto scale = vec_to_first * _normal;
47  const auto projection = _normal * scale;
48 
49  // Check if projection point lands inside the geometry
50  if (_elem->contains_point(pt + projection))
51  return projection;
52 
53  // (d) Point to closest edge or node
54  Real min_dist = std::numeric_limits<Real>::max();
55  Point closest_vec;
56 
57  const unsigned int n_edges = _elem->n_sides();
58  for (unsigned int j = 0; j < n_edges; ++j)
59  {
60  std::unique_ptr<const Elem> curr_edge = _elem->build_side_ptr(j);
61 
62  switch (curr_edge->type())
63  {
64  case EDGE2:
65  {
66  const Point & p1 = *curr_edge->node_ptr(0);
67  const Point & p2 = *curr_edge->node_ptr(1);
68 
69  const Point edge = p2 - p1;
70  Real t = ((pt - p1) * edge) / (edge * edge);
71  t = std::clamp(t, 0.0, 1.0);
72  const Point proj = p1 + t * edge;
73  const Real dist = (pt - proj).norm();
74 
75  if (dist < min_dist)
76  {
77  min_dist = dist;
78  closest_vec = proj - pt;
79  }
80  break;
81  }
82 
83  case NODEELEM:
84  {
85  const Point & p = *curr_edge->node_ptr(0);
86  const Real dist = (pt - p).norm();
87  if (dist < min_dist)
88  {
89  min_dist = dist;
90  closest_vec = p - pt;
91  }
92  break;
93  }
94 
95  default:
96  mooseAssert(false, "unreachable: side type validated in SBMBndElementBase ctor");
97  }
98  }
99 
100  return closest_vec;
101 }
102 
103 Real
105 {
106  BoundingBox bbox = _elem->loose_bounding_box();
107 
108  const Point & min_pt = bbox.first;
109  const Point & max_pt = bbox.second;
110 
111  // Step (a): Calculate box_vec
112  Point box_vec = max_pt - min_pt;
113 
114  // Step (b): Project box_vec onto normal_dir
115  Real normal_scale = box_vec * normal_dir;
116  Point normal_box_vec = normal_dir * normal_scale;
117 
118  // Step (c): Calculate tangent_vec and its norm
119  Point tangent_vec = box_vec - normal_box_vec;
120 
121  return tangent_vec.norm();
122 }
123 
124 bool
125 SBMBndElementBase::intersect(const LineSegment & line_segment) const
126 {
127  if (const auto * geom = dynamic_cast<const GeometryBase *>(this))
128  return geom->intersect(line_segment);
129 
130  mooseError("SBMBndElementBase::intersect: unsupported geometry type");
131 }
132 
133 Ball
135 {
136  if (const auto * geom = dynamic_cast<const GeometryBase *>(this))
137  return geom->computeBoundingBall();
138 
139  mooseError("SBMBndElementBase::computeBoundingBall: unsupported geometry type");
140 }
const Elem & elem() const
Getter for the underlying element.
void mooseError(Args &&... args)
void scale(MeshBase &mesh, const Real xs, const Real ys=0., const Real zs=0.)
Ball computeBoundingBall() const
Compute a bounding ball for this boundary element.
bool intersect(const LineSegment &line_segment) const
Check if the given line segment intersects this boundary element.
std::string enum_to_string(const T e)
Real getProjectedBoundingBoxDiagonal(const Point &normal_dir) const
Compute the length of the element bounding-box diagonal projected onto a plane orthogonal to a given ...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
EDGE2
const Elem * _elem
< Pointer to the libMesh element representing this boundary face.
auto norm(const T &a)
virtual Point distanceFrom(const Point &pt) const
Compute the distance vector from an arbitrary point to this boundary element.
const Real p
SBMBndElementBase(const Elem *elem, const Point &normal)
Constructor takes a pointer to a boundary element and its precomputed unit normal.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
Ball computeBoundingBall() const override
NODEELEM