16 #include "libmesh/fparser_ad.hh" 17 #include "libmesh/edge_edge2.h" 18 #include "libmesh/edge_edge3.h" 19 #include "libmesh/edge_edge4.h" 32 MooseEnum edge_elem_type(
"EDGE2 EDGE3 EDGE4",
"EDGE2");
34 params.
addRequiredParam<std::string>(
"x_formula",
"Function expression of x(t)");
35 params.
addRequiredParam<std::string>(
"y_formula",
"Function expression of y(t)");
36 params.
addParam<std::string>(
"z_formula",
"0",
"Function expression of z(t)");
40 "Numbers of segments (EDGE elements) of each section of the curve to be generated. The " 41 "number of entries in this parameter should be equal to one less than the number of entries " 42 "in 'section_bounding_t_values'");
44 "section_bounding_t_values",
45 "The 't' values that bound the sections of the curve. Start and end points must be included. " 46 "The number of entries in 'nums_segments' should be equal to one less than the number of " 47 "entries in this parameter.");
48 params.
addParam<std::vector<std::string>>(
49 "constant_names",
"Vector of constants used in the parsed function (use this for kB etc.)");
50 params.
addParam<std::vector<std::string>>(
51 "constant_expressions",
52 "Vector of values for the constants in constant_names (can be an FParser expression)");
53 params.
addParam<
bool>(
"is_closed_loop",
false,
"Whether the curve is closed or not.");
56 "point_overlapping_tolerance>0.0",
57 "The point-to-point distance tolerance that is used to " 58 "determine whether the two points are overlapped.");
60 "forced_closing_num_segments",
61 "forced_closing_num_segments>1",
62 "Number of segments (EDGE elements) of the curve section that is generated to forcefully " 66 "oversample_factor>2.0",
67 "Oversample factor to help make node distance nearly uniform.");
69 "max_oversample_number_factor",
71 "max_oversample_number_factor>100",
72 "For each section of the curve, the maximum number of oversampling points is the product of " 73 "this factor and the number of nodes on the curve.");
74 params.
addParam<std::vector<BoundaryName>>(
75 "edge_nodesets", std::vector<BoundaryName>(),
"Nodesets on both edges of the parsed curves");
77 "edge_element_type", edge_elem_type,
"Type of the EDGE elements to be generated.");
78 params.
addClassDescription(
"This ParsedCurveGenerator object is designed to generate a mesh of a " 79 "curve that consists of EDGE2, EDGE3, or EDGE4 elements.");
87 _function_x(getParam<
std::string>(
"x_formula")),
88 _function_y(getParam<
std::string>(
"y_formula")),
89 _function_z(getParam<
std::string>(
"z_formula")),
90 _nums_segments(getParam<
std::vector<unsigned
int>>(
"nums_segments")),
91 _section_bounding_t_values(getParam<
std::vector<
Real>>(
"section_bounding_t_values")),
92 _is_closed_loop(getParam<bool>(
"is_closed_loop")),
93 _point_overlapping_tolerance(getParam<
Real>(
"point_overlapping_tolerance")),
94 _forced_closing_num_segments(isParamValid(
"forced_closing_num_segments")
95 ? getParam<unsigned
int>(
"forced_closing_num_segments")
97 _oversample_factor(getParam<
Real>(
"oversample_factor")),
98 _max_oversample_number_factor(getParam<unsigned
int>(
"max_oversample_number_factor")),
99 _node_set_boundaries(getParam<
std::vector<BoundaryName>>(
"edge_nodesets")),
100 _order(getParam<
MooseEnum>(
"edge_element_type") ==
"EDGE2" 102 : (getParam<
MooseEnum>(
"edge_element_type") ==
"EDGE3" ? 2 : 3))
106 paramError(
"section_bounding_t_values",
"elements must be unique.");
109 paramError(
"section_bounding_t_values",
"elements must change monotonically.");
113 "The size of this parameter must be one less than size of section_bounding_t_values.");
114 _func_Fx = std::make_shared<SymFunction>();
115 _func_Fy = std::make_shared<SymFunction>();
116 _func_Fz = std::make_shared<SymFunction>();
127 getParam<std::vector<std::string>>(
"constant_names"),
128 getParam<std::vector<std::string>>(
"constant_expressions"));
130 getParam<std::vector<std::string>>(
"constant_names"),
131 getParam<std::vector<std::string>>(
"constant_expressions"));
133 getParam<std::vector<std::string>>(
"constant_names"),
134 getParam<std::vector<std::string>>(
"constant_expressions"));
141 "\nin ParsedCurveGenerator ",
148 "\nin ParsedCurveGenerator ",
155 "\nin ParsedCurveGenerator ",
164 "this parameter is not needed if the curve to be generated is not a closed loop.");
167 paramError(
"edge_nodesets",
"Cannot add more than one edge nodeset on a closed loop");
169 paramError(
"edge_nodesets",
"Exactly two edges in an open loop");
172 std::unique_ptr<MeshBase>
180 std::vector<Real> t_sect_space;
181 std::vector<Real> dis_sect_space;
194 for (
auto & dis_elem : dis_sect_space)
203 std::unique_ptr<LinearInterpolation> linear_t;
206 std::vector<Node *> nodes(
208 for (
unsigned int i = 0; i < nodes.size(); i++)
212 nodes[i] =
mesh->add_point(side_p, i);
222 mesh->delete_node(nodes.back());
223 nodes.resize(nodes.size() - 1);
226 "this parameter is not needed if the first and last points of the curve to be " 227 "generated are overlapped.");
232 const Point start_pt(*nodes.back());
233 const Point end_pt(*nodes.front());
234 const unsigned int num_nodes_0(nodes.size());
237 Point side_p = start_pt + (end_pt - start_pt) * (
Real)i /
239 nodes.push_back(
mesh->add_point(side_p, num_nodes_0 + i - 1));
245 for (
unsigned int i = 0; i < num_elems; i++)
247 std::unique_ptr<Elem> new_elem;
248 new_elem = std::make_unique<Edge2>();
251 new_elem = std::make_unique<Edge3>();
254 new_elem = std::make_unique<Edge4>();
255 new_elem->set_node(3, nodes[i *
_order + 2]);
257 new_elem->set_node(2, nodes[i *
_order + 1]);
259 new_elem->set_node(0, nodes[i *
_order]);
260 new_elem->set_node(1, nodes[((i + 1) *
_order) % nodes.size()]);
262 new_elem->subdomain_id() = 1;
263 mesh->add_elem(std::move(new_elem));
269 BoundaryInfo & boundary_info =
mesh->get_boundary_info();
272 boundary_info.nodeset_name(i++) = side_name;
276 boundary_info.add_node(*(nodes.end() - 1),
286 std::vector<Real> & t_sect_space,
287 std::vector<Real> & dis_sect_space,
288 unsigned int num_segments,
289 const bool is_closed_loop,
290 const Real oversample_factor)
292 std::vector<Point> pt_sect_space;
293 t_sect_space.push_back(t_start);
294 t_sect_space.push_back(t_end);
297 const Real total_distance =
303 "The curve has at least one cross, which is not supported.");
304 const Real target_fine_interval = total_distance / (
Real)num_segments / oversample_factor;
305 unsigned int t_space_id = 0;
306 dis_sect_space.push_back(0.0);
309 unsigned int binary_search_counter(0);
311 while (t_space_id + 1 < t_sect_space.size() && binary_search_counter <= max_binary_search)
313 binary_search_counter++;
314 if (
euclideanDistance(pt_sect_space[t_space_id], pt_sect_space[t_space_id + 1]) >
315 target_fine_interval)
317 const Real new_t_value = (t_sect_space[t_space_id] + t_sect_space[t_space_id + 1]) / 2.0;
318 t_sect_space.insert(t_sect_space.begin() + t_space_id + 1, new_t_value);
319 pt_sect_space.insert(pt_sect_space.begin() + t_space_id + 1,
pointCalculator(new_t_value));
323 dis_sect_space.push_back(
324 dis_sect_space.back() +
329 if (binary_search_counter > max_binary_search)
331 "max_oversample_number_factor",
332 "Maximum oversampling points number has been exceeded. Please consider adding more t " 333 "values into 'section_bounding_t_values' or increase 'max_oversample_number_factor'.");
334 const Real total_dis_seg = dis_sect_space.back();
336 for (
auto & dist : dis_sect_space)
337 dist = dist / total_dis_seg * (
Real)num_segments;
350 return (p1 - p2).norm();
GenericReal< is_ad > evaluate(SymFunctionPtr &, const std::string &object_name="")
Evaluate FParser object and check EvalError.
void addFParserConstants(SymFunctionPtr &parser, const std::vector< std::string > &constant_names, const std::vector< std::string > &constant_expressions) const
add constants (which can be complex expressions) to the parser object
Real euclideanDistance(const Point p1, const Point p2)
Calculates the Euclidean distance between two given points.
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
std::unique_ptr< ReplicatedMesh > buildReplicatedMesh(unsigned int dim=libMesh::invalid_uint)
Build a replicated mesh.
SymFunctionPtr _func_Fy
function parser object describing the y(t)
static constexpr Real TOLERANCE
const std::string _function_x
function expression for x(t)
const bool _is_closed_loop
whether the curve is a closed loop or not
ParsedCurveGenerator(const InputParameters ¶meters)
const Real _oversample_factor
Oversampling factor to help make node distance nearly uniform.
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
SymFunctionPtr _func_Fz
function parser object describing the z(t)
const Real _point_overlapping_tolerance
the point-to-point distance tolerance that is used to determine whether the two points are overlapped...
virtual const std::string & name() const
Get the name of the class.
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
const unsigned int _order
order of the EDGE elements to be generated
static InputParameters validParams()
const std::string _function_z
function expression for z(t)
const std::vector< Real > _section_bounding_t_values
critical t values that define the sections of the curve
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
std::vector< Real > _t_space
t values that are sampled for curve points
constexpr bool is_sorted()
Check if the given index sequence is sorted ()internal function)
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 unsigned int _forced_closing_num_segments
Number of segments of the curve section that is generated to forcefully close the loop...
his ParsedCurveGenerator object is designed to generate a mesh of a curve that consists of EDGE2...
static InputParameters validParams()
Point pointCalculator(const Real t_param)
Calculates the point coordinates {x(t), y(t), 0.0} based on parameter t.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const unsigned int _max_oversample_number_factor
A factor used to calculate the maximum oversampling points number in each section.
const std::vector< unsigned int > _nums_segments
numbers of side segments of each section defined by section_bounding_t_values
std::vector< GenericReal< is_ad > > _func_params
Array to stage the parameters passed to the functions when calling Eval.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
SymFunctionPtr _func_Fx
function parser object describing the x(t)
std::vector< Real > _dis_space
cumulative distances of the curve points from the starting ppint
static InputParameters validParams()
registerMooseObject("MooseApp", ParsedCurveGenerator)
void tSectionSpaceDefiner(const Real t_start, const Real t_end, std::vector< Real > &t_sect_space, std::vector< Real > &dis_sect_space, unsigned int num_segments, const bool is_closed_loop, const Real oversample_factor)
Calculates the oversampled parameter t series and corresponding cumulative distances from the startin...
const std::string _function_y
function expression for y(t)
MeshGenerators are objects that can modify or add to an existing mesh.
void ErrorVector unsigned int
std::vector< BoundaryName > _node_set_boundaries
vector of the names of the boundaries at the ends of the parsed curve
void setParserFeatureFlags(SymFunctionPtr &) const
apply input parameters to internal feature flags of the parser object