15#include "libmesh/parsed_function.h"
16#include "libmesh/replicated_mesh.h"
17#include "libmesh/face_quad4.h"
18#include "libmesh/fparser_ad.hh"
19#include "libmesh/elem.h"
29 MooseEnum edge_type(
"LINE=1 CIRCARC=2 DISCRETE=3 PARSED=4");
31 params.
addRequiredParam<std::vector<Point>>(
"corners",
"The x,y,z positions of the nodes");
42 "Number of nodes on horizontal edges, including corners");
44 "Number of Nodes on vertical edges, including corners");
47 params.
addParam<std::string>(
"bottom_parameter",
"",
"Bottom side support parameter");
48 params.
addParam<std::string>(
"top_parameter",
"",
"Top side support parameter");
49 params.
addParam<std::string>(
"left_parameter",
"",
"Left side support parameter");
50 params.
addParam<std::string>(
"right_parameter",
"",
"Right side support parameter");
55 "bias_x>=1.0 & bias_x<=2",
56 "The amount by which to grow (or shrink) the cells in the x-direction.");
60 "bias_y>=1.0 & bias_y<=2",
61 "The amount by which to grow (or shrink) the cells in the y-direction.");
64 "Creates a QUAD4 mesh given a set of corner vertices and edge types. "
65 "The edge type can be either LINE, CIRCARC, DISCRETE or PARSED, with "
66 "LINE as the default option. "
67 "For the non-default options the user needs to specify additional "
68 "parameters via the edge_parameter option "
69 "as follows: for CIRCARC the deviation of the midpoint from an "
70 "arccircle, for DISCRETE a set of points, or "
71 "a paramterization via the PARSED option. Opposite edges may have "
72 "different distributions s long as the "
73 "number of points is identical. Along opposite edges a different point "
74 "distribution can be prescribed "
75 "via the options bias_x or bias_y for opposing edges.");
88 _corners(getParam<
std::vector<Point>>(
"corners")),
89 _nx(getParam<unsigned
int>(
"nx")),
90 _ny(getParam<unsigned
int>(
"ny")),
91 _bottom_type(getParam<
MooseEnum>(
"bottom_type")),
92 _top_type(getParam<
MooseEnum>(
"top_type")),
93 _left_type(getParam<
MooseEnum>(
"left_type")),
94 _right_type(getParam<
MooseEnum>(
"right_type")),
95 _bottom_parameter(getParam<
std::string>(
"bottom_parameter")),
96 _top_parameter(getParam<
std::string>(
"top_parameter")),
97 _left_parameter(getParam<
std::string>(
"left_parameter")),
98 _right_parameter(getParam<
std::string>(
"right_parameter")),
99 _bias_x(getParam<Real>(
"bias_x")),
100 _bias_y(getParam<Real>(
"bias_y"))
108 mooseAssert((
_nx > 1) && (
_ny > 1),
109 "A minimum of 2 points is needed on each edge, i.e. the user needs to consider edge "
110 "vertices as well.");
112std::unique_ptr<MeshBase>
117 mesh->set_mesh_dimension(2);
118 mesh->set_spatial_dimension(2);
119 BoundaryInfo & boundary_info =
mesh->get_boundary_info();
130 std::vector<Point> outward_vec(4);
131 outward_vec[0] = Point(0.0, -1.0, 0.0);
132 outward_vec[1] = Point(0.0, 1.0, 0.0);
133 outward_vec[2] = Point(-1.0, 0.0, 0.0);
134 outward_vec[3] = Point(1.0, 0.0, 0.0);
136 const unsigned long int total_nodes =
_nx *
_ny;
139 Real edge_length = 1.0;
143 std::vector<Point> edge_bottom =
145 std::vector<Point> edge_top =
147 std::vector<Point> edge_left =
149 std::vector<Point> edge_right =
154 Real rx_coord, sy_coord;
156 std::vector<Node *> nodes(total_nodes);
157 unsigned int node_id = 0;
160 Real r1_basis, r2_basis, s1_basis, s2_basis;
162 for (
unsigned int idx = 0; idx <
_nx; idx++)
164 rx_coord = param_x_dir[idx];
165 r1_basis = 1 - rx_coord;
168 for (
unsigned int idy = 0; idy <
_ny; idy++)
170 sy_coord = param_y_dir[idy];
171 s1_basis = 1 - sy_coord;
175 newPt = r2_basis * edge_right[idy] + r1_basis * edge_left[idy] + s1_basis * edge_bottom[idx] +
176 s2_basis * edge_top[idx] - r1_basis * s1_basis * V00 - r1_basis * s2_basis * V01 -
177 r2_basis * s1_basis * V10 - r2_basis * s2_basis * V11;
179 nodes[node_id] =
mesh->add_point(newPt, node_id);
184 for (
unsigned int idx = 0; idx <
_nx - 1; idx++)
186 for (
unsigned int idy = 0; idy <
_ny - 1; idy++)
188 Elem * elem =
mesh->add_elem(
new Quad4);
189 elem->set_node(0, nodes[idy + idx *
_ny]);
190 elem->set_node(1, nodes[idy + (idx + 1) *
_ny]);
191 elem->set_node(2, nodes[idy + 1 + (idx + 1) *
_ny]);
192 elem->set_node(3, nodes[idy + 1 + idx *
_ny]);
195 boundary_info.add_side(elem, 0, 0);
198 boundary_info.add_side(elem, 1, 1);
201 boundary_info.add_side(elem, 2, 2);
204 boundary_info.add_side(elem, 3, 3);
208 boundary_info.sideset_name(0) =
"bottom";
209 boundary_info.nodeset_name(0) =
"bottom";
211 boundary_info.sideset_name(1) =
"right";
212 boundary_info.nodeset_name(1) =
"right";
214 boundary_info.sideset_name(2) =
"top";
215 boundary_info.nodeset_name(2) =
"top";
217 boundary_info.sideset_name(3) =
"left";
218 boundary_info.nodeset_name(3) =
"left";
220 mesh->prepare_for_use();
221 return dynamic_pointer_cast<MeshBase>(
mesh);
227 const unsigned int np,
229 const std::string & parameter,
230 const Point & outward,
231 const std::vector<Real> & param_vec)
233 std::vector<Point> edge;
240 mooseAssert(MooseUtils::absoluteFuzzyEqual((edge[0] - P1).norm(), 0.0),
241 "The line does not fit the first vertex on the edge.");
242 mooseAssert(MooseUtils::absoluteFuzzyEqual((edge[np - 1] - P2).norm(), 0.0),
243 "The line does not fit the end vertex on the edge.");
249 mooseAssert(MooseUtils::absoluteFuzzyEqual((edge[0] - P1).norm(), 0.0),
250 "No arccircle parametrization can be found to fit the first vertex on the edge.");
251 mooseAssert(MooseUtils::absoluteFuzzyEqual((edge[np - 1] - P2).norm(), 0.0),
252 "No arccircle parametrization can be found to fit the end vertex on the edge.");
258 mooseAssert(MooseUtils::absoluteFuzzyEqual((edge[0] - P1).norm(), 0.0),
259 "The first discrete point does not fit the corresponding edge vertex."
260 "Note: discrete points need to replicate the edge corners.");
261 mooseAssert(MooseUtils::absoluteFuzzyEqual((edge[np - 1] - P2).norm(), 0.0),
262 "The last discrete point does not fit the corresponding edge vertex."
263 "Note: discrete points need to replicate the edge corners.");
269 mooseAssert(MooseUtils::absoluteFuzzyEqual((edge[0] - P1).norm(), 0.0),
270 "The parametrization does not fit the first vertex on the edge.");
271 mooseAssert(MooseUtils::absoluteFuzzyEqual((edge[np - 1] - P2).norm(), 0.0),
272 "The parametrization does not fit the end vertex on the edge.");
276 if (edge.size() != np)
277 mooseError(
"The generated edge does not match the number of points on the"
285 const std::vector<Real> & param_vec)
287 std::vector<Point> edge(param_vec.size());
290 for (
auto rx : param_vec)
292 edge[it] = P1 * (1.0 - rx) + P2 * rx;
300 const std::vector<Real> & param_vec)
302 std::vector<Point> edge(param_vec.size());
303 Real x_coord, y_coord;
305 std::vector<std::string> param_coords;
309 for (
auto rx : param_vec)
315 edge[it] = Point(x_coord, y_coord, 0.0);
325 std::vector<Point> edge(np);
326 std::vector<std::string> string_points;
328 if (string_points.size() != np)
329 mooseError(
"DISCRETE: the number of discrete points does not match the number of points on the"
333 for (
unsigned int iter = 0; iter < string_points.size(); iter++)
335 std::vector<Real> point_vals;
337 edge[it] = Point(point_vals[0], point_vals[1], point_vals[2]);
347 const std::string & parameter,
348 const Point & outward,
349 const std::vector<Real> & param_vec)
351 std::vector<Point> edge(param_vec.size());
353 std::vector<Real> param_coords;
356 if (param_coords.size() == 1)
362 P3 = Point(param_coords[0], param_coords[1], param_coords[2]);
369 Point x0 = (P1 - P0);
370 Point x1 = (P2 - P0);
375 mooseAssert(x0.norm() > 0.0 && x1.norm() > 0.0,
376 "The point provided cannot generate an arc circle on the edge specified");
378 Real arclength = std::acos((x0 * x1) / x0.norm() / x1.norm());
380 Real a = std::atan2(x0(1), x0(0));
381 Real b = std::atan2(x1(1), x1(0));
385 if (std::abs(b - a) > M_PI)
389 for (
auto rx : param_vec)
392 Real x = P0(0) + rad * std::cos(interval);
393 Real y = P0(1) + rad * std::sin(interval);
394 edge[it] = Point(x, y, 0.0);
403 const Real xab,
const Real a,
const Real b,
const Real c,
const Real d)
const
406 mooseAssert(std::abs(b - a) > 0.0,
407 "The input interval [a, b] is empty, check that a and b are not identical.");
408 Real xcd = c + (d - c) / (b - a) * (xab - a);
415 const unsigned int np,
416 const Real bias)
const
418 std::vector<Real> param_vec;
424 Real factor = edge_length * (1.0 - std::abs(bias)) / (1.0 -
std::pow(std::abs(bias), np - 1));
425 param_vec.push_back(rx);
426 for (
unsigned int iter = 1; iter < np; iter++)
428 step = step + factor *
std::pow(bias, Real(iter - 1));
430 param_vec.push_back(rx);
435 const Real interval = edge_length / Real(np - 1);
436 for (
unsigned int iter = 0; iter < np; iter++)
438 rx =
getMapInterval(Real(iter) * interval, 0.0, edge_length, 0.0, 1.0);
439 param_vec.push_back(rx);
448 Point temp1 = P1 - P2;
449 Real a2 = temp1.norm_sq();
450 Point temp2 = P3 - P1;
451 Real b2 = temp2.norm_sq();
452 Real dr = std::sqrt(b2 - a2 / 4.0);
453 const Real rad = a2 / 8.0 / dr + dr / 2.0;
461 const Real a1 = (2 * P3(0) - 2 * P1(0));
462 const Real a2 = (2 * P3(1) - 2 * P1(1));
463 const Real A = P3(1) * P3(1) - P1(0) * P1(0) + P3(0) * P3(0) - P1(1) * P1(1);
464 const Real b1 = (2 * P3(0) - 2 * P2(0));
465 const Real b2 = (2 * P3(1) - 2 * P2(1));
466 const Real
B = P3(1) * P3(1) - P2(0) * P2(0) + P3(0) * P3(0) - P2(1) * P2(1);
467 mooseAssert(std::abs(b2) > 0.0 && std::abs(a1) > 0.0 && std::abs(a1 * b2 - a2 * b1) > 0.0,
468 "The point provided cannot generate an arc circle on the edge specified."
469 "The origin of the corresponding circle cannot be computed.");
471 const Real y0 = (a1 *
B - A * b1) / (a1 * b2 - a2 * b1);
472 const Real x0 = (A - y0 * a2) / a1;
475 Point P0 = Point(x0, y0, 0.0);
483 const Point & outward)
const
485 const Real xm = (P1(0) + P2(0)) / 2;
486 const Real ym = (P1(1) + P2(1)) / 2;
491 const Real dist = std::abs(height);
492 const int orient = (height >= 0) ? 1 : -1;
496 if ((std::abs(P2(0) - P1(0)) < 1e-15) || (std::abs(P2(1) - P1(1)) < 1e-15))
497 MidPoint = Point(xm, ym, 0.0) + dist * orient * outward;
501 if (std::abs(P2(0) - P1(0)) > 1e-15 && std::abs(P2(1) - P1(1)) > 1e-15)
504 const Real m = -(P2(0) - P1(0)) / (P2(1) - P1(1));
506 const Real x_temp = dist * sqrt((m * m + 1)) / (m * m + 1);
507 const Real factor = orient * outward(0) + m * orient * outward(1);
508 int direction = (factor >= 0) ? 1 : -1;
510 MidPoint = Point(direction * x_temp + xm, direction * x_temp * m + ym, 0.0);
registerMooseObject("MooseApp", TransfiniteMeshGenerator)
void ErrorVector unsigned int
std::vector< GenericReal< is_ad > > _func_params
Array to stage the parameters passed to the functions when calling Eval.
void setParserFeatureFlags(SymFunctionPtr &) const
apply input parameters to internal feature flags of the parser object
static InputParameters validParams()
MeshGenerators are objects that can modify or add to an existing mesh.
static InputParameters validParams()
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
Build a MeshBase object whose underlying type will be determined by the Mesh input file block.
const std::string & type() const
Get the type of this class.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Generates an quadrilateral given all the parameters.
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
const MooseEnum _bottom_type
std::vector< Point > getEdge(const Point &P1, const Point &P2, const unsigned int np, const MooseEnum &type, const std::string ¶meter, const Point &outward, const std::vector< Real > ¶m_vec)
Real computeRadius(const Point &P1, const Point &P2, const Point &P3) const
std::vector< Point > getCircarcEdge(const Point &P1, const Point &P2, const std::string ¶meter, const Point &outward, const std::vector< Real > ¶m_vec)
static InputParameters validParams()
Real getMapInterval(const Real xab, const Real a, const Real b, const Real c, const Real d) const
Point computeOrigin(const Point &P1, const Point &P2, const Point &P3) const
const std::string _right_parameter
const std::vector< Point > & _corners
const std::string _left_parameter
const std::string _bottom_parameter
std::vector< Point > getLineEdge(const Point &P1, const Point &P2, const std::vector< Real > ¶m_vec)
Point computeMidPoint(const Point &P1, const Point &P2, const Real dist, const Point &outward) const
std::vector< Point > getParsedEdge(const std::string ¶meter, const std::vector< Real > ¶m_vec)
std::vector< Real > getPointsDistribution(const Real edge_length, const unsigned int np, const Real bias) const
const MooseEnum _top_type
const MooseEnum _left_type
const std::string _top_parameter
const MooseEnum _right_type
SymFunctionPtr _parsed_func
function parser object describing the combinatorial geometry
TransfiniteMeshGenerator(const InputParameters ¶meters)
std::vector< Point > getDiscreteEdge(const unsigned int np, const std::string ¶meter)
bool tokenizeAndConvert(const std::string &str, std::vector< T > &tokenized_vector, const std::string &delimiter=" \t\n\v\f\r")
tokenizeAndConvert splits a string using delimiter and then converts to type T.
void tokenize(const std::string &str, std::vector< T > &elements, unsigned int min_len=1, const std::string &delims="/")
This function will split the passed in string on a set of delimiters appending the substrings to the ...
MooseUnits pow(const MooseUnits &, int)