https://mooseframework.inl.gov
Loading...
Searching...
No Matches
InterceptedElementModifier.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#include "SBMUtils.h"
12#include "Function.h"
14#include "UserObjectBase.h"
15
17
20{
22
23 params.addClassDescription("Marks elements as inside, outside, or intercepted based on a given "
24 "distance function or geometry.");
25
26 params.addParam<FunctionName>(
27 "signed_dist_function",
28 "Signed distance function to evaluate. Exactly one of 'signed_dist_function' and "
29 "'in_out_test' must be provided; providing neither or both is invalid.");
30
31 params.addRequiredParam<SubdomainID>("subdomain_id_inside", "ID for inside elements.");
32 params.addRequiredParam<SubdomainID>("subdomain_id_outside", "ID for outside elements.");
33
34 params.addParam<Real>("threshold", 0, "Threshold for inside/outside classification.");
35 params.addRequiredParam<bool>(
36 "is_domain_inside_surface",
37 "When true, the retained (inside) domain is the region enclosed by the surface (signed "
38 "distance below 'threshold', or points reported inside by the in-out test); when false, the "
39 "retained domain is the region outside the surface.");
40
41 params.addParam<UserObjectName>(
42 "in_out_test",
43 "The name of the in-out test user object. Exactly one of 'in_out_test' and "
44 "'signed_dist_function' must be provided; providing neither or both is invalid.");
45
46 return params;
47}
48
51 _parsed_function(isParamSetByUser("signed_dist_function")
52 ? &getFunctionByName(parameters.get<FunctionName>("signed_dist_function"))
53 : nullptr),
54 _subdomain_id_inside(getParam<SubdomainID>("subdomain_id_inside")),
55 _subdomain_id_outside(getParam<SubdomainID>("subdomain_id_outside")),
56 _threshold(getParam<Real>("threshold")),
57 _is_domain_inside_surface(getParam<bool>("is_domain_inside_surface")),
58 _in_out_test_base(nullptr)
59{
60 // Register by name before sorting and defer the lookup, as done by MeshCut2DUserObjectBase.
61 if (isParamSetByUser("in_out_test"))
62 _depend_uo.insert(getParam<UserObjectName>("in_out_test"));
63}
64
67{
68 const UserObjectBase & base = getUserObjectBase("in_out_test");
69 const auto * check = dynamic_cast<const PointInSurfaceCheckInterface *>(&base);
70 if (!check)
71 paramError("in_out_test",
72 "'",
73 base.name(),
74 "' (type ",
75 base.type(),
76 ") does not implement the point-in-surface check interface.");
77 return check;
78}
79
82void
84{
85 // Run the base class setup (reinitialize subdomains/variables, moving boundary maps,
86 // reinitialization strategy, and parameter consistency checks) before our own.
88
89 if (isParamSetByUser("in_out_test"))
91
92 // Exactly one geometry source must be provided.
94 mooseError("InterceptedElementModifier: provide exactly one geometry source, but both "
95 "'signed_dist_function' and 'in_out_test' were set.");
96
99 else if (_parsed_function)
101 else
102 mooseError("InterceptedElementModifier: provide exactly one geometry source, but neither "
103 "'signed_dist_function' nor 'in_out_test' was set.");
104}
105
108{
109 const Elem * elem = _current_elem;
110 if (!elem)
111 mooseError("InterceptedElementModifier: _current_elem is null!");
112
113 const auto classify_element = [this](const bool all_nodes_active,
114 const bool all_nodes_inactive,
115 const Real ratio_active) -> SubdomainID
116 {
117 const SBMUtils::ElementActivity activity{all_nodes_active, all_nodes_inactive, ratio_active};
118 const SBMUtils::ClassificationSubdomains subdomains{
120 return SBMUtils::classifyPartialElement(activity, subdomains, _mark_intercepted, _lambda);
121 };
122
123 switch (_in_out_test_type)
124 {
126 {
127 Real min_val = std::numeric_limits<Real>::max();
128 Real max_val = std::numeric_limits<Real>::lowest();
129
130 for (const auto node : make_range(elem->n_nodes()))
131 {
132 const Real val = _parsed_function->value(_t, elem->point(node));
133 min_val = std::min(min_val, val);
134 max_val = std::max(max_val, val);
135 }
136
137 const bool all_nodes_active = (_is_domain_inside_surface && max_val < _threshold) ||
139
140 const bool all_nodes_inactive = (_is_domain_inside_surface && min_val > _threshold) ||
142
143 const auto is_active = [this](const Point & point)
144 {
145 const Real val = _parsed_function->value(_t, point);
146 return (_is_domain_inside_surface && val < _threshold) ||
148 };
149
150 const Real ratio_active = SBMUtils::activeElementFraction(*elem, _qrule_order, is_active);
151
152 return classify_element(all_nodes_active, all_nodes_inactive, ratio_active);
153 }
154
156 {
157 unsigned int inside_nodes = 0;
158 for (const auto node : make_range(elem->n_nodes()))
159 if (_in_out_test_base->contains(elem->point(node)))
160 ++inside_nodes;
161
162 const unsigned int active_nodes =
163 _is_domain_inside_surface ? inside_nodes : elem->n_nodes() - inside_nodes;
164
165 const auto is_active = [this](const Point & point)
166 {
167 const bool is_inside = _in_out_test_base->contains(point);
168 return _is_domain_inside_surface ? is_inside : !is_inside;
169 };
170
171 const Real ratio_active = SBMUtils::activeElementFraction(*elem, _qrule_order, is_active);
172
173 return classify_element(active_nodes == elem->n_nodes(), active_nodes == 0, ratio_active);
174 }
175
177 mooseError("InterceptedElementModifier: DistanceType::NONE is invalid in "
178 "computeSubdomainID().");
179 }
180
181 mooseError("InterceptedElementModifier: unhandled DistanceType in computeSubdomainID().");
182}
subdomain_id_type SubdomainID
registerMooseObject("ShiftedBoundaryMethodApp", InterceptedElementModifier)
void initialSetup() override
const Elem *const & _current_elem
virtual Real value(Real t, const Point &p) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
DistanceType _in_out_test_type
How to classify the element to be inside or outside.
static InputParameters validParams()
const PointInSurfaceCheckInterface * _in_out_test_base
user object for in-out test
virtual void initialSetup() override
Validate that exactly one geometry source (signed_dist_function or in_out_test) is set,...
SubdomainID _subdomain_id_outside
IDs for subdomain classification (outside)
const PointInSurfaceCheckInterface * getCheckedInOutTest()
Fetches the "in_out_test" user object and validates it implements the point-in-surface check interfac...
InterceptedElementModifier(const InputParameters &parameters)
const Function * _parsed_function
Store the parsed function.
SubdomainID _subdomain_id_inside
IDs for subdomain classification (inside)
Real _threshold
Threshold value for classification.
virtual SubdomainID computeSubdomainID() override
bool _is_domain_inside_surface
When true, the retained (inside) domain is the region enclosed by the surface (signed distance below ...
const std::string & type() const
const std::string & name() const
void paramError(const std::string &param, Args... args) const
bool isParamSetByUser(const std::string &name) const
void mooseError(Args &&... args) const
bool contains(const libMesh::Point &p) const
Common partial-element classification parameters for shifted boundary element modifiers.
const Order _qrule_order
Quadrature order used to estimate the active fraction.
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.
std::set< std::string > _depend_uo
const UserObjectBase & getUserObjectBase(const std::string &param_name, bool is_dependency=true) const
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
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
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