24 params.
addClassDescription(
"Assign subdomain ID based on geometric inclusion using per-subdomain "
25 "in-out checks provided by a subdomain_id_tester.");
28 "subdomain_id_tester",
29 "The UserObject (PointInSubdomainCheckUO) for subdomain in/out tests.");
45 mooseError(
"SubdomainElementModifier: _current_elem is null!");
48 if (all_checkers.empty())
49 mooseError(
"SubdomainElementModifier: subdomain checker collection is empty!");
51 std::optional<SubdomainID> fully_inside_subdomain;
52 std::optional<SubdomainID> best_intercepted_subdomain;
53 std::vector<std::pair<SubdomainID, Real>> intercepted_candidates;
56 for (
const auto & [sub_id, checker_ptr] : all_checkers)
58 unsigned int num_inside_nodes = 0;
59 for (
const auto i : make_range(elem->n_nodes()))
60 if (checker_ptr->sideness(elem->point(i)) != SurfaceGeometry::SurfaceSide::OUTSIDE)
63 const auto *
const checker = checker_ptr.get();
67 [checker](
const Point & point)
68 {
return checker->sideness(point) != SurfaceGeometry::SurfaceSide::OUTSIDE; });
70 if (num_inside_nodes == elem->n_nodes() && ratio_active == 1.0)
72 if (!fully_inside_subdomain || sub_id < *fully_inside_subdomain)
73 fully_inside_subdomain = sub_id;
78 const bool has_active_region = num_inside_nodes != 0 || ratio_active > 0.0;
79 if (!has_active_region)
82 intercepted_candidates.emplace_back(sub_id, ratio_active);
83 max_ratio = std::max(max_ratio, ratio_active);
86 if (fully_inside_subdomain)
87 return *fully_inside_subdomain;
92 for (
const auto & [sub_id, ratio_active] : intercepted_candidates)
93 if (MooseUtils::absoluteFuzzyEqual(ratio_active, max_ratio) &&
94 (!best_intercepted_subdomain || sub_id < *best_intercepted_subdomain))
95 best_intercepted_subdomain = sub_id;
99 if (!best_intercepted_subdomain)
106 : *best_intercepted_subdomain;
subdomain_id_type SubdomainID
registerMooseObject("ShiftedBoundaryMethodApp", SubdomainElementModifier)
const Elem *const & _current_elem
void mooseError(Args &&... args) const
Performs in-out testing and identifies the subdomain containing a point.
const std::map< subdomain_id_type, std::unique_ptr< const PointContainmentClassifier > > & subdomainCheckers() const
Read-only view of the per-subdomain checkers (subdomain id -> checker).
Common partial-element classification parameters for shifted boundary element modifiers.
const Order _qrule_order
Quadrature order used to estimate the active fraction.
static InputParameters validParams()
const Real _lambda
Threshold applied to the inactive fraction of a partially active element.
const SubdomainID _subdomain_id_intercepted
Subdomain ID assigned to intercepted elements.
const bool _mark_intercepted
Whether to assign a dedicated subdomain ID to intercepted elements.
SubdomainElementModifier(const InputParameters ¶meters)
const PointInSubdomainCheckUO & _subdomain_id_tester
The user object containing subdomain-wise in/out checkers.
virtual SubdomainID computeSubdomainID() override
static InputParameters validParams()
const SubdomainID INVALID_BLOCK_ID
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.
bool isInactive(Real active_fraction, Real lambda)
Return whether a partial element is inactive, i.e.