17 #include "libmesh/int_range.h" 18 #include "libmesh/mesh_base.h" 19 #include "libmesh/mesh_generation.h" 20 #include "libmesh/mesh_serializer.h" 21 #include "libmesh/point.h" 22 #include "libmesh/elem.h" 23 #include "libmesh/node.h" 24 #include "libmesh/face_tri3.h" 25 #include "libmesh/face_quad4.h" 33 const std::vector<Point> & boundary_points_vec_1,
34 const std::vector<Point> & boundary_points_vec_2,
35 const unsigned int num_layers,
41 const std::string type,
42 const std::string name,
44 const Real bias_parameter,
48 boundary_points_vec_1,
Point(0.0, 0.0, 1.0),
Point(0.0, 0.0, 0.0)) ||
50 boundary_points_vec_2,
Point(0.0, 0.0, 1.0),
Point(0.0, 0.0, 0.0)))
55 ", the input vectors of points for " 56 "FillBetweenPointVectorsTools::fillBetweenPointVectorsGenerator " 57 "must be in XY plane.");
59 const unsigned int vec_1_node_num = boundary_points_vec_1.size();
60 const unsigned int vec_2_node_num = boundary_points_vec_2.size();
62 if (vec_1_node_num < 2 || vec_2_node_num < 2)
67 ", the two input vectors of points for " 68 "FillBetweenPointVectorsTools::fillBetweenPointVectorsGenerator " 69 "must respectively contain at least two elements.");
71 if (quad_elem && boundary_points_vec_1.size() != boundary_points_vec_2.size())
76 ", QUAD4 elements option can only be selected when the two input vectors of Points " 77 "have the same length. In the current instance, the first vector has ",
78 boundary_points_vec_1.size(),
79 " points and the second ",
80 boundary_points_vec_2.size(),
83 std::vector<Point> possibly_reoriented_boundary_points_vec_2;
84 const std::vector<Point> * oriented_boundary_points_vec_2 = &boundary_points_vec_2;
86 if (
needFlip(boundary_points_vec_1, boundary_points_vec_2))
88 possibly_reoriented_boundary_points_vec_2.assign(boundary_points_vec_2.rbegin(),
89 boundary_points_vec_2.rend());
90 oriented_boundary_points_vec_2 = &possibly_reoriented_boundary_points_vec_2;
102 std::vector<Real> vec_1_index;
103 std::vector<Real> vec_2_index;
105 std::vector<Real> wt_1;
106 std::vector<Real> index_1;
107 std::vector<Real> wt_2;
108 std::vector<Real> index_2;
111 std::unique_ptr<LinearInterpolation> linear_vec_1_x;
112 std::unique_ptr<LinearInterpolation> linear_vec_1_y;
113 std::unique_ptr<SplineInterpolation> spline_vec_1_l;
114 std::unique_ptr<LinearInterpolation> linear_vec_2_x;
115 std::unique_ptr<LinearInterpolation> linear_vec_2_y;
116 std::unique_ptr<SplineInterpolation> spline_vec_2_l;
119 boundary_points_vec_1,
128 *oriented_boundary_points_vec_2,
141 std::vector<unsigned int> node_number_vec;
143 std::vector<std::vector<Node *>> nodes(num_layers + 1);
145 unsigned int node_counter = 0;
147 for (
const auto i :
make_range(num_layers + 1))
150 node_number_vec.push_back(
153 nodes[i] = std::vector<Node *>(node_number_vec[i]);
156 std::vector<Real> weighted_surrogate_index_1;
157 std::vector<Real> unweighted_surrogate_index_1;
160 unweighted_surrogate_index_1,
168 std::vector<Real> weighted_surrogate_index_2;
169 std::vector<Real> unweighted_surrogate_index_2;
172 unweighted_surrogate_index_2,
179 for (
const auto j :
make_range(node_number_vec[i]))
182 Point surrogate_pos_1 =
Point(linear_vec_1_x->sample(weighted_surrogate_index_1[j]),
183 linear_vec_1_y->sample(weighted_surrogate_index_1[j]),
186 Point surrogate_pos_2 =
Point(linear_vec_2_x->sample(weighted_surrogate_index_2[j]),
187 linear_vec_2_y->sample(weighted_surrogate_index_2[j]),
189 const Real l_ratio = bias_parameter <= 0.0
190 ?
std::pow(spline_vec_2_l->sample(weighted_surrogate_index_2[j]) /
191 spline_vec_1_l->sample(weighted_surrogate_index_1[j]),
192 1.0 / ((
Real)num_layers - 1.0))
194 const Real index_factor =
198 Point tmp_point = surrogate_pos_2 * index_factor + surrogate_pos_1 * (1.0 - index_factor);
201 node_counter += node_number_vec[i];
212 begin_side_boundary_id,
213 end_side_boundary_id);
222 begin_side_boundary_id,
223 end_side_boundary_id);
228 const std::vector<Point> & boundary_points_vec_1,
229 const std::vector<Point> & boundary_points_vec_2,
230 const unsigned int num_layers,
233 const std::string type,
234 const std::string name,
235 const bool quad_elem)
238 boundary_points_vec_1,
239 boundary_points_vec_2,
242 external_boundary_id,
243 external_boundary_id,
244 external_boundary_id,
245 external_boundary_id,
253 const std::vector<std::vector<Node *>> & nodes,
254 const unsigned int num_layers,
255 const std::vector<unsigned int> & node_number_vec,
262 const unsigned int node_number = node_number_vec.front();
266 for (
unsigned int j = 1; j < node_number; j++)
274 transition_layer_id);
276 boundary_info.
add_side(elem, is_elem_flip ? 0 : 3, input_boundary_1_id);
277 if (i == num_layers - 1)
278 boundary_info.
add_side(elem, is_elem_flip ? 2 : 1, input_boundary_2_id);
280 boundary_info.
add_side(elem, is_elem_flip ? 3 : 0, begin_side_boundary_id);
281 if (j == node_number - 1)
282 boundary_info.
add_side(elem, is_elem_flip ? 1 : 2, end_side_boundary_id);
288 const std::vector<std::vector<Node *>> & nodes,
289 const unsigned int num_layers,
290 const std::vector<unsigned int> & node_number_vec,
301 unsigned int nodes_up_it = 0;
302 unsigned int nodes_down_it = 0;
303 const unsigned int node_number_up = node_number_vec[i + 1];
304 const unsigned int node_number_down = node_number_vec[i];
306 while (nodes_up_it < node_number_up - 1 && nodes_down_it < node_number_down - 1 &&
307 nodes_up_it + nodes_down_it < node_number_up + node_number_down - 3)
310 Real dis1 = (*nodes[i + 1][nodes_up_it] - *nodes[i][nodes_down_it + 1]).
norm();
311 Real dis2 = (*nodes[i + 1][nodes_up_it + 1] - *nodes[i][nodes_down_it]).
norm();
316 nodes[i + 1][nodes_up_it],
317 nodes[i][nodes_down_it],
318 nodes[i + 1][nodes_up_it + 1],
319 transition_layer_id);
320 if (i == num_layers - 1)
321 boundary_info.
add_side(elem, is_elem_flip ? 0 : 2, input_boundary_2_id);
322 if (nodes_up_it == 0 && nodes_down_it == 0)
323 boundary_info.
add_side(elem, is_elem_flip ? 2 : 0, begin_side_boundary_id);
330 nodes[i + 1][nodes_up_it],
331 nodes[i][nodes_down_it],
332 nodes[i][nodes_down_it + 1],
333 transition_layer_id);
335 boundary_info.
add_side(elem, 1, input_boundary_1_id);
336 if (nodes_up_it == 0 && nodes_down_it == 0)
337 boundary_info.
add_side(elem, is_elem_flip ? 2 : 0, begin_side_boundary_id);
342 while (nodes_up_it < node_number_up - 1)
346 nodes[i + 1][nodes_up_it],
347 nodes[i][nodes_down_it],
348 nodes[i + 1][nodes_up_it + 1],
349 transition_layer_id);
351 if (i == num_layers - 1)
352 boundary_info.
add_side(elem, is_elem_flip ? 0 : 2, input_boundary_2_id);
353 if (nodes_up_it == node_number_up - 1 && nodes_down_it == node_number_down - 1)
354 boundary_info.
add_side(elem, 1, end_side_boundary_id);
356 while (nodes_down_it < node_number_down - 1)
360 nodes[i + 1][nodes_up_it],
361 nodes[i][nodes_down_it],
362 nodes[i][nodes_down_it + 1],
363 transition_layer_id);
366 boundary_info.
add_side(elem, 1, input_boundary_1_id);
367 if (nodes_up_it == node_number_up - 1 && nodes_down_it == node_number_down - 1)
368 boundary_info.
add_side(elem, is_elem_flip ? 0 : 2, end_side_boundary_id);
375 const std::vector<Point> & boundary_points_vec,
376 std::vector<Real> & vec_index,
377 std::vector<Real> & wt,
378 std::vector<Real> & index,
380 std::unique_ptr<LinearInterpolation> & linear_vec_x,
381 std::unique_ptr<LinearInterpolation> & linear_vec_y,
382 std::unique_ptr<SplineInterpolation> & spline_vec_l)
384 std::vector<Real> pos_x;
385 std::vector<Real> pos_y;
386 std::vector<Real> dist_vec;
387 std::vector<Real> pos_l;
393 vec_index.push_back((
Real)i / ((
Real)vec_node_num - 1.0));
395 pos_x.push_back(boundary_points_vec[i](0));
396 pos_y.push_back(boundary_points_vec[i](1));
400 wt.push_back((boundary_points_vec[i] - boundary_points_vec[i - 1]).
norm());
401 dist_vec.push_back(wt.back());
404 index.push_back(std::accumulate(wt.begin(), wt.end(), 0.0));
406 const Real dist_vec_total = index.back();
407 const Real wt_norm_factor = dist_vec_total / ((
Real)vec_node_num - 1.0);
410 wt.begin(), wt.end(), wt.begin(), [wt_norm_factor](
Real & c) {
return c / wt_norm_factor; });
411 std::transform(index.begin(),
414 [dist_vec_total](
Real & c) {
return c / dist_vec_total; });
418 Real gaussian_factor(0.0);
421 for (
const auto j :
make_range(vec_node_num - 1))
424 const Real tmp_factor =
425 exp(-((
Real)(i - j) - 0.5) * ((
Real)(i - j) - 0.5) / 2.0 / sigma / sigma);
426 gaussian_factor += tmp_factor;
427 sum_tmp += tmp_factor * dist_vec[j];
429 pos_l.push_back(sum_tmp / gaussian_factor);
432 linear_vec_x = std::make_unique<LinearInterpolation>(index, pos_x);
433 linear_vec_y = std::make_unique<LinearInterpolation>(index, pos_y);
434 spline_vec_l = std::make_unique<SplineInterpolation>(index, pos_l);
439 std::vector<Real> & unweighted_surrogate_index,
440 const std::vector<unsigned int> & node_number_vec,
441 const std::vector<Real> & wt,
442 const std::vector<Real> & index,
443 const unsigned int boundary_node_num,
444 const unsigned int i)
447 weighted_surrogate_index.push_back(0.0);
448 unweighted_surrogate_index.push_back(0.0);
449 for (
unsigned int j = 1; j < node_number_vec[i]; j++)
452 unweighted_surrogate_index.push_back((
Real)j / ((
Real)node_number_vec[i] - 1.0));
455 std::upper_bound(index.begin(), index.end(), unweighted_surrogate_index[j - 1]);
457 const auto it_1 = std::lower_bound(index.begin(), index.end(), unweighted_surrogate_index[j]);
459 const auto it_dist = std::distance(it_0, it_1);
461 const auto it_start = std::distance(index.begin(), it_0);
464 weighted_surrogate_index.push_back(weighted_surrogate_index[j - 1] +
465 wt[it_start - 1] / ((
Real)node_number_vec[i] - 1.0));
468 weighted_surrogate_index.push_back(weighted_surrogate_index[j - 1]);
469 weighted_surrogate_index[j] += (*it_0 - unweighted_surrogate_index[j - 1]) * wt[it_start - 1];
470 weighted_surrogate_index[j] +=
471 (unweighted_surrogate_index[j] - *(it_1 - 1)) * wt[it_start + it_dist - 1];
472 for (
unsigned int k = 1; k < it_dist; k++)
473 weighted_surrogate_index[j] += wt[it_start + k - 1] / ((
Real)boundary_node_num - 1.0);
479 needFlip(
const std::vector<Point> & vec_pts_1,
const std::vector<Point> & vec_pts_2)
482 acos((vec_pts_1.back() - vec_pts_1.front()) * (vec_pts_2.front() - vec_pts_1.front()) /
483 (vec_pts_1.back() - vec_pts_1.front()).
norm() /
484 (vec_pts_2.front() - vec_pts_1.front()).
norm());
485 const Real th2 = acos(
486 (vec_pts_2.back() - vec_pts_1.back()) * (vec_pts_1.front() - vec_pts_1.back()) /
487 (vec_pts_2.back() - vec_pts_1.back()).
norm() / (vec_pts_1.front() - vec_pts_1.back()).
norm());
488 const Real th3 = acos(
489 (vec_pts_2.front() - vec_pts_2.back()) * (vec_pts_1.back() - vec_pts_2.back()) /
490 (vec_pts_2.front() - vec_pts_2.back()).
norm() / (vec_pts_1.back() - vec_pts_2.back()).
norm());
492 acos((vec_pts_1.front() - vec_pts_2.front()) * (vec_pts_2.back() - vec_pts_2.front()) /
493 (vec_pts_1.front() - vec_pts_2.front()).
norm() /
494 (vec_pts_2.back() - vec_pts_2.front()).
norm());
502 Real & max_node_radius,
503 std::vector<dof_id_type> & boundary_ordered_node_list,
504 const Point origin_pt,
511 max_node_radius = 0.0;
514 std::vector<std::pair<dof_id_type, dof_id_type>> boundary_node_assm;
515 std::vector<dof_id_type> boundary_midpoint_node_list;
518 if (std::get<2>(side_list_tmp[i]) == bid)
521 const auto elem =
mesh.
elem_ptr(std::get<0>(side_list_tmp[i]));
522 const auto side = elem->
side_ptr(std::get<1>(side_list_tmp[i]));
523 boundary_node_assm.push_back(std::make_pair(side->node_id(0), side->node_id(1)));
525 const auto & side_type = elem->side_type(std::get<1>(side_list_tmp[i]));
526 if (side_type ==
EDGE3)
527 boundary_midpoint_node_list.push_back(
528 elem->node_id(elem->n_vertices() + std::get<1>(side_list_tmp[i])));
536 boundary_ordered_node_list,
538 boundary_midpoint_node_list,
542 return is_closed_loop;
547 Real & max_node_radius,
548 const Point origin_pt,
551 std::vector<dof_id_type> dummy_boundary_ordered_node_list;
553 mesh, max_node_radius, dummy_boundary_ordered_node_list, origin_pt, bid);
559 Real dummy_max_node_radius;
565 Real & max_node_radius,
566 std::vector<dof_id_type> & boundary_ordered_node_list,
567 const Point origin_pt,
576 if (((std::string)e.
what())
577 .compare(
"This mesh generator does not work for the provided external boundary as it " 578 "is not a closed loop.") != 0)
579 throw MooseException(
"The provided boundary is not an open single-segment boundary.");
584 throw MooseException(
"The provided boundary is closed loop, which is not supported.");
600 if (std::get<2>(side_list[i]) == bid)
610 Real & max_node_radius,
611 std::vector<dof_id_type> & ordered_node_list,
612 const Point origin_pt)
618 max_node_radius = 0.0;
619 std::vector<std::pair<dof_id_type, dof_id_type>> node_assm;
620 for (
auto it =
mesh.active_elements_begin(); it !=
mesh.active_elements_end(); it++)
621 node_assm.push_back(std::make_pair((*it)->node_id(0), (*it)->node_id(1)));
624 mesh, max_node_radius, ordered_node_list, node_assm, origin_pt,
"curve", is_closed_loop);
625 return is_closed_loop;
631 std::vector<dof_id_type> dummy_ordered_node_list;
638 Real dummy_max_node_radius;
644 Real & max_node_radius,
645 std::vector<dof_id_type> & ordered_node_list,
646 const Point origin_pt)
654 if (((std::string)e.
what())
655 .compare(
"This mesh generator does not work for the provided curve as it is not a " 656 "closed loop.") != 0)
657 throw MooseException(
"The provided curve is not an open single-segment boundary.");
661 throw MooseException(
"The provided curve is closed loop, which is not supported.");
667 Real & max_node_radius,
668 std::vector<dof_id_type> & ordered_node_list,
669 std::vector<std::pair<dof_id_type, dof_id_type>> & node_assm,
670 std::vector<dof_id_type> & midpoint_node_list,
671 const Point origin_pt,
672 const std::string input_type,
673 bool & is_closed_loop,
674 const bool suppress_exception)
680 std::vector<dof_id_type> dummy_elem_list = std::vector<dof_id_type>(node_assm.size(), 0);
681 std::vector<dof_id_type> ordered_dummy_elem_list;
682 is_closed_loop =
false;
684 node_assm, dummy_elem_list, midpoint_node_list, ordered_node_list, ordered_dummy_elem_list);
688 if (ordered_node_list.front() != ordered_node_list.back())
691 if (!suppress_exception)
692 throw MooseException(
"This mesh generator does not work for the provided ",
694 " as it is not a closed loop.");
702 std::vector<Real> ordered_node_azi_list;
703 for (
const auto i :
make_range(ordered_node_list.size() - 1))
705 ordered_node_azi_list.push_back(
707 .cross(*
mesh.
node_ptr(ordered_node_list[i + 1]) - origin_pt)(2));
712 std::sort(ordered_node_azi_list.begin(), ordered_node_azi_list.end());
713 if (ordered_node_azi_list.front() * ordered_node_azi_list.back() < 0.0)
716 if (!suppress_exception)
718 "This mesh generator does not work for the provided ",
720 " as azimuthal angles of consecutive nodes do not change monotonically.");
723 is_closed_loop =
true;
729 Real & max_node_radius,
730 std::vector<dof_id_type> & ordered_node_list,
731 std::vector<std::pair<dof_id_type, dof_id_type>> & node_assm,
732 const Point origin_pt,
733 const std::string input_type,
734 bool & is_closed_loop,
735 const bool suppress_exception)
742 dummy_midpoint_node_list,
760 if (((*nd_1 - *nd_0).cross((*nd_2 - *nd_0)).unit())(2) > 0)
785 if (((*nd_1 - *nd_0).cross((*nd_2 - *nd_0)).unit())(2) > 0)
std::string name(const ElemQuality q)
void makeOrderedNodeList(std::vector< std::pair< dof_id_type, dof_id_type >> &node_assm, std::vector< dof_id_type > &elem_id_list, std::vector< dof_id_type > &midpoint_node_list, std::vector< dof_id_type > &ordered_node_list, std::vector< dof_id_type > &ordered_elem_id_list)
Convert a list of sides in the form of a vector of pairs of node ids into a list of ordered nodes bas...
virtual Node *& set_node(const unsigned int i)
constexpr auto increment(std::index_sequence< first, tail... >)
Increment the first number in an index sequence, but roll over into the next number if it reaches Nma...
virtual const char * what() const
Get out the error message.
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.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
const BoundaryInfo & get_boundary_info() const
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
auto max(const L &left, const R &right)
void build_side_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &side_list, std::vector< boundary_id_type > &bc_id_list) const
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true)=0
virtual Elem * add_elem(Elem *e)=0
static const dof_id_type invalid_id
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...
virtual const Elem * elem_ptr(const dof_id_type i) const=0
const Elem * neighbor_ptr(unsigned int i) const
Provides a way for users to bail out of the current solve.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
subdomain_id_type subdomain_id() const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
IntRange< T > make_range(T beg, T end)
virtual const Node * node_ptr(const dof_id_type i) const=0
MooseUnits pow(const MooseUnits &, int)
auto index_range(const T &sizable)
bool absoluteFuzzyGreaterThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether a variable is greater than another variable within an absolute tolerance...