https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SBMUtils.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 "SBMUtils.h"
11#include "Function.h"
12#include "MooseUtils.h"
13#include "FunctionInterface.h"
14#include "MooseParsedFunction.h"
17#include "libmesh/fe.h"
18#include "libmesh/quadrature_gauss.h"
19
20#include <limits>
21
22namespace SBMUtils
23{
24
25Real
26activeElementFraction(const Elem & elem,
27 Order qrule_order,
28 const std::function<bool(const libMesh::Point &)> & is_active)
29{
30 const FEType fe_type(elem.default_order(), LAGRANGE);
31 auto fe = FEBase::build(elem.dim(), fe_type);
32 QGauss qrule(elem.dim(), qrule_order);
33 const auto & q_points = fe->get_xyz();
34 const auto & JxW = fe->get_JxW();
35 fe->attach_quadrature_rule(&qrule);
36 fe->reinit(&elem);
37
38 Real active_measure = 0.0;
39 Real total_measure = 0.0;
40 for (const auto i : index_range(q_points))
41 {
42 if (is_active(q_points[i]))
43 active_measure += JxW[i];
44 total_measure += JxW[i];
45 }
46
47 return active_measure / total_measure;
48}
49
50bool
51isInactive(const Real active_fraction, const Real lambda)
52{
53 if (MooseUtils::absoluteFuzzyEqual(lambda, 0))
54 return true;
55 if (MooseUtils::absoluteFuzzyEqual(lambda, 1))
56 return false;
57
58 return MooseUtils::absoluteFuzzyGreaterThan(1.0 - active_fraction, lambda);
59}
60
63 const ClassificationSubdomains & subdomains,
64 const bool mark_intercepted,
65 const Real lambda)
66{
67 // Same-side nodes do not rule out a surface crossing the element or enclosing a region
68 // within it. Quadrature sampling detects most such cases, but may miss very small regions.
69 // Exact endpoint comparisons are intentional: activeElementFraction returns exactly zero
70 // or one when no or all quadrature points are active, respectively.
71 if (activity.all_nodes_active && activity.active_fraction == 1.0)
72 return subdomains.inside;
73
74 if (activity.all_nodes_inactive && activity.active_fraction == 0.0)
75 return subdomains.outside;
76
77 if (mark_intercepted)
78 return subdomains.intercepted;
79
80 return isInactive(activity.active_fraction, lambda) ? subdomains.outside : subdomains.inside;
81}
82
83bool
84checkWatertightnessFromRawElems(const std::vector<const Elem *> & bd_elements)
85{
86 for (const auto * el : bd_elements)
87 for (unsigned int s = 0; s < el->n_sides(); ++s)
88 if (!el->neighbor_ptr(s))
89 return false;
90
91 return true;
92}
93
94std::vector<const Function *>
95buildDistanceFunctions(const std::vector<FunctionName> & function_names,
96 const FunctionInterface & function_provider)
97{
98 std::vector<const Function *> funcs;
99 funcs.reserve(function_names.size());
100
101 for (const auto & name : function_names)
102 {
103 const Function * func = &function_provider.getFunctionByName(name);
104 if (!dynamic_cast<const MooseParsedFunction *>(func) &&
105 !dynamic_cast<const UnsignedDistanceToSurfaceMesh *>(func) &&
106 !dynamic_cast<const SignedDistanceToSurfaceMesh *>(func))
107 {
108 mooseError("SBM distance helpers only support ParsedFunction, "
109 "UnsignedDistanceToSurfaceMesh, or SignedDistanceToSurfaceMesh types. Offending "
110 "function: ",
111 name);
112 }
113 funcs.emplace_back(func);
114 }
115
116 return funcs;
117}
118
119RealVectorValue
120distanceVectorFromFunction(const Function * func, const libMesh::Point & pt, Real t)
121{
122 mooseAssert(dynamic_cast<const MooseParsedFunction *>(func) ||
123 dynamic_cast<const UnsignedDistanceToSurfaceMesh *>(func) ||
124 dynamic_cast<const SignedDistanceToSurfaceMesh *>(func),
125 "Function was not a valid distance strategy, the only "
126 "supported types are ParsedFunction, UnsignedDistanceToSurfaceMesh, or "
127 "SignedDistanceToSurfaceMesh.");
128
129 const Real phi = func->value(t, pt);
130 const RealVectorValue grad_phi = func->gradient(t, pt);
131 const Real grad_norm = grad_phi.norm();
132
133 if (grad_norm <= libMesh::TOLERANCE)
134 return RealVectorValue(0.0, 0.0, 0.0);
135
136 return -(phi / grad_norm) * grad_phi;
137}
138
139RealVectorValue
140trueNormalFromFunction(const Function * func, const libMesh::Point & pt, Real t)
141{
142 if (const auto * parsed = dynamic_cast<const MooseParsedFunction *>(func))
143 {
144 const auto proj_pt = pt + distanceVectorFromFunction(func, pt, t);
145 const RealVectorValue grad_phi = parsed->gradient(t, proj_pt);
146 const Real grad_norm = grad_phi.norm();
147 if (grad_norm <= libMesh::TOLERANCE)
148 return RealVectorValue(0.0, 0.0, 0.0);
149 return grad_phi / grad_norm;
150 }
151 else
152 {
153 const auto * mesh_func = dynamic_cast<const UnsignedDistanceToSurfaceMesh *>(func);
154 if (!mesh_func)
155 mesh_func = dynamic_cast<const SignedDistanceToSurfaceMesh *>(func);
156
157 mooseAssert(mesh_func, "Function was not a valid distance strategy");
158 return mesh_func->surfaceNormal(pt);
159 }
160}
161
162RealVectorValue
163closestDistanceVector(const std::vector<const Function *> & funcs,
164 const libMesh::Point & pt,
165 Real t)
166{
167 Real min_dist = std::numeric_limits<Real>::max();
168 RealVectorValue closest_dist_vec;
169
170 for (const auto & func : funcs)
171 {
172 const auto dist_vec = distanceVectorFromFunction(func, pt, t);
173 const auto dist = dist_vec.norm();
174 if (dist < min_dist)
175 {
176 min_dist = dist;
177 closest_dist_vec = dist_vec;
178 }
179 }
180
181 return closest_dist_vec;
182}
183
184RealVectorValue
185closestTrueNormalVector(const std::vector<const Function *> & funcs,
186 const libMesh::Point & pt,
187 Real t)
188{
189 Real min_dist = std::numeric_limits<Real>::max();
190 RealVectorValue closest_normal_vec;
191
192 for (const auto & func : funcs)
193 {
194 const auto dist_vec = distanceVectorFromFunction(func, pt, t);
195 const auto dist = dist_vec.norm();
196 if (dist < min_dist)
197 {
198 min_dist = dist;
199 closest_normal_vec = trueNormalFromFunction(func, pt, t);
200 }
201 }
202
203 return closest_normal_vec;
204}
205
206Real
207unionSignedDistance(const std::vector<const Function *> & funcs, Real t, const Point & p)
208{
209 // Ensure all distance functions are valid signed distance strategies
210 for (const auto * func : funcs)
211 {
212 if (!dynamic_cast<const MooseParsedFunction *>(func) &&
213 !dynamic_cast<const SignedDistanceToSurfaceMesh *>(func))
214 mooseError("Signed distance requested but function was not a valid signed distance strategy. "
215 "Valid types are MooseParsedFunction or SignedDistanceToSurfaceMesh. "
216 "Offending function: ",
217 func->name());
218 }
219
220 mooseAssert(!funcs.empty(), "unionSignedDistance requires at least one function.");
221
222 // Union signed distance: min of all signed distances
223 Real min_value = funcs[0]->value(t, p);
224 for (const auto i : make_range(std::size_t(1), funcs.size()))
225 {
226 const Real val = funcs[i]->value(t, p);
227 if (val < min_value)
228 min_value = val;
229 }
230
231 return min_value;
232}
233
234} // namespace SBMUtils
subdomain_id_type SubdomainID
const Real p
void mooseError(Args &&... args)
const std::string name
Definition Setup.h:21
const Function & getFunctionByName(const FunctionName &name) const
virtual RealGradient gradient(Real t, const Point &p) const
virtual Real value(Real t, const Point &p) const
Computes the signed distance to a surface mesh using KDTree nearest neighbor lookup from SBMSurfaceMe...
Computes the unsigned distance to a surface mesh using KDTree nearest neighbor lookup from SBMSurface...
Real activeElementFraction(const Elem &elem, Order qrule_order, const std::function< bool(const libMesh::Point &)> &is_active)
Compute the fraction of an element's quadrature-weighted measure satisfying a predicate.
Definition SBMUtils.C:26
Real unionSignedDistance(const std::vector< const Function * > &funcs, Real t, const Point &p)
Computes the union signed distance by taking the minimum of all signed distance functions.
Definition SBMUtils.C:207
RealVectorValue closestTrueNormalVector(const std::vector< const Function * > &funcs, const libMesh::Point &pt, Real t)
Scan all distance functions and return the corresponding normal vector.
Definition SBMUtils.C:185
bool checkWatertightnessFromRawElems(const std::vector< const Elem * > &bd_elements)
Definition SBMUtils.C:84
bool isInactive(Real active_fraction, Real lambda)
Return whether a partial element is inactive, i.e.
Definition SBMUtils.C:51
SubdomainID classifyPartialElement(const ElementActivity &activity, const ClassificationSubdomains &subdomains, bool mark_intercepted, Real lambda)
Classify a (possibly partial) element into an inside/outside/intercepted subdomain.
Definition SBMUtils.C:62
std::vector< const Function * > buildDistanceFunctions(const std::vector< FunctionName > &function_names, const FunctionInterface &function_provider)
Build a list of distance functions based on names specified in input.
Definition SBMUtils.C:95
RealVectorValue distanceVectorFromFunction(const Function *func, const libMesh::Point &pt, Real t)
Compute the distance vector induced by a distance function.
Definition SBMUtils.C:120
RealVectorValue trueNormalFromFunction(const Function *func, const libMesh::Point &pt, Real t)
Compute the true boundary surface normal at the point on the boundary closest to pt.
Definition SBMUtils.C:140
RealVectorValue closestDistanceVector(const std::vector< const Function * > &funcs, const libMesh::Point &pt, Real t)
Scan all distance functions and return the closest distance vector.
Definition SBMUtils.C:163
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
The subdomain IDs a (possibly partial) element can be labeled with.
Definition SBMUtils.h:58
Measured activity state of a (possibly partial) element, used to classify it.
Definition SBMUtils.h:47
bool all_nodes_active
Whether all of the element's nodes are on the active (retained) side.
Definition SBMUtils.h:49
bool all_nodes_inactive
Whether all of the element's nodes are on the inactive (removed) side.
Definition SBMUtils.h:51
Real active_fraction
Fraction of the element's quadrature-weighted measure that is active, in [0, 1].
Definition SBMUtils.h:53