https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PointInSubdomainCheckUO.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
11
12#include "libmesh/utility.h"
13
14#include <filesystem>
15#include <sstream>
16#include <vector>
17
18registerMooseObject("ShiftedBoundaryMethodApp", PointInSubdomainCheckUO);
19
22{
25 "In-Out test with subdomain_id identification based on SurfaceMeshBySubdomainBuilder.");
26
27 params.addRequiredParam<UserObjectName>(
28 "builder", "The SurfaceMeshBySubdomainBuilder providing SurfaceElementSets by subdomain_id.");
29
30 return params;
31}
32
34 : PointInPolyhedronBaseUO(parameters),
35 _builder(getUserObject<SurfaceMeshBySubdomainBuilder>("builder"))
36{
37 // Per-subdomain checks use the ray-casting engine over element subsets; the
38 // fixed_x_ray (TriangleManifold) backend operates on a whole Tri3 MeshBase and
39 // cannot be applied per subdomain.
40 if (_method == PointContainmentClassifier::Method::FIXED_X_RAY)
41 paramError("point_containment_method",
42 "fixed_x_ray is not supported by PointInSubdomainCheckUO; use pca_ray or "
43 "user_selected_ray.");
44}
45
46void
48{
49 // The shared ray-backend tuning/debug options (method -> ray-direction intent,
50 // leaf size, comm) come from the base class; only the debug file names are
51 // specialized per subdomain below.
53
54 // Each subdomain gets its own checker, so the OBB/ray debug meshes must go to
55 // distinct files; otherwise later subdomains overwrite earlier ones. Insert the
56 // subdomain id before the extension (e.g. "obb.e" -> "obb_2.e"). An empty name
57 // means "no debug output" and is left untouched.
58 const auto per_subdomain_name = [](const FileName & base, subdomain_id_type id) -> FileName
59 {
60 if (base.empty())
61 return base;
62 std::filesystem::path p(base.c_str());
63 p.replace_filename(p.stem().string() + "_" + std::to_string(id) + p.extension().string());
64 return p.string();
65 };
66
67 for (const auto & [subdomain_id, set] : _builder.getSurfaceElementSetsBySubdomain())
68 {
69 PointContainmentClassifier::RayOptions options = base_options;
70 options.obb_file_name = per_subdomain_name(_obb_file_name, subdomain_id);
71 options.ray_file_name = per_subdomain_name(_ray_file_name, subdomain_id);
72
73 // fixed_x_ray is rejected in the constructor, so only the ray backends reach here;
74 // the facade's mesh argument is used only by fixed_x_ray and is unreferenced.
75 _subdomain_id_checkers[subdomain_id] = std::make_unique<PointContainmentClassifier>(
76 _builder.mesh(), &set, _method, _tolerance, options);
77 }
78}
79
80bool
82{
83 for (const auto & [_, checker] : _subdomain_id_checkers)
84 {
85 const SurfaceGeometry::SurfaceSide side = checker->sideness(p);
86 if (side == SurfaceGeometry::SurfaceSide::INSIDE || side == SurfaceGeometry::SurfaceSide::ON)
87 return true;
88 }
89 return false;
90}
91
92subdomain_id_type
94{
95 // A point can be reported INSIDE or ON more than one subdomain when subdomain surfaces overlap
96 // or the point lies exactly on a shared interface. That is ambiguous for a single-subdomain
97 // query, so collect every match (in ascending id order via the id-ordered map) and error
98 // unless there is exactly one.
99 std::vector<subdomain_id_type> matches;
100 for (const auto & [subdomain_id, checker] : _subdomain_id_checkers)
101 {
102 const SurfaceGeometry::SurfaceSide side = checker->sideness(p);
103 if (side == SurfaceGeometry::SurfaceSide::INSIDE || side == SurfaceGeometry::SurfaceSide::ON)
104 matches.push_back(subdomain_id);
105 }
106
107 if (matches.empty())
108 return libMesh::Elem::invalid_subdomain_id;
109
110 if (matches.size() > 1)
111 {
112 std::ostringstream ids;
113 for (const auto i : index_range(matches))
114 ids << (i ? ", " : "") << matches[i];
115 mooseError("PointInSubdomainCheckUO: point ",
116 p,
117 " is contained in multiple subdomains (",
118 ids.str(),
119 "); the geometry is ambiguous for a single-subdomain query.");
120 }
121
122 return matches.front();
123}
const Real p
registerMooseObject("ShiftedBoundaryMethodApp", PointInSubdomainCheckUO)
MeshBase & mesh() const
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
const PointContainmentClassifier::Method _method
const FileName _obb_file_name
const FileName _ray_file_name
static InputParameters validParams()
PointContainmentClassifier::RayOptions pcaRayOptions() const
Performs in-out testing and identifies the subdomain containing a point.
const SurfaceMeshBySubdomainBuilder & _builder
Builder providing subdomain-wise SurfaceElementSets.
virtual void initialSetup() override
std::map< subdomain_id_type, std::unique_ptr< const PointContainmentClassifier > > _subdomain_id_checkers
Each subdomain has its own PointContainmentClassifier (owns the checkers).
virtual subdomain_id_type whichSubdomain(const Point &p) const
Determine which subdomain the point belongs to (returns "OUTSIDE" if none)
static InputParameters validParams()
virtual bool ifInside(const Point &p) const
Check if the point is inside any subdomain.
PointInSubdomainCheckUO(const InputParameters &parameters)
BoundaryMeshBuilder specialization that groups the surface elements by subdomain, building one Surfac...
const std::unordered_map< subdomain_id_type, SurfaceElementSet > & getSurfaceElementSetsBySubdomain() const
Per-subdomain SurfaceElementSets. Valid after initialSetup().