Line data Source code
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 255 : SBMBndElementBase::SBMBndElementBase(const Elem * elem, const Point & normal) 17 255 : : _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 255 : if (elem && elem->n_sides() > 0) 27 : { 28 255 : const auto t = elem->build_side_ptr(0)->type(); 29 255 : if (t != EDGE2 && t != NODEELEM) 30 1 : mooseError("SBMBndElementBase: unsupported side type ", 31 2 : libMesh::Utility::enum_to_string(t), 32 : " (from element type ", 33 1 : libMesh::Utility::enum_to_string(elem->type()), 34 : "). distanceFrom() only handles EDGE2 and NODEELEM sides."); 35 : } 36 254 : } 37 : 38 : Point 39 3685190 : 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 3685190 : 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 3685190 : 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 1680066 : const unsigned int n_edges = _elem->n_sides(); 58 5679239 : for (unsigned int j = 0; j < n_edges; ++j) 59 : { 60 3999173 : std::unique_ptr<const Elem> curr_edge = _elem->build_side_ptr(j); 61 : 62 3999173 : 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 1917123 : Real t = ((pt - p1) * edge) / (edge * edge); 71 3834246 : t = std::clamp(t, 0.0, 1.0); 72 : const Point proj = p1 + t * edge; 73 1917123 : const Real dist = (pt - proj).norm(); 74 : 75 1917123 : 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 2082050 : const Real dist = (pt - p).norm(); 87 2082050 : if (dist < min_dist) 88 : { 89 : min_dist = dist; 90 : closest_vec = p - pt; 91 : } 92 : break; 93 : } 94 : 95 3999173 : default: 96 : mooseAssert(false, "unreachable: side type validated in SBMBndElementBase ctor"); 97 : } 98 3999173 : } 99 : 100 1680066 : return closest_vec; 101 : } 102 : 103 : Real 104 2 : SBMBndElementBase::getProjectedBoundingBoxDiagonal(const Point & normal_dir) const 105 : { 106 2 : 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 2 : return tangent_vec.norm(); 122 : } 123 : 124 : bool 125 5 : SBMBndElementBase::intersect(const LineSegment & line_segment) const 126 : { 127 5 : if (const auto * geom = dynamic_cast<const GeometryBase *>(this)) 128 4 : return geom->intersect(line_segment); 129 : 130 1 : mooseError("SBMBndElementBase::intersect: unsupported geometry type"); 131 : } 132 : 133 : Ball 134 3 : SBMBndElementBase::computeBoundingBall() const 135 : { 136 3 : if (const auto * geom = dynamic_cast<const GeometryBase *>(this)) 137 2 : return geom->computeBoundingBall(); 138 : 139 1 : mooseError("SBMBndElementBase::computeBoundingBall: unsupported geometry type"); 140 : }