https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SurfaceDelaunayGeneratorBase.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
12#include "libmesh/int_range.h"
13#include "libmesh/parallel_implementation.h"
14#include "libmesh/parallel_algebra.h"
15
16#include <algorithm>
17
20{
22
23 params.addParam<bool>("use_auto_area_func",
24 false,
25 "Use the automatic area function for the triangle meshing region.");
26 params.addParam<Real>(
27 "auto_area_func_default_size",
28 0,
29 "Background size for automatic area function, or 0 to use non background size");
30 params.addParam<Real>("auto_area_func_default_size_dist",
31 -1.0,
32 "Effective distance of background size for automatic area "
33 "function, or negative to use non background size");
34 params.addParam<unsigned int>("auto_area_function_num_points",
35 10,
36 "Maximum number of nearest points used for the inverse distance "
37 "interpolation algorithm for automatic area function calculation.");
38 params.addRangeCheckedParam<Real>(
39 "auto_area_function_power",
40 1.0,
41 "auto_area_function_power>0",
42 "Polynomial power of the inverse distance interpolation algorithm for automatic area "
43 "function calculation.");
44
45 params.addClassDescription("Base class for Delaunay mesh generators applied to a surface.");
46
48 "use_auto_area_func auto_area_func_default_size auto_area_func_default_size_dist "
49 "auto_area_function_num_points auto_area_function_power",
50 "Automatic triangle meshing area control");
51
52 params.addRangeCheckedParam<Real>(
53 "max_angle_deviation",
54 60.0,
55 "max_angle_deviation>0 & max_angle_deviation<90",
56 "Maximum angle deviation from the global average normal vector in the input mesh.");
57 params.addParam<bool>(
58 "verbose", false, "Whether the generator should output additional information");
59 return params;
60}
61
64{
66
67 params.addRequiredParam<MeshGeneratorName>(
68 "boundary",
69 "The input MeshGenerator defining the output outer boundary and required Steiner points.");
70 params.addParam<std::vector<BoundaryName>>(
71 "input_boundary_names", "2D-input-mesh boundaries defining the output mesh outer boundary");
72 params.addParam<std::vector<SubdomainName>>(
73 "input_subdomain_names", "1D-input-mesh subdomains defining the output mesh outer boundary");
74 params.addParam<unsigned int>("add_nodes_per_boundary_segment",
75 0,
76 "How many more nodes to add in each outer boundary segment.");
77 params.addParam<bool>(
78 "refine_boundary", true, "Whether to allow automatically refining the outer boundary.");
79
80 params.addParam<SubdomainName>("output_subdomain_name",
81 "Subdomain name to set on new triangles.");
82
83 params.addParam<BoundaryName>(
84 "output_boundary",
85 "Boundary name to set on new outer boundary. Default ID: 0 if no hole meshes are stitched; "
86 "or maximum boundary ID of all the stitched hole meshes + 1.");
87 params.addParam<std::vector<BoundaryName>>(
88 "hole_boundaries",
89 "Boundary names to set on holes. Default IDs are numbered up from 1 if no hole meshes are "
90 "stitched; or from maximum boundary ID of all the stitched hole meshes + 2.");
91
92 params.addParam<bool>(
93 "verify_holes",
94 true,
95 "Verify holes do not intersect boundary or each other. Asymptotically costly.");
96
97 params.addParam<std::vector<MeshGeneratorName>>(
98 "holes", std::vector<MeshGeneratorName>(), "The MeshGenerators that define mesh holes.");
99 params.addParam<std::vector<bool>>(
100 "stitch_holes", std::vector<bool>(), "Whether to stitch to the mesh defining each hole.");
101 params.addParam<std::vector<bool>>("refine_holes",
102 std::vector<bool>(),
103 "Whether to allow automatically refining each hole boundary.");
104 params.addRangeCheckedParam<Real>(
105 "desired_area",
106 0,
107 "desired_area>=0",
108 "Desired (maximum) triangle area, or 0 to skip uniform refinement");
109 params.addParam<std::string>(
110 "desired_area_func",
111 std::string(),
112 "Desired area as a function of x,y; omit to skip non-uniform refinement");
113
114 return params;
115}
116
118 : MeshGenerator(parameters),
119 _use_auto_area_func(getParam<bool>("use_auto_area_func")),
120 _auto_area_func_default_size(getParam<Real>("auto_area_func_default_size")),
121 _auto_area_func_default_size_dist(getParam<Real>("auto_area_func_default_size_dist")),
122 _auto_area_function_num_points(getParam<unsigned int>("auto_area_function_num_points")),
123 _auto_area_function_power(getParam<Real>("auto_area_function_power")),
124 _max_angle_deviation(getParam<Real>("max_angle_deviation")),
125 _verbose(getParam<bool>("verbose"))
126{
127}
128
129void
131 const std::vector<std::unique_ptr<MeshBase> *> & hole_ptrs) const
132{
133 const auto desired_area = getParam<Real>("desired_area");
134 const auto & desired_area_func = getParam<std::string>("desired_area_func");
135
136 if ((desired_area > 0.0 && !desired_area_func.empty()) ||
137 (desired_area > 0.0 && _use_auto_area_func) ||
138 (!desired_area_func.empty() && _use_auto_area_func))
139 paramError("desired_area_func",
140 "Only one of the three methods ('desired_area', 'desired_area_func', and "
141 "'use_auto_area_func') to set element area limit should be used.");
142
144 if (isParamSetByUser("auto_area_func_default_size") ||
145 isParamSetByUser("auto_area_func_default_size_dist") ||
146 isParamSetByUser("auto_area_function_num_points") ||
147 isParamSetByUser("auto_area_function_power"))
148 paramError("use_auto_area_func",
149 "If this parameter is set to false, the following parameters should not be set: "
150 "'auto_area_func_default_size', 'auto_area_func_default_size_dist', "
151 "'auto_area_function_num_points', 'auto_area_function_power'.");
152
153 const auto & stitch_holes = getParam<std::vector<bool>>("stitch_holes");
154 const auto & refine_holes = getParam<std::vector<bool>>("refine_holes");
155
156 if (!stitch_holes.empty() && stitch_holes.size() != hole_ptrs.size())
157 paramError("stitch_holes", "Need one stitch_holes entry per hole, if specified.");
158
159 for (const auto hole_i : index_range(stitch_holes))
160 if (stitch_holes[hole_i] && (hole_i >= refine_holes.size() || refine_holes[hole_i]))
161 paramError("refine_holes", "Disable auto refine of any hole boundary to be stitched.");
162
163 if (isParamValid("hole_boundaries"))
164 if (getParam<std::vector<BoundaryName>>("hole_boundaries").size() != hole_ptrs.size())
165 paramError("hole_boundaries", "Need one hole_boundaries entry per hole, if specified.");
166}
167
168void
169SurfaceDelaunayGeneratorBase::checkInteriorPoints(const std::vector<Point> & interior_points) const
170{
171 std::vector<Point> sorted_points(interior_points);
172 std::sort(sorted_points.begin(), sorted_points.end());
173 const bool has_duplicates =
174 std::adjacent_find(sorted_points.begin(), sorted_points.end()) != sorted_points.end();
175 if (has_duplicates)
176 paramError("interior_points", "Duplicate points were found in the provided interior points.");
177}
178
179void
182{
183 if (isParamValid("input_boundary_names"))
184 opts.input_boundary_names = getParam<std::vector<BoundaryName>>("input_boundary_names");
185 if (isParamValid("input_subdomain_names"))
186 opts.input_subdomain_names = getParam<std::vector<SubdomainName>>("input_subdomain_names");
187 opts.add_nodes_per_boundary_segment = getParam<unsigned int>("add_nodes_per_boundary_segment");
188 opts.refine_bdy = getParam<bool>("refine_boundary");
189 opts.verify_holes = getParam<bool>("verify_holes");
190 opts.desired_area = getParam<Real>("desired_area");
191 opts.desired_area_func = getParam<std::string>("desired_area_func");
197 opts.stitch_holes = getParam<std::vector<bool>>("stitch_holes");
198 opts.refine_holes = getParam<std::vector<bool>>("refine_holes");
199
200 if (isParamValid("output_subdomain_name"))
201 {
202 opts.has_output_subdomain_name = true;
203 opts.output_subdomain_name = getParam<SubdomainName>("output_subdomain_name");
204 }
205 if (isParamValid("output_boundary"))
206 {
207 opts.has_output_boundary = true;
208 opts.output_boundary = getParam<BoundaryName>("output_boundary");
209 }
210 if (isParamValid("hole_boundaries"))
211 opts.hole_boundaries = getParam<std::vector<BoundaryName>>("hole_boundaries");
212}
213
214Point
216{
217 mooseAssert(elem.n_vertices() == 3 || elem.n_vertices() == 4, "unsupported element type.");
218 // Only the first three vertices are used to calculate the normal vector
219 const Point & p0 = *elem.node_ptr(0);
220 const Point & p1 = *elem.node_ptr(1);
221 const Point & p2 = *elem.node_ptr(2);
222
223 if (elem.n_vertices() == 4)
224 {
225 const Point & p3 = *elem.node_ptr(3);
226 return ((p2 - p0).cross(p3 - p1)).unit();
227 }
228
229 return ((p2 - p1).cross(p0 - p1)).unit();
230}
231
232Point
234{
235 Point mesh_norm = Point(0.0, 0.0, 0.0);
236 Real mesh_area = 0.0;
237
238 // Check all the elements' normal vectors
239 for (const auto & elem : mesh.active_local_element_ptr_range())
240 {
241 const Real elem_area = elem->volume();
242 mesh_norm += elemNormal(*elem) * elem_area;
243 mesh_area += elem_area;
244 }
245 mesh.comm().sum(mesh_norm);
246 mesh.comm().sum(mesh_area);
247 mesh_norm /= mesh_area;
248 return mesh_norm.unit();
249}
250
251Real
253 const Point & global_norm)
254{
255 Real max_deviation(0.0);
256 // Check all the elements' deviation from the global normal vector
257 for (const auto & elem : mesh.active_local_element_ptr_range())
258 {
259 const Real elem_deviation = std::acos(global_norm * elemNormal(*elem)) / M_PI * 180.0;
260 max_deviation = std::max(max_deviation, elem_deviation);
261 if (_verbose && elem_deviation > _max_angle_deviation)
262 _console << "Element " << elem->id() << " from subdomain ID " << elem->subdomain_id()
263 << " has normal deviation: " << elem_deviation << std::endl;
264 }
265 mesh.comm().max(max_deviation);
266 return max_deviation;
267}
InputParameters emptyInputParameters()
void ErrorVector unsigned int
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
MeshGenerators are objects that can modify or add to an existing mesh.
static InputParameters validParams()
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
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.
Definition MooseBase.h:205
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition MooseBase.h:406
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
const bool _verbose
Whether the generator should be verbose.
Real meshNormalDeviation2D(const MeshBase &mesh, const Point &global_norm)
Calculate the maximum deviation of the normal vectors in a given mesh from a global average normal ve...
Point meshNormal2D(const MeshBase &mesh)
Calculate the average normal vector of a 2D mesh based on the normal vectors of its elements using th...
const Real _auto_area_func_default_size_dist
Background size's effective distance for automatic desired area function.
const Real _auto_area_func_default_size
Background size for automatic desired area function.
void checkInteriorPoints(const std::vector< Point > &interior_points) const
Errors if a point was given twice as an interior point, which the triangulation cannot honor.
Point elemNormal(const Elem &elem)
Calculate the normal vector of a 2D element based the first three vertices.
SurfaceDelaunayGeneratorBase(const InputParameters &parameters)
const Real _max_angle_deviation
Max angle deviation from the global average normal vector in the input mesh.
void fillDelaunayOptions(MeshTriangulationUtils::XYDelaunayOptions &opts) const
Fills the triangulation options that follow from the parameters boundaryAndHolesParams() adds,...
const bool _use_auto_area_func
Whether to use automatic desired area function.
const Real _auto_area_function_power
Power of the polynomial used in the inverse distance interpolation for automatic area function.
static InputParameters boundaryAndHolesParams()
The parameters that select the outer boundary to triangulate within and the holes to leave out of the...
void checkBoundaryAndHolesParams(const std::vector< std::unique_ptr< MeshBase > * > &hole_ptrs) const
Errors if the parameters boundaryAndHolesParams() adds contradict each other or the holes they refer ...
const unsigned int _auto_area_function_num_points
Maximum number of points to use for the inverse distance interpolation for automatic area function.
MeshBase & mesh
Bundle of inputs for triangulateWithDelaunay.
std::vector< SubdomainName > input_subdomain_names