18 #include "libmesh/int_range.h" 19 #include "libmesh/mesh_modification.h" 20 #include "libmesh/mesh_serializer.h" 21 #include "libmesh/unstructured_mesh.h" 31 MooseEnum algorithm(
"BINARY EXHAUSTIVE",
"BINARY");
32 MooseEnum tri_elem_type(
"TRI3 TRI6 TRI7 DEFAULT",
"DEFAULT");
36 "The input MeshGenerator defining the output outer boundary and required Steiner points.");
37 params.
addParam<std::vector<BoundaryName>>(
38 "input_boundary_names",
"2D-input-mesh boundaries defining the output mesh outer boundary");
39 params.
addParam<std::vector<SubdomainName>>(
40 "input_subdomain_names",
"1D-input-mesh subdomains defining the output mesh outer boundary");
41 params.
addParam<
unsigned int>(
"add_nodes_per_boundary_segment",
43 "How many more nodes to add in each outer boundary segment.");
45 "refine_boundary",
true,
"Whether to allow automatically refining the outer boundary.");
47 params.
addParam<SubdomainName>(
"output_subdomain_name",
48 "Subdomain name to set on new triangles.");
49 params.
addParam<
SubdomainID>(
"output_subdomain_id",
"Subdomain id to set on new triangles.");
53 "Boundary name to set on new outer boundary. Default ID: 0 if no hole meshes are stitched; " 54 "or maximum boundary ID of all the stitched hole meshes + 1.");
55 params.
addParam<std::vector<BoundaryName>>(
57 "Boundary names to set on holes. Default IDs are numbered up from 1 if no hole meshes are " 58 "stitched; or from maximum boundary ID of all the stitched hole meshes + 2.");
63 "Verify holes do not intersect boundary or each other. Asymptotically costly.");
65 params.
addParam<
bool>(
"smooth_triangulation",
67 "Whether to do Laplacian mesh smoothing on the generated triangles.");
68 params.
addParam<std::vector<MeshGeneratorName>>(
69 "holes", std::vector<MeshGeneratorName>(),
"The MeshGenerators that define mesh holes.");
71 "stitch_holes", std::vector<bool>(),
"Whether to stitch to the mesh defining each hole.");
72 params.
addParam<std::vector<bool>>(
"refine_holes",
74 "Whether to allow automatically refining each hole boundary.");
79 "Desired (maximum) triangle area, or 0 to skip uniform refinement");
83 "Desired area as a function of x,y; omit to skip non-uniform refinement");
88 "Control the use of binary search for the nodes of the stitched surfaces.");
90 "tri_element_type", tri_elem_type,
"Type of the triangular elements to be generated.");
92 "verbose_stitching",
false,
"Whether mesh stitching should have verbose output.");
93 params.
addParam<std::vector<Point>>(
"interior_points",
95 "Interior node locations, if no smoothing is used. Any point " 96 "outside the surface will not be meshed.");
97 params.
addParam<std::vector<FileName>>(
98 "interior_point_files", {},
"Text file(s) with the interior points, one per line");
99 params.
addClassDescription(
"Triangulates meshes within boundaries defined by input meshes.");
103 "outer_boundary_layer_thickness>=0",
104 "Thickness of the outer boundary layer to be added.");
106 "outer_boundary_layer_num", 0,
"Number of layers for the outer boundary layer.");
108 "outer_boundary_layer_bias",
110 "outer_boundary_layer_bias>0",
111 "Bias factor for the thickness of each layer in the outer boundary layer.");
114 "holes_boundary_layer_thickness",
115 "holes_boundary_layer_thickness>=0",
116 "Thickness of the hole boundary layers to be added.");
117 params.
addParam<std::vector<unsigned int>>(
"holes_boundary_layer_num",
118 "Numbers of layers for the hole boundary layers.");
120 "holes_boundary_layer_bias",
121 "holes_boundary_layer_bias>0",
122 "Bias factors for the thickness of each layer in the hole boundary layers.");
125 "Mandatory mesh interior nodes");
128 "outer_boundary_layer_bias holes_boundary_layer_thickness " 129 "holes_boundary_layer_num holes_boundary_layer_bias",
137 _bdy_ptr(getMesh(
"boundary")),
138 _add_nodes_per_boundary_segment(getParam<unsigned
int>(
"add_nodes_per_boundary_segment")),
139 _refine_bdy(getParam<bool>(
"refine_boundary")),
140 _output_subdomain_id(0),
141 _smooth_tri(getParam<bool>(
"smooth_triangulation")),
142 _verify_holes(getParam<bool>(
"verify_holes")),
143 _hole_ptrs(getMeshes(
"holes")),
144 _stitch_holes(getParam<
std::vector<bool>>(
"stitch_holes")),
145 _refine_holes(getParam<
std::vector<bool>>(
"refine_holes")),
146 _desired_area(getParam<
Real>(
"desired_area")),
147 _desired_area_func(getParam<
std::string>(
"desired_area_func")),
149 _tri_elem_type(parameters.
get<
MooseEnum>(
"tri_element_type")),
150 _verbose_stitching(parameters.
get<bool>(
"verbose_stitching")),
151 _interior_points(getParam<
std::vector<Point>>(
"interior_points")),
152 _outer_boundary_layer_thickness(getParam<
Real>(
"outer_boundary_layer_thickness")),
153 _outer_boundary_layer_num(getParam<unsigned
int>(
"outer_boundary_layer_num")),
154 _outer_boundary_layer_bias(getParam<
Real>(
"outer_boundary_layer_bias")),
155 _holes_boundary_layer_thickness(
156 isParamValid(
"holes_boundary_layer_thickness")
157 ? getParam<
std::vector<
Real>>(
"holes_boundary_layer_thickness")
159 _holes_boundary_layer_num(isParamValid(
"holes_boundary_layer_num")
160 ? getParam<
std::vector<unsigned
int>>(
"holes_boundary_layer_num")
161 :
std::vector<unsigned
int>()),
162 _holes_boundary_layer_bias(isParamValid(
"holes_boundary_layer_bias")
163 ? getParam<
std::vector<
Real>>(
"holes_boundary_layer_bias")
170 "Only one of the three methods ('desired_area', 'desired_area_func', and " 171 "'_use_auto_area_func') to set element area limit should be used.");
179 "If this parameter is set to false, the following parameters should not be set: " 180 "'auto_area_func_default_size', 'auto_area_func_default_size_dist', " 181 "'auto_area_function_num_points', 'auto_area_function_power'.");
184 paramError(
"stitch_holes",
"Need one stitch_holes entry per hole, if specified.");
188 paramError(
"refine_holes",
"Disable auto refine of any hole boundary to be stitched.");
192 auto & hole_boundaries = getParam<std::vector<BoundaryName>>(
"hole_boundaries");
193 if (hole_boundaries.size() !=
_hole_ptrs.size())
194 paramError(
"hole_boundaries",
"Need one hole_boundaries entry per hole, if specified.");
197 const auto & positions_files = getParam<std::vector<FileName>>(
"interior_point_files");
198 for (
const auto p_file_it :
index_range(positions_files))
200 const std::string positions_file = positions_files[p_file_it];
206 for (
const auto & d : data)
209 bool has_duplicates =
215 paramError(
"interior_points",
"Duplicate points were found in the provided interior points.");
220 "outer_boundary_layer_thickness",
221 "this parameter must be set as non-zero along with a non-zero outer_boundary_layer_num.");
227 "Cannot add nodes per boundary segment when using an outer boundary layer.");
229 paramError(
"refine_boundary",
"Cannot refine boundary when using an outer boundary layer.");
237 "holes_boundary_layer_thickness, holes_boundary_layer_bias and this parameter must " 238 "be specified or not specified together.");
242 "If specified, this parameter must have the same length as 'holes'.");
245 "If specified, this parameter must have the same length as 'holes'.");
248 "If specified, this parameter must have the same length as 'holes'.");
254 "holes_boundary_layer_thickness",
255 "entry " + std::to_string(i) +
256 " must be set as non-zero along with a non-zero holes_boundary_layer_num entry.");
260 paramError(
"refine_holes",
"Cannot refine hole boundary when using a hole boundary layer.");
265 std::unique_ptr<MeshBase>
308 std::vector<std::unique_ptr<MeshBase>> hole_meshes(
_hole_ptrs.size());
310 hole_meshes[hole_i] = std::move(*
_hole_ptrs[hole_i]);
312 std::unique_ptr<MeshBase> boundary_mesh = std::move(
_bdy_ptr);
318 const BoundaryName tmp_outer_name(
"__xyd_bdry_layer_tmp_outer__");
323 const SubdomainName layer_sd_name =
329 std::unique_ptr<MeshBase> outer_ring_clone;
330 if (using_outer_layer)
342 outer_ring_clone = outer_ring->clone();
343 boundary_mesh = std::move(outer_ring);
358 *hole_meshes[hole_i],
359 std::vector<BoundaryName>(),
371 auto & ring_u =
dynamic_cast<UnstructuredMesh &
>(*hole_ring);
372 auto & inp_u =
dynamic_cast<UnstructuredMesh &
>(*hole_meshes[hole_i]);
374 if (!ring_u.is_prepared())
375 ring_u.prepare_for_use();
376 if (!inp_u.is_prepared())
377 inp_u.prepare_for_use();
381 const auto & ring_bids = ring_u.get_boundary_info().get_global_boundary_ids();
382 const auto inp_bids = inp_u.get_boundary_info().get_global_boundary_ids();
383 const auto max_bid =
std::max(*ring_bids.rbegin(),
386 bool overlap =
false;
387 for (
auto b : inp_bids)
388 if (ring_bids.count(b))
393 for (
auto b : inp_bids)
395 const auto new_b = max_bid + (
idx++);
396 inp_u.get_boundary_info().renumber_id(b, new_b);
398 ext_id = max_bid +
idx;
401 ext_id = max_bid + 1;
402 inp_u.comm().max(ext_id);
403 bool has_ext =
false;
405 mooseAssert(has_ext,
"A 2D-XY mesh should have an external boundary.");
406 const auto ring_u_ext_id =
413 ring_u.stitch_meshes(inp_u,
425 hole_meshes[hole_i] = std::move(hole_ring);
439 *
this, std::move(boundary_mesh), std::move(hole_meshes), xyd_opts);
442 if (outer_ring_clone)
458 *outer_ring_clone, ring_outermost_orig, ring_outermost_temp);
460 auto & result_u =
dynamic_cast<UnstructuredMesh &
>(*result);
461 auto & clone_u =
dynamic_cast<UnstructuredMesh &
>(*outer_ring_clone);
463 result_u.stitch_meshes(clone_u,
473 if (user_has_output_boundary)
476 if (user_id != sentinel_id)
478 result->get_boundary_info().sideset_name(user_id) = user_output_boundary;
481 result->unset_is_prepared();
const std::string _desired_area_func
Desired triangle area as a (fparser-compatible) function of x,y.
const bool _verbose_stitching
Whether mesh stitching should have verbose output.
std::string desired_area_func
Bundle of inputs for triangulateWithDelaunay.
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 T & getParam(const std::string &name) const
Retrieve a parameter for the object.
const unsigned int _outer_boundary_layer_num
Number of element layers in the outer boundary-layer ring.
Real auto_area_func_default_size
const bool _verify_holes
Whether to verify holes do not intersect boundary or each other.
std::string tri_elem_type
bool has_output_subdomain_id
const std::vector< Point > getDataAsPoints() const
Get the data in Point format.
Base class for Delaunay mesh generators applied to a surface.
const std::vector< bool > _refine_holes
Whether to allow automatically refining each hole boundary.
registerMooseObject("MooseApp", XYDelaunayGenerator)
std::vector< Point > _interior_points
Desired interior node locations.
const Real _outer_boundary_layer_thickness
Thickness of an optional boundary-layer ring grown inward from the outer boundary.
bool has_output_subdomain_name
const bool _smooth_tri
Whether to do Laplacian mesh smoothing on the generated triangles.
const Real _outer_boundary_layer_bias
Bias factor for the layer thicknesses in the outer boundary-layer ring.
const Parallel::Communicator & _communicator
SubdomainID output_subdomain_id
static InputParameters validParams()
std::unique_ptr< MeshBase > & _bdy_ptr
Input mesh defining the boundary to triangulate within.
std::vector< BoundaryName > hole_boundaries
const bool _refine_bdy
Whether to allow automatically refining the outer boundary.
std::vector< BoundaryName > input_boundary_names
auto max(const L &left, const R &right)
const std::vector< Real > _holes_boundary_layer_thickness
Per-hole boundary-layer ring thicknesses (grown outward from each hole)
Real auto_area_func_default_size_dist
const std::vector< bool > _stitch_holes
Whether to stitch to the mesh defining each hole.
Generates a triangulation in the XY plane, based on an input mesh defining the outer boundary (as wel...
std::vector< SubdomainName > input_subdomain_names
const bool _use_auto_area_func
Whether to use automatic desired area function.
BoundaryName output_boundary
const std::vector< unsigned int > _holes_boundary_layer_num
Per-hole boundary-layer ring layer counts.
std::vector< bool > refine_holes
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
boundary_id_type BoundaryID
std::vector< std::set< std::size_t > > hole_boundary_id_filters
void setFormatFlag(FormatFlag value)
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.
std::unique_ptr< MeshBase > triangulateWithDelaunay(MeshGenerator &mg, std::unique_ptr< MeshBase > boundary_mesh, std::vector< std::unique_ptr< MeshBase >> hole_meshes, const XYDelaunayOptions &xyd_opts)
Performs a 2D Delaunay triangulation (via libMesh::Poly2TriTriangulator) inside a closed boundary mes...
subdomain_id_type SubdomainID
const unsigned int _auto_area_function_num_points
Maximum number of points to use for the inverse distance interpolation for automatic area function...
void read()
Perform the actual data reading.
XYDelaunayGenerator(const InputParameters ¶meters)
unsigned int auto_area_function_num_points
static InputParameters validParams()
const unsigned int _add_nodes_per_boundary_segment
How many more nodes to add in each outer boundary segment.
const std::vector< Real > _holes_boundary_layer_bias
Per-hole boundary-layer ring bias factors.
const Real _auto_area_func_default_size_dist
Background size's effective distance for automatic desired area function.
unsigned int add_nodes_per_boundary_segment
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Utility class for reading delimited data (e.g., CSV data).
SubdomainName output_subdomain_name
std::vector< bool > stitch_holes
const MooseEnum _algorithm
Type of algorithm used to find matching nodes (binary or exhaustive)
const Real _auto_area_function_power
Power of the polynomial used in the inverse distance interpolation for automatic area function...
const std::vector< std::unique_ptr< MeshBase > * > _hole_ptrs
Holds pointers to the pointers to input meshes defining holes.
std::vector< Point > interior_points
const MooseEnum _tri_elem_type
Type of triangular elements to be generated.
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
std::vector< std::set< BoundaryID > > hole_boundary_inner_id_defaults
void changeBoundaryId(MeshBase &mesh, const libMesh::boundary_id_type old_id, const libMesh::boundary_id_type new_id, bool delete_prev)
Changes the old boundary ID to a new ID in the mesh.
const Real _auto_area_func_default_size
Background size for automatic desired area function.
BoundaryID getNextFreeBoundaryID(MeshBase &input_mesh)
Checks input mesh and returns the largest boundary ID in the mesh plus one, which is a boundary ID in...
std::unique_ptr< MeshBase > buildBoundaryLayerRing(MeshGenerator &mg, MeshBase &input_mesh, const std::vector< BoundaryName > &boundary_names, unsigned int num_layers, Real thickness, Real layer_bias, bool outward, const MooseEnum &tri_elem_type, SubdomainID output_subdomain_id, const SubdomainName &output_subdomain_name)
Builds a conformal boundary-layer ring of triangulated annuli along a boundary of an input 2D mesh (o...
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
void ErrorVector unsigned int
auto index_range(const T &sizable)
Real auto_area_function_power
const Elem & get(const ElemType type_in)
const Real _desired_area
Desired (maximum) triangle area.
void addExternalBoundary(MeshBase &mesh, const BoundaryID extern_bid, bool &has_external_bid)
Adds a sideset for the external boundary of the mesh (e.g.