82 "pattern_pitch_meta", getMeshProperty<Real>(
"pattern_pitch_meta",
_input_name));
84 auto input_mesh = dynamic_pointer_cast<ReplicatedMesh>(
_mesh);
90 "External boundary does not exist in the input mesh");
91 std::vector<std::tuple<dof_id_type, unsigned short int, boundary_id_type>> side_list =
92 input_mesh->get_boundary_info().build_side_list();
93 input_mesh->get_boundary_info().build_node_list_from_side_list();
94 std::vector<std::tuple<dof_id_type, boundary_id_type>> node_list =
95 input_mesh->get_boundary_info().build_node_list();
97 if (!input_mesh->is_prepared())
98 input_mesh->find_neighbors();
100 const unsigned int n_extra_integer_input = input_mesh->n_elem_integers();
101 std::vector<std::string> extra_integer_names;
102 for (
unsigned int i = 0; i < n_extra_integer_input; i++)
103 extra_integer_names.push_back(input_mesh->get_elem_integer_name(i));
106 std::vector<bool> extra_id_modify_flags = std::vector<bool>(n_extra_integer_input,
false);
107 std::vector<dof_id_type> extra_modify_values = std::vector<dof_id_type>(n_extra_integer_input, 0);
112 "extra_id_names_to_modify",
113 "The parameter contains an extra element integer that does not exist in the input mesh.");
123 std::vector<dof_id_type> bid_elem_list;
124 std::vector<dof_id_type> new_bid_elem_list;
125 std::vector<dof_id_type> ext_node_list;
128 for (
unsigned int i = 0; i < side_list.size(); i++)
133 bid_elem_list.push_back(std::get<0>(side_list[i]));
135 const auto elem_type = input_mesh->elem_ptr(std::get<0>(side_list[i]))->type();
138 "The input mesh has non-QUAD4/QUAD8/QUAD9 elements in its peripheral area, "
139 "which is not supported.");
149 new_bid_elem_list.push_back(input_mesh->elem_ptr(std::get<0>(side_list[i]))
150 ->neighbor_ptr((std::get<1>(side_list[i]) + 2) % 4)
155 auto bid_elem_list_it = std::unique(bid_elem_list.begin(), bid_elem_list.end());
156 auto new_bid_elem_list_it = std::unique(new_bid_elem_list.begin(), new_bid_elem_list.end());
157 bid_elem_list.resize(std::distance(bid_elem_list.begin(), bid_elem_list_it));
158 new_bid_elem_list.resize(std::distance(new_bid_elem_list.begin(), new_bid_elem_list_it));
161 std::vector<std::pair<Point, std::vector<dof_id_type>>> del_elem_extra_ids;
163 for (
unsigned int i = 0; i < bid_elem_list.size(); i++)
165 const auto & tmp_elem_ptr = input_mesh->elem_ptr(bid_elem_list[i]);
169 del_elem_extra_ids.push_back(
170 std::make_pair(tmp_elem_ptr->true_centroid(), std::vector<dof_id_type>()));
171 for (
unsigned int j = 0; j < n_extra_integer_input; j++)
172 del_elem_extra_ids[i].second.push_back(
173 extra_id_modify_flags[j] ? extra_modify_values[j] : tmp_elem_ptr->get_extra_integer(j));
175 input_mesh->delete_elem(tmp_elem_ptr);
179 del_elem_extra_ids.push_back(
182 input_mesh->find_neighbors();
184 BoundaryInfo & boundary_info = input_mesh->get_boundary_info();
185 for (
unsigned int i = 0; i < new_bid_elem_list.size(); i++)
188 for (
unsigned int j = 0; j < input_mesh->elem_ptr(new_bid_elem_list[i])->n_sides(); j++)
190 if (input_mesh->elem_ptr(new_bid_elem_list[i])->neighbor_ptr(j) ==
nullptr)
196 input_mesh->contract();
197 input_mesh->prepare_for_use();
200 auto input_mesh_origin = dynamic_pointer_cast<ReplicatedMesh>(input_mesh->clone());
203 for (
unsigned i_side = 0; i_side <
_num_sides; i_side++)
206 std::vector<Point> inner_pts;
212 MeshTools::Modification::rotate(*input_mesh_origin, -360.0 / (Real)
_num_sides, 0, 0);
216 std::vector<Point> outer_pts;
217 const Point outer_end_1 = Point(pattern_pitch_meta / 2.0,
218 -pattern_pitch_meta / 2.0 * std::tan(M_PI / (Real)
_num_sides),
220 const Point outer_end_2 = Point(pattern_pitch_meta / 2.0,
221 pattern_pitch_meta / 2.0 * std::tan(M_PI / (Real)
_num_sides),
224 const std::vector<Real> input_arg{0.0, 1.0};
225 const std::vector<Real> input_x{outer_end_1(0), outer_end_2(0)};
226 const std::vector<Real> input_y{outer_end_1(1), outer_end_2(1)};
227 std::unique_ptr<LinearInterpolation> linear_outer_x =
228 std::make_unique<LinearInterpolation>(input_arg, input_x);
229 std::unique_ptr<LinearInterpolation> linear_outer_y =
230 std::make_unique<LinearInterpolation>(input_arg, input_y);
235 outer_pts.push_back(Point(linear_outer_x->sample((Real)i / (Real)
_new_num_sector),
258 std::vector<std::pair<Point, Point>> inner_midpts_pairs;
261 auto inner_pts_tmp(inner_pts);
263 for (
const auto i : index_range(inner_pts_tmp))
265 inner_pts.push_back(inner_pts_tmp[i]);
270 const Point avgpt = 0.5 * (inner_pts_tmp[i - 1] + inner_pts_tmp[i + 1]);
271 if (!MooseUtils::absoluteFuzzyEqual((avgpt - inner_pts_tmp[i]).norm(), 0.0))
272 inner_midpts_pairs.push_back(std::make_pair(avgpt, inner_pts_tmp[i]));
274 inner_pts_tmp.clear();
289 mesh->all_second_order();
291 mesh->all_complete_order();
294 if (inner_midpts_pairs.size())
296 mesh->get_boundary_info().build_node_list_from_side_list();
297 auto tl_node_list =
mesh->get_boundary_info().build_node_list();
298 std::vector<dof_id_type> bdry_node_ids;
299 std::vector<Point> bdry_node_pts;
300 for (
const auto & tl_node_tuple : tl_node_list)
304 bdry_node_ids.push_back(std::get<0>(tl_node_tuple));
305 bdry_node_pts.push_back(*(
mesh->node_ptr(std::get<0>(tl_node_tuple))));
308 KDTree ref_kd_tree(bdry_node_pts, 4);
309 for (
const auto & midpt_pair : inner_midpts_pairs)
311 std::vector<std::size_t> nn_id;
313 *(
mesh->node_ptr(bdry_node_ids[nn_id.front()])) = midpt_pair.second;
317 MeshTools::Modification::rotate(*
mesh, (Real)i_side * 360.0 / (Real)
_num_sides, 0, 0);
319 mesh->add_elem_integers(extra_integer_names,
true);
321 mesh->prepare_for_use();