15 #include "libmesh/mesh_generation.h" 16 #include "libmesh/mesh.h" 17 #include "libmesh/elem.h" 18 #include "libmesh/remote_elem.h" 19 #include "libmesh/string_to_enum.h" 25 params.
addRequiredParam<MeshGeneratorName>(
"input",
"The mesh we want to modify");
28 "new_subdomain",
"The list of subdomain names to create on the supplied subdomain");
29 params.
addParam<std::vector<SubdomainName>>(
30 "included_subdomains",
31 "A set of subdomain names or ids an element has to be previously a part of to be considered " 38 "If supplied, only surface (2D) elements with normal equal to this, up to " 39 "normal_tol, will be considered for modification");
42 "normal_tol>=0 & normal_tol<=2",
43 "Surface elements are " 44 "only added if face_normal.normal_hat >= " 45 "1 - normal_tol, where normal_hat = " 46 "normal/|normal|. The normal can the normal specified by the " 47 "parameter or by a specific mesh generator.");
51 "Whether to move the normal vector as we paint/flood the geometry, or keep it " 52 "fixed from the first element we started painting with");
53 params.
addParam<
bool>(
"check_painted_neighbor_normals",
55 "When examining the normal of a 2D element and comparing to the 'painting' " 56 "normal, also check if the element neighbors in the 'painted' subdomain " 57 "have a closer normal and accept the element into the new subdomain if so");
65 "flipped_normal_tol>=0 & flipped_normal_tol<=2",
66 "If 'consider_flipped_normals' is true, surface elements are " 67 "also added if -1 * face_normal.normal_hat >= " 68 "1 - normal_tol, where normal_hat = " 71 "consider_flipped_normals",
73 "Whether to allow for surface elements to be considered " 74 "when their normal is flipped with regard to the neighbor element we are painting from. A " 75 "specific tolerance may be specified for these flipped normals using the " 76 "'flipped_normal_tol'.");
78 "flip_inverted_normals",
false,
"Whether to flip the elements with inverted normals");
82 "max_paint_size_centroids",
83 "Maximum distance between element centroids (using a vertex average approximation) " 84 "when painting/flooding the geometry. 0 means not applying a distance constraint, a single " 85 "value in the vector is applied to all elements, multiple values can be specified for each " 86 "'included_subdomains'");
88 "flood_elements_once",
90 "Whether to consider elements only once when painting/flooding the geometry");
92 "flood_max_recursion",
94 "Max number of recursions when flooding. Once this number is reached, the propagation is " 95 "stopped until enough calls have returned");
98 "Flooding using surface element normals");
100 "Flooding using surface element inverted normals");
107 _input(getMesh(
"input")),
108 _subdomain_names(isParamValid(
"new_subdomain")
109 ? getParam<
std::vector<SubdomainName>>(
"new_subdomain")
110 :
std::vector<SubdomainName>()),
111 _check_subdomains(isParamValid(
"included_subdomains")),
113 _using_normal(isParamSetByUser(
"normal") || isParamValid(
"_using_normal")),
114 _normal(isParamSetByUser(
"normal")
115 ? Point(getParam<Point>(
"normal") / getParam<Point>(
"normal").
norm())
116 : getParam<Point>(
"normal")),
117 _normal_tol(getParam<
Real>(
"normal_tol")),
118 _flipped_normal_tol(getParam<
Real>(
"flipped_normal_tol")),
119 _fixed_flooding_normal(getParam<bool>(
"fixed_normal")),
120 _consider_flipped_normals(getParam<bool>(
"consider_flipped_normals")),
121 _flip_inverted_normals(getParam<bool>(
"flip_inverted_normals")),
122 _has_max_distance_criterion(isParamSetByUser(
"max_paint_size_centroids")),
123 _flood_only_once(getParam<bool>(
"flood_elements_once")),
124 _flood_max_recursion(getParam<unsigned
int>(
"flood_max_recursion")),
125 _check_painted_neighor_normals(getParam<bool>(
"check_painted_neighbor_normals"))
133 if (!
mesh.preparation().has_cached_elem_data)
134 mesh.cache_elem_data();
140 const auto & subdomains = getParam<std::vector<SubdomainName>>(
"included_subdomains");
141 for (
const auto &
name : subdomains)
143 paramError(
"included_subdomains",
"The block '",
name,
"' was not found in the mesh");
151 const auto & max_dists = getParam<std::vector<Real>>(
"max_paint_size_centroids");
154 "Maximum distance should be specified uniformly for all subdomains (1 value) or a " 155 "value for each 'included_subdomains'");
162 (max_dists.size() == 1)
164 : (max_dists[i] > 0 ? max_dists[i]
177 const Point & base_normal,
178 const Elem & starting_elem,
197 bool criterion_met =
false;
199 criterion_met =
true;
204 for (
const auto neighbor :
make_range(elem->n_sides()))
205 if (elem->neighbor_ptr(neighbor) &&
206 (elem->neighbor_ptr(neighbor)->subdomain_id() == sub_id) &&
208 elem,
get2DElemNormal(elem->neighbor_ptr(neighbor)), starting_elem, elem_normal))
209 criterion_met =
true;
227 BoundaryInfo & boundary_info =
mesh.get_boundary_info();
230 elem->flip(&boundary_info);
233 for (
const auto neighbor :
make_range(elem->n_sides()))
238 flood(elem->neighbor_ptr(neighbor),
249 const Point & desired_normal,
250 const Elem & base_elem,
251 const Point & face_normal)
const 276 if ((elem->vertex_average() - base_elem.vertex_average()).
norm_sq() > max_dsq)
286 mooseAssert(elem->dim() == 2,
"Should be a 2D element");
287 mooseAssert(elem->default_order() ==
FIRST,
"Should be a first order element");
290 if (elem->n_nodes() > 3)
292 std::vector<Point> vec_pts(elem->n_nodes());
293 for (
const auto & node : elem->node_ref_range())
294 vec_pts.push_back(node);
296 mooseDoOnce(
mooseWarning(
"A non planar element was detected. Normal is approximated with the " 297 "first 3 nodes at time."););
300 const auto & p1 = elem->point(0);
301 const auto & p2 = elem->point(1);
302 const auto & p3 = elem->point(2);
303 auto elem_normal = (p1 - p2).cross(p1 - p3);
304 if (elem_normal.norm_sq() == 0)
306 mooseWarning(
"Colinear nodes on element " + std::to_string(elem->id()) +
", using 0 normal");
309 return elem_normal.unit();
bool elementSubdomainIdInList(const Elem *const elem, const std::vector< subdomain_id_type > &subdomain_id_list)
Determines whether the given element's subdomain id is in the given subdomain_id_list.
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
void setup(MeshBase &mesh)
Sets up various data structures.
std::unordered_map< subdomain_id_type, std::unordered_set< Elem * > > _visited
Map used for the flooding algorithm to keep track of which elements have been visited for which subdo...
void flood(Elem *const elem, const Point &normal, const Elem &starting_elem, const subdomain_id_type &sub_id, MeshBase &mesh)
This method implements a recursive flood routine to paint (applying an operation) to elements on mesh...
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
const Real _normal_tol
Tolerance to group elements with normals such that face_normal.normal_hat <= 1 - normal_tol where nor...
bool _using_normal
true if only elements are only considered when their normal is close to either the "_normal" or a mov...
bool isCoPlanar(const std::vector< Point > &vec_pts, const Point plane_nvec, const Point fixed_pt)
Decides whether all the Points of a vector of Points are in a plane that is defined by a normal vecto...
SurfaceMeshGeneratorBase(const InputParameters ¶meters)
const bool _flip_inverted_normals
Whether to flip the normal of a surface element when they meet the criterion.
std::vector< subdomain_id_type > getSubdomainIDs(const libMesh::MeshBase &mesh, const std::vector< SubdomainName > &subdomain_name)
Get the associated subdomainIDs for the subdomain names that are passed in.
Point get2DElemNormal(const Elem *const elem) const
Get the normal of the 2D element.
auto max(const L &left, const R &right)
virtual void actOnElem(Elem *const elem, const Point &normal, const subdomain_id_type &sub_id, MeshBase &mesh)=0
Action to perform when flooding.
unsigned int _flood_recursion_count
Current tally for the number of flood routine calls active.
void mooseWarning(Args &&... args) const
const bool _check_painted_neighor_normals
Additional heuristic: check the element neighbors and if they have already been painted with the subd...
const std::string & name() const
Get the name of the class.
const Real _flipped_normal_tol
Tolerance but when using the flipped normal.
std::unordered_map< subdomain_id_type, Real > _max_elem_distance
Distance to use for max painting radius. This distance can be specified per subdomain.
static InputParameters validParams()
static InputParameters validParams()
bool hasSubdomainName(const MeshBase &input_mesh, const SubdomainName &name)
Whether a particular subdomain name exists in the mesh.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const bool _consider_flipped_normals
Whether to also consider surface elements that have a flipped normal.
const bool _has_max_distance_criterion
Whether to painting beyond a certain radius.
const unsigned int _flood_max_recursion
Maximum amount of calls to the flood routine at once.
const bool _check_subdomains
whether to check the prior subdomain id of the element when choosing whether to change its subdomain ...
IntRange< T > make_range(T beg, T end)
bool _flood_only_once
Only act on each element once.
std::unordered_set< Elem * > _acted_upon_once
Set used when flooding each element once. If the element pointer is in the set, it has been visited a...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
const bool _fixed_flooding_normal
Whether to paint/flood using a fixed normal or a moving normal.
MooseUnits pow(const MooseUnits &, int)
MeshGenerators are objects that can modify or add to an existing mesh.
void ErrorVector unsigned int
auto index_range(const T &sizable)
bool normalsWithinTol(const Point &normal_1, const Point &normal_2, const Real tol)
Determines whether two normal vectors are within normal_tol of each other.
std::vector< subdomain_id_type > _included_subdomain_ids
A list of included subdomain ids that the element has to be priorly a part of, extracted from the 'in...
bool elementSatisfiesRequirements(const Elem *const elem, const Point &desired_normal, const Elem &base_elem, const Point &face_normal) const
Determines whether the given element satisfies a set of criteria that are defined in this base class...
const RemoteElem * remote_elem