https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SubdomainInterceptedGenerator.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://www.mooseframework.org
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
14
17{
20
21 params.addRequiredParam<std::string>("signed_dist_function",
22 "Parsed function expression (in terms of x, y, and z) "
23 "defining the signed distance function to "
24 "the interface.");
25
27 "subdomain_id_inside", "Subdomain ID to assign to elements categorized inside the domain.");
29 "subdomain_id_outside", "Subdomain ID to assign to elements categorized outside the domain.");
30
31 params.addParam<Real>(
32 "threshold", 0.0, "Level-set threshold value defining the interface boundary (default 0.0).");
33 params.addRequiredParam<bool>(
34 "is_domain_inside_surface",
35 "Whether the inside domain corresponds to the negative signed distance region (< threshold). "
36 "If true, points with signed distance < threshold are categorized as inside and > threshold "
37 "as outside. If false, points with signed distance > threshold are categorized as inside.");
38 params.addParam<bool>(
39 "multi_geo",
40 false,
41 "Whether to enable multi-geometry handling when chaining generators, allowing elements with "
42 "specific existing subdomain IDs to be preserved without reclassification (see "
43 "'keep_inside_as_inside' and 'keep_outside_as_outside').");
44 params.addParam<bool>("keep_inside_as_inside",
45 false,
46 "When 'multi_geo' is true, elements whose existing subdomain ID matches "
47 "'subdomain_id_inside' "
48 "are skipped, preserving their existing subdomain assignment.");
49 params.addParam<bool>(
50 "keep_outside_as_outside",
51 false,
52 "When 'multi_geo' is true, elements whose existing subdomain ID matches "
53 "'subdomain_id_outside' are skipped, preserving their existing subdomain assignment.");
54
55 params.addParam<bool>(
56 "modify_outside_only",
57 false,
58 "If true, only elements categorized as outside are updated to 'subdomain_id_outside'; "
59 "elements categorized as inside retain their existing subdomain IDs.");
60 params.addParam<bool>(
61 "modify_inside_only",
62 false,
63 "If true, only elements categorized as inside are updated to 'subdomain_id_inside'; elements "
64 "categorized as outside retain their existing subdomain IDs.");
65
66 params.addClassDescription("Classifies mesh elements into inside, outside, and optionally "
67 "intercepted subdomains based on an analytical signed distance "
68 "function expression.");
69
70 return params;
71}
72
74 : SBMSubdomainGeneratorBase(parameters),
75 FunctionParserUtils<false>(parameters),
76 _parsed_function(std::make_shared<SymFunction>()),
77 _subdomain_id_inside(getParam<SubdomainID>("subdomain_id_inside")),
78 _subdomain_id_outside(getParam<SubdomainID>("subdomain_id_outside")),
79 _threshold(getParam<Real>("threshold")),
80 _is_domain_inside_surface(getParam<bool>("is_domain_inside_surface")),
81 _multi_geo(getParam<bool>("multi_geo")),
82 _keep_inside_as_inside(getParam<bool>("keep_inside_as_inside")),
83 _keep_outside_as_outside(getParam<bool>("keep_outside_as_outside")),
84 _modify_outside_only(getParam<bool>("modify_outside_only")),
85 _modify_inside_only(getParam<bool>("modify_inside_only"))
86{
88
89 if (_parsed_function->Parse(getParam<std::string>("signed_dist_function"), "x,y,z") >= 0)
90 mooseError("Invalid function expression provided.");
91
92 _func_params.resize(3);
93}
94
95std::unique_ptr<libMesh::MeshBase>
97{
98 // Take ownership of the input mesh (already cloned by getMesh()).
99 std::unique_ptr<libMesh::MeshBase> mesh = std::move(_input);
100
101 for (const auto & elem : mesh->active_element_ptr_range() /*gen only run rank = 0*/)
102 {
103 // Skip elements that have already been explicitly assigned by a
104 // previous geometry in a multi-geometry workflow.
105 if (_multi_geo)
106 {
107 if (elem->subdomain_id() == _subdomain_id_inside && _keep_inside_as_inside)
108 continue;
109 else if (elem->subdomain_id() == _subdomain_id_outside && _keep_outside_as_outside)
110 continue;
111 }
112
113 const auto outside_id = (_modify_inside_only) ? elem->subdomain_id() : _subdomain_id_outside;
114 const auto inside_id = (_modify_outside_only) ? elem->subdomain_id() : _subdomain_id_inside;
115
116 const auto is_in_domain = [&](const Point & point)
117 {
118 _func_params = {point(0), point(1), point(2)};
119 const Real phi = evaluate(_parsed_function);
120 return (_is_domain_inside_surface && phi < _threshold) ||
122 };
123
124 const auto is_outside_domain = [&](const Point & point)
125 {
126 _func_params = {point(0), point(1), point(2)};
127 const Real phi = evaluate(_parsed_function);
128 return (_is_domain_inside_surface && phi > _threshold) ||
130 };
131
132 // Calculate the element occupancy at nodes and quadrature points according to the domain
133 // policy.
134 const auto occupancy =
135 SBMUtils::elementDomainOccupancy(*elem, _qrule_order, is_in_domain, is_outside_domain);
136
137 // The subdomain IDs to assign for inside, outside, and intercepted elements.
138 const SBMUtils::ClassificationSubdomains subdomain_id_settings{
139 inside_id, outside_id, _intercepted_subdomain_policy.subdomain_id};
140
141 // Classify the element based on its occupancy and the intercepted-subdomain policy.
142 elem->subdomain_id() = SBMUtils::classifySubdomainFromOccupancy(
143 occupancy, subdomain_id_settings, _intercepted_subdomain_policy.mark_intercepted, _lambda);
144 }
145
146 // Signal that the mesh has been modified and needs preparation.
147 mesh->unset_is_prepared();
148 return mesh;
149}
registerMooseObject("ShiftedBoundaryMethodApp", SubdomainInterceptedGenerator)
std::vector< GenericReal< is_ad > > _func_params
void setParserFeatureFlags(SymFunctionPtr &) const
GenericReal< is_ad > evaluate(SymFunctionPtr &, const std::string &object_name="")
static InputParameters validParams()
GenericSymFunction< is_ad > SymFunction
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)
void mooseError(Args &&... args) const
const SBMUtils::InterceptedSubdomainPolicy _intercepted_subdomain_policy
Policy for assigning partial elements to a dedicated intercepted subdomain.
const Order _qrule_order
Quadrature order used to estimate the retained-domain fraction.
const Real _lambda
Threshold applied to the fraction outside the retained domain for a partial element.
Common parameters and members for shifted boundary subdomain mesh generators that classify volume ele...
std::unique_ptr< libMesh::MeshBase > & _input
The input mesh to modify.
static InputParameters validParams()
Classifies mesh elements into inside, outside, and optionally intercepted subdomains based on an anal...
SubdomainInterceptedGenerator(const InputParameters &parameters)
SubdomainID _subdomain_id_inside
Subdomain ID assigned to elements categorized inside the domain.
SymFunctionPtr _parsed_function
Parsed function.
bool _modify_inside_only
If true, only modify inside elements; outside elements retain their existing subdomain IDs.
bool _multi_geo
Whether multi-geometry handling is enabled to skip previously assigned elements.
bool _keep_outside_as_outside
If multi_geo is true, whether to keep elements already matching subdomain_id_outside.
bool _modify_outside_only
If true, only modify outside elements; inside elements retain their existing subdomain IDs.
bool _is_domain_inside_surface
Whether the inside domain corresponds to the negative signed distance region (< threshold)
SubdomainID _subdomain_id_outside
Subdomain ID assigned to elements categorized outside the domain.
bool _keep_inside_as_inside
If multi_geo is true, whether to keep elements already matching subdomain_id_inside.
std::unique_ptr< libMesh::MeshBase > generate() override
Real _threshold
Level-set threshold value defining the interface boundary.
MeshBase & mesh
ElementDomainOccupancy elementDomainOccupancy(const Elem &elem, Order qrule_order, const std::function< bool(const libMesh::Point &)> &is_in_domain)
Test an element against the domain defined by is_in_domain.
Definition SBMUtils.C:51
SubdomainID classifySubdomainFromOccupancy(const ElementDomainOccupancy &occupancy, const ClassificationSubdomains &subdomain_id_settings, bool mark_intercepted, Real lambda)
Classify an element from its retained-domain occupancy measurements.
Definition SBMUtils.C:138
The subdomain IDs a (possibly partial) element can be labeled with.
Definition SBMUtils.h:102