Line data Source code
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 :
10 : #include "ConcentricCircleMeshGenerator.h"
11 : #include "CastUniquePointer.h"
12 : #include "libmesh/replicated_mesh.h"
13 : #include "libmesh/face_quad4.h"
14 : #include "libmesh/mesh_modification.h"
15 : #include "libmesh/serial_mesh.h"
16 : #include "libmesh/boundary_info.h"
17 : #include "libmesh/utility.h"
18 : #include "libmesh/mesh_smoother_laplace.h"
19 :
20 : // C++ includes
21 : #include <cmath> // provides round, not std::round (see http://www.cplusplus.com/reference/cmath/round/)
22 :
23 : registerMooseObject("MooseApp", ConcentricCircleMeshGenerator);
24 :
25 : InputParameters
26 14743 : ConcentricCircleMeshGenerator::validParams()
27 : {
28 14743 : InputParameters params = MeshGenerator::validParams();
29 : MooseEnum portion(
30 : "full top_right top_left bottom_left bottom_right right_half left_half top_half bottom_half",
31 14743 : "full");
32 14743 : params.addRequiredParam<unsigned int>("num_sectors",
33 : "num_sectors % 2 = 0, num_sectors > 0"
34 : "Number of azimuthal sectors in each quadrant"
35 : "'num_sectors' must be an even number.");
36 14743 : params.addRequiredParam<std::vector<Real>>("radii", "Radii of major concentric circles");
37 14743 : params.addRequiredParam<std::vector<unsigned int>>(
38 : "rings", "Number of rings in each circle or in the enclosing square");
39 14743 : params.addRequiredParam<bool>(
40 : "has_outer_square",
41 : "It determines if meshes for a outer square are added to concentric circle meshes.");
42 44229 : params.addRangeCheckedParam<Real>(
43 : "pitch",
44 29486 : 0.0,
45 : "pitch>=0.0",
46 : "The enclosing square can be added to the completed concentric circle mesh."
47 : "Elements are quad meshes.");
48 14743 : params.addParam<MooseEnum>("portion", portion, "Control of which part of mesh is created");
49 14743 : params.addRequiredParam<bool>(
50 : "preserve_volumes", "Volume of concentric circles can be preserved using this function.");
51 14743 : params.addParam<unsigned int>("smoothing_max_it", 1, "Number of Laplacian smoothing iterations");
52 14743 : params.addClassDescription(
53 : "This ConcentricCircleMeshGenerator source code is to generate concentric "
54 : "circle meshes.");
55 :
56 29486 : return params;
57 14743 : }
58 :
59 220 : ConcentricCircleMeshGenerator::ConcentricCircleMeshGenerator(const InputParameters & parameters)
60 : : MeshGenerator(parameters),
61 220 : _num_sectors(getParam<unsigned int>("num_sectors")),
62 220 : _radii(getParam<std::vector<Real>>("radii")),
63 220 : _rings(getParam<std::vector<unsigned int>>("rings")),
64 220 : _has_outer_square(getParam<bool>("has_outer_square")),
65 220 : _pitch(getParam<Real>("pitch")),
66 220 : _preserve_volumes(getParam<bool>("preserve_volumes")),
67 220 : _smoothing_max_it(getParam<unsigned int>("smoothing_max_it")),
68 440 : _portion(getParam<MooseEnum>("portion"))
69 : {
70 220 : declareMeshProperty("use_distributed_mesh", false);
71 :
72 220 : if (_num_sectors % 2 != 0)
73 0 : paramError("num_sectors", "must be an even number.");
74 :
75 : // radii data check
76 558 : for (unsigned i = 0; i < _radii.size() - 1; ++i)
77 : {
78 338 : if (_radii[i] == 0.0)
79 0 : paramError("radii", "must be positive numbers.");
80 338 : if (_radii[i] > _radii[i + 1])
81 0 : paramError("radii",
82 : "must be provided in order by starting with the smallest radius providing the "
83 : "following gradual radii.");
84 : }
85 :
86 : // size of 'rings' check
87 220 : if (_has_outer_square)
88 : {
89 106 : if (_rings.size() != _radii.size() + 1)
90 0 : paramError("rings", "The size of 'rings' must be equal to the size of 'radii' plus 1.");
91 : }
92 : else
93 : {
94 114 : if (_rings.size() != _radii.size())
95 0 : paramError("rings", "The size of 'rings' must be equal to the size of 'radii'.");
96 : }
97 : // pitch / 2 must be bigger than any raddi.
98 220 : if (_has_outer_square)
99 454 : for (unsigned i = 0; i < _radii.size(); ++i)
100 348 : if (_pitch / 2 < _radii[i])
101 0 : paramError("pitch", "The pitch / 2 must be larger than any radii.");
102 220 : }
103 :
104 : std::unique_ptr<MeshBase>
105 218 : ConcentricCircleMeshGenerator::generate()
106 : {
107 218 : auto mesh = buildReplicatedMesh(2);
108 218 : BoundaryInfo & boundary_info = mesh->get_boundary_info();
109 :
110 : // Creating real mesh concentric circles
111 : // i: index for _rings, j: index for _radii
112 218 : std::vector<Real> total_concentric_circles;
113 218 : unsigned int j = 0;
114 766 : while (j < _radii.size())
115 : {
116 548 : unsigned int i = 0;
117 548 : if (j == 0)
118 582 : while (i < _rings[j])
119 : {
120 364 : total_concentric_circles.push_back(_radii[j] / (_num_sectors / 2 + _rings[j]) *
121 364 : (i + _num_sectors / 2 + 1));
122 364 : ++i;
123 : }
124 : else
125 988 : while (i < _rings[j])
126 : {
127 658 : total_concentric_circles.push_back(_radii[j - 1] +
128 658 : (_radii[j] - _radii[j - 1]) / _rings[j] * (i + 1));
129 658 : ++i;
130 : }
131 548 : ++j;
132 : }
133 :
134 : // volume preserving function is used to conserve volume.
135 218 : const Real d_angle = M_PI / 2 / _num_sectors;
136 :
137 218 : if (_preserve_volumes)
138 : {
139 32 : Real original_radius = 0.0;
140 272 : for (unsigned i = 0; i < total_concentric_circles.size(); ++i)
141 : {
142 : // volume preserving function for the center circle
143 240 : if (i == 0)
144 : {
145 32 : const Real target_area = M_PI * Utility::pow<2>(total_concentric_circles[i]);
146 32 : Real modified_radius = std::sqrt(2 * target_area / std::sin(d_angle) / _num_sectors / 4);
147 32 : original_radius = total_concentric_circles[i];
148 32 : total_concentric_circles[i] = modified_radius;
149 : }
150 : else
151 : {
152 : // volume preserving functions for outer circles
153 208 : const Real target_area = M_PI * (Utility::pow<2>(total_concentric_circles[i]) -
154 208 : Utility::pow<2>(original_radius));
155 416 : Real modified_radius = std::sqrt(target_area / std::sin(d_angle) / _num_sectors / 2 +
156 208 : Utility::pow<2>(total_concentric_circles[i - 1]));
157 208 : original_radius = total_concentric_circles[i];
158 208 : total_concentric_circles[i] = modified_radius;
159 : }
160 : }
161 : }
162 :
163 : // number of total nodes
164 218 : unsigned num_total_nodes = 0;
165 :
166 218 : if (_has_outer_square)
167 106 : num_total_nodes = Utility::pow<2>(_num_sectors / 2 + 1) +
168 106 : (_num_sectors + 1) * total_concentric_circles.size() +
169 106 : Utility::pow<2>(_rings.back() + 2) + _num_sectors * (_rings.back() + 1) - 1;
170 : else
171 224 : num_total_nodes = Utility::pow<2>(_num_sectors / 2 + 1) +
172 112 : (_num_sectors + 1) * total_concentric_circles.size();
173 :
174 218 : std::vector<Node *> nodes(num_total_nodes);
175 :
176 218 : unsigned node_id = 0;
177 :
178 : // for adding nodes for the square at the center of the circle
179 218 : Real xx = total_concentric_circles[0] / (_num_sectors / 2 + 1) * _num_sectors / 2;
180 218 : Point p1 = Point(xx, 0, 0);
181 218 : Point p2 = Point(0, xx, 0);
182 218 : Point p3 = Point(xx * std::sqrt(2.0) / 2, xx * std::sqrt(2.0) / 2, 0);
183 1122 : for (unsigned i = 0; i <= _num_sectors / 2; ++i)
184 : {
185 904 : Real fx = i / (_num_sectors / 2.0);
186 4840 : for (unsigned j = 0; j <= _num_sectors / 2; ++j)
187 : {
188 3936 : Real fy = j / (_num_sectors / 2.0);
189 3936 : Point p = p1 * fx * (1 - fy) + p2 * fy * (1 - fx) + p3 * fx * fy;
190 3936 : nodes[node_id] = mesh->add_point(p, node_id);
191 3936 : ++node_id;
192 : }
193 : }
194 :
195 : // for adding the outer layers of the square
196 218 : Real current_radius = total_concentric_circles[0];
197 :
198 : // for adding the outer circles of the square.
199 1240 : for (unsigned layers = 0; layers < total_concentric_circles.size(); ++layers)
200 : {
201 1022 : current_radius = total_concentric_circles[layers];
202 8556 : for (unsigned num_outer_nodes = 0; num_outer_nodes <= _num_sectors; ++num_outer_nodes)
203 : {
204 7534 : const Real x = current_radius * std::cos(num_outer_nodes * d_angle);
205 7534 : const Real y = current_radius * std::sin(num_outer_nodes * d_angle);
206 7534 : nodes[node_id] = mesh->add_point(Point(x, y, 0.0), node_id);
207 7534 : ++node_id;
208 : }
209 : }
210 :
211 : // adding nodes for the enclosing square.
212 : // adding nodes for the left edge of the square.
213 : // applying the method for partitioning the line segments.
214 :
215 218 : if (_has_outer_square)
216 : {
217 : // putting nodes for the left side of the enclosing square.
218 470 : for (unsigned i = 0; i <= _num_sectors / 2; ++i)
219 : {
220 364 : const Real a1 = (_pitch / 2) * i / (_num_sectors / 2 + _rings.back() + 1);
221 364 : const Real b1 = _pitch / 2;
222 :
223 364 : const Real a2 = total_concentric_circles.back() * std::cos(M_PI / 2 - i * d_angle);
224 364 : const Real b2 = total_concentric_circles.back() * std::sin(M_PI / 2 - i * d_angle);
225 :
226 1508 : for (unsigned j = 0; j <= _rings.back(); ++j)
227 : {
228 1144 : Real x = ((_rings.back() + 1 - j) * a1 + j * a2) / (_rings.back() + 1);
229 1144 : Real y = ((_rings.back() + 1 - j) * b1 + j * b2) / (_rings.back() + 1);
230 1144 : nodes[node_id] = mesh->add_point(Point(x, y, 0.0), node_id);
231 1144 : ++node_id;
232 : }
233 : }
234 : // putting nodes for the center part of the enclosing square.
235 106 : unsigned k = 1;
236 422 : for (unsigned i = 1; i <= _rings.back() + 1; ++i)
237 : {
238 : const Real a1 =
239 316 : (_pitch / 2) * (i + _num_sectors / 2) / (_num_sectors / 2 + _rings.back() + 1);
240 316 : const Real b1 = _pitch / 2;
241 :
242 316 : const Real a2 = _pitch / 2;
243 316 : const Real b2 = (_pitch / 2) * (_num_sectors / 2) / (_num_sectors / 2 + _rings.back() + 1);
244 :
245 316 : const Real a3 = total_concentric_circles.back() * std::cos(M_PI / 4);
246 316 : const Real b3 = total_concentric_circles.back() * std::sin(M_PI / 4);
247 :
248 316 : const Real a4 = ((_rings.back() + 1 - k) * a3 + k * a2) / (_rings.back() + 1);
249 316 : const Real b4 = ((_rings.back() + 1 - k) * b3 + k * b2) / (_rings.back() + 1);
250 :
251 1768 : for (unsigned j = 0; j <= _rings.back() + 1; ++j)
252 : {
253 1452 : Real x = ((_rings.back() + 1 - j) * a1 + j * a4) / (_rings.back() + 1);
254 1452 : Real y = ((_rings.back() + 1 - j) * b1 + j * b4) / (_rings.back() + 1);
255 1452 : nodes[node_id] = mesh->add_point(Point(x, y, 0.0), node_id);
256 1452 : ++node_id;
257 : }
258 316 : ++k;
259 : }
260 :
261 : // putting nodes for the right part of the enclosing square.
262 364 : for (unsigned i = 1; i <= _num_sectors / 2; ++i)
263 : {
264 258 : const Real a1 = _pitch / 2;
265 : const Real b1 =
266 258 : (_pitch / 2) * (_num_sectors / 2 - i) / (_num_sectors / 2 + _rings.back() + 1);
267 :
268 258 : const Real a2 = total_concentric_circles.back() * std::cos(M_PI / 4 - i * d_angle);
269 258 : const Real b2 = total_concentric_circles.back() * std::sin(M_PI / 4 - i * d_angle);
270 :
271 1086 : for (unsigned j = 0; j <= _rings.back(); ++j)
272 : {
273 828 : Real x = ((_rings.back() + 1 - j) * a1 + j * a2) / (_rings.back() + 1);
274 828 : Real y = ((_rings.back() + 1 - j) * b1 + j * b2) / (_rings.back() + 1);
275 828 : nodes[node_id] = mesh->add_point(Point(x, y, 0.0), node_id);
276 828 : ++node_id;
277 : }
278 : }
279 : }
280 :
281 : // Currently, index, limit, counter variables use the int type because of the 'modulo' function.
282 : // adding elements
283 218 : int index = 0;
284 218 : int limit = 0;
285 218 : int standard = static_cast<int>(_num_sectors);
286 :
287 : // This is to set the limit for the index
288 218 : if (standard > 4)
289 : {
290 158 : int additional_term = 0;
291 158 : int counter = standard;
292 418 : while (counter > 4)
293 : {
294 260 : counter = counter - 2;
295 260 : additional_term = additional_term + counter;
296 : }
297 158 : limit = standard + additional_term;
298 : }
299 60 : else if (standard == 4)
300 50 : limit = standard;
301 :
302 : // SubdomainIDs set up
303 218 : std::vector<unsigned int> subdomainIDs;
304 :
305 218 : if (_has_outer_square)
306 454 : for (unsigned int i = 0; i < _rings.size() - 1; ++i)
307 1020 : for (unsigned int j = 0; j < _rings[i]; ++j)
308 672 : subdomainIDs.push_back(i + 1);
309 : else
310 312 : for (unsigned int i = 0; i < _rings.size(); ++i)
311 550 : for (unsigned int j = 0; j < _rings[i]; ++j)
312 350 : subdomainIDs.push_back(i + 1);
313 :
314 : // adding elements in the square
315 2564 : while (index <= limit)
316 : {
317 : // inner circle area (polygonal core)
318 2346 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
319 2346 : elem->set_node(0, nodes[index]);
320 2346 : elem->set_node(1, nodes[index + _num_sectors / 2 + 1]);
321 2346 : elem->set_node(2, nodes[index + _num_sectors / 2 + 2]);
322 2346 : elem->set_node(3, nodes[index + 1]);
323 2346 : elem->subdomain_id() = subdomainIDs[0];
324 :
325 2346 : if (index < standard / 2)
326 686 : boundary_info.add_side(elem, 3, 1);
327 2346 : if (index % (standard / 2 + 1) == 0)
328 686 : boundary_info.add_side(elem, 0, 2);
329 :
330 2346 : ++index;
331 :
332 : // increment by 2 indices is necessary depending on where the index points to.
333 2346 : if ((index - standard / 2) % (standard / 2 + 1) == 0)
334 686 : ++index;
335 : }
336 :
337 218 : index = (_num_sectors / 2 + 1) * (_num_sectors / 2);
338 218 : limit = (_num_sectors / 2) * (_num_sectors / 2 + 2);
339 :
340 : // adding elements in one outer layer of the square (right side)
341 904 : while (index < limit)
342 : {
343 : // inner circle elements touching B
344 686 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
345 686 : elem->set_node(0, nodes[index]);
346 686 : elem->set_node(1, nodes[index + _num_sectors / 2 + 1]);
347 686 : elem->set_node(2, nodes[index + _num_sectors / 2 + 2]);
348 686 : elem->set_node(3, nodes[index + 1]);
349 686 : elem->subdomain_id() = subdomainIDs[0];
350 :
351 686 : if (index == (standard / 2 + 1) * (standard / 2))
352 218 : boundary_info.add_side(elem, 0, 2);
353 :
354 686 : ++index;
355 : }
356 :
357 : // adding elements in one outer layer of the square (left side)
358 218 : int counter = 0;
359 904 : while (index != standard / 2)
360 : {
361 : // inner circle elements touching C
362 686 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
363 686 : elem->set_node(0, nodes[index]);
364 686 : elem->set_node(1, nodes[index + (_num_sectors / 2 + 1) + counter * (_num_sectors / 2 + 2)]);
365 686 : elem->set_node(2, nodes[index + (_num_sectors / 2 + 1) + counter * (_num_sectors / 2 + 2) + 1]);
366 686 : elem->set_node(3, nodes[index - _num_sectors / 2 - 1]);
367 686 : elem->subdomain_id() = subdomainIDs[0];
368 :
369 686 : if (index == standard + 1)
370 218 : boundary_info.add_side(elem, 2, 1);
371 :
372 686 : index = index - _num_sectors / 2 - 1;
373 686 : ++counter;
374 : }
375 :
376 218 : counter = 0;
377 : // adding elements for other concentric circles
378 218 : index = Utility::pow<2>(standard / 2 + 1);
379 218 : limit = Utility::pow<2>(standard / 2 + 1) +
380 218 : (_num_sectors + 1) * (total_concentric_circles.size() - 1);
381 :
382 218 : int num_nodes_boundary = Utility::pow<2>(standard / 2 + 1) + standard + 1;
383 :
384 5358 : while (index < limit)
385 : {
386 5140 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
387 5140 : elem->set_node(0, nodes[index]);
388 5140 : elem->set_node(1, nodes[index + standard + 1]);
389 5140 : elem->set_node(2, nodes[index + standard + 2]);
390 5140 : elem->set_node(3, nodes[index + 1]);
391 :
392 56152 : for (int i = 0; i < static_cast<int>(subdomainIDs.size() - 1); ++i)
393 51012 : if (index < limit - (standard + 1) * i && index >= limit - (standard + 1) * (i + 1))
394 5140 : elem->subdomain_id() = subdomainIDs[subdomainIDs.size() - 1 - i];
395 :
396 5140 : const int initial = Utility::pow<2>(standard / 2 + 1);
397 5140 : const int final = Utility::pow<2>(standard / 2 + 1) + standard - 1;
398 :
399 5140 : if ((index - initial) % (standard + 1) == 0)
400 804 : boundary_info.add_side(elem, 0, 2);
401 5140 : if ((index - final) % (standard + 1) == 0)
402 804 : boundary_info.add_side(elem, 2, 1);
403 5140 : if (!_has_outer_square)
404 1824 : if (index >= limit - (standard + 1))
405 376 : boundary_info.add_side(elem, 1, 3);
406 :
407 : // index increment is for adding nodes for a next element.
408 5140 : ++index;
409 :
410 : // increment by 2 indices may be necessary depending on where the index points to.
411 : // this varies based on the algorithms provided for the specific element and node placement.
412 5140 : if (index == (num_nodes_boundary + counter * (standard + 1)) - 1)
413 : {
414 804 : ++index;
415 804 : ++counter;
416 : }
417 : }
418 :
419 : // Enclosing square sections
420 : // ABCA
421 : // C B
422 : // B C
423 : // ACBA
424 :
425 : // adding elements for the enclosing square. (top left)
426 : int initial =
427 218 : Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size();
428 :
429 : int initial2 =
430 218 : Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size();
431 :
432 218 : if (_has_outer_square)
433 : {
434 106 : if (_rings.back() != 0) // this must be condition up front.
435 : {
436 106 : index = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size();
437 106 : limit = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
438 106 : (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 3 -
439 106 : _rings.back() * (_rings.back() + 2) - (_rings.back() + 1);
440 992 : while (index <= limit)
441 : {
442 : // outer square sector C
443 780 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
444 780 : elem->set_node(0, nodes[index]);
445 780 : elem->set_node(1, nodes[index + 1]);
446 780 : elem->set_node(2, nodes[index + 1 + _rings.back() + 1]);
447 780 : elem->set_node(3, nodes[index + 1 + _rings.back()]);
448 780 : elem->subdomain_id() = subdomainIDs.back() + 1;
449 :
450 780 : if (index < (initial2 + static_cast<int>(_rings.back())))
451 210 : boundary_info.add_side(elem, 0, 1);
452 :
453 780 : if (index == initial)
454 364 : boundary_info.add_side(elem, 3, 4);
455 :
456 780 : ++index;
457 :
458 : // As mentioned before, increment by 2 indices may be required depending on where the index
459 : // points to.
460 780 : if ((index - initial) % static_cast<int>(_rings.back()) == 0)
461 : {
462 364 : ++index;
463 364 : initial = initial + (static_cast<int>(_rings.back()) + 1);
464 : }
465 : }
466 :
467 : // adding elements for the enclosing square. (top right)
468 106 : initial = Utility::pow<2>(standard / 2 + 1) +
469 318 : (standard + 1) * total_concentric_circles.size() +
470 106 : (_rings.back() + 1) * (standard / 2 + 1);
471 :
472 106 : limit = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
473 106 : (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 3 -
474 106 : (_rings.back() + 2);
475 :
476 1032 : while (index <= limit)
477 : {
478 : // outer square sector A
479 820 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
480 820 : elem->set_node(3, nodes[index]);
481 820 : elem->set_node(2, nodes[index + _rings.back() + 2]);
482 820 : elem->set_node(1, nodes[index + _rings.back() + 3]);
483 820 : elem->set_node(0, nodes[index + 1]);
484 820 : elem->subdomain_id() = subdomainIDs.back() + 1;
485 :
486 820 : if (index >= static_cast<int>(limit - (_rings.back() + 1)))
487 316 : boundary_info.add_side(elem, 1, 3);
488 :
489 820 : if ((index - initial) % static_cast<int>(_rings.back() + 2) == 0)
490 210 : boundary_info.add_side(elem, 2, 4);
491 :
492 820 : ++index;
493 :
494 820 : if ((index - initial) % static_cast<int>(_rings.back() + 1) == 0)
495 : {
496 210 : ++index;
497 210 : initial = initial + (static_cast<int>(_rings.back()) + 2);
498 : }
499 : }
500 :
501 : // adding elements for the enclosing square. (one center quad)
502 106 : int index1 = Utility::pow<2>(standard / 2 + 1) +
503 106 : (standard + 1) * (total_concentric_circles.size() - 1) + standard / 2;
504 :
505 106 : int index2 = Utility::pow<2>(standard / 2 + 1) +
506 318 : (standard + 1) * total_concentric_circles.size() +
507 106 : (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 3 -
508 106 : _rings.back() * (_rings.back() + 2) - (_rings.back() + 1);
509 :
510 : // pointy tips of the A sectors, touching the inner circle
511 106 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
512 106 : elem->set_node(3, nodes[index1]);
513 106 : elem->set_node(2, nodes[index2]);
514 106 : elem->set_node(1, nodes[index2 + _rings.back() + 1]);
515 106 : elem->set_node(0, nodes[index2 + _rings.back() + 2]);
516 106 : elem->subdomain_id() = subdomainIDs.back() + 1;
517 :
518 : // adding elements for the left mid part.
519 106 : index = Utility::pow<2>(standard / 2 + 1) + standard / 2 +
520 106 : (standard + 1) * (total_concentric_circles.size() - 1);
521 106 : limit = index + standard / 2 - 1;
522 :
523 364 : while (index <= limit)
524 : {
525 : // outer square elements in sector C touching the inner circle
526 258 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
527 258 : elem->set_node(3, nodes[index]);
528 258 : elem->set_node(2, nodes[index + 1]);
529 258 : elem->set_node(1, nodes[index2 - _rings.back() - 1]);
530 258 : elem->set_node(0, nodes[index2]);
531 258 : elem->subdomain_id() = subdomainIDs.back() + 1;
532 :
533 258 : if (index == limit)
534 106 : boundary_info.add_side(elem, 1, 1);
535 :
536 258 : ++index;
537 :
538 : // two different indices are used to add nodes for an element.
539 258 : index2 = index2 - _rings.back() - 1;
540 : }
541 :
542 : // adding elements for the right mid part.
543 106 : index1 = Utility::pow<2>(standard / 2 + 1) + standard / 2 +
544 106 : (standard + 1) * (total_concentric_circles.size() - 1);
545 106 : index2 = Utility::pow<2>(standard / 2 + 1) +
546 318 : (standard + 1) * total_concentric_circles.size() +
547 106 : (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 2 +
548 106 : (_rings.back() + 1);
549 : int index3 =
550 106 : Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
551 106 : (_rings.back() + 1) * (standard / 2) - 1 + (_rings.back() + 1) + (_rings.back() + 2);
552 :
553 : // elements clockwise from the A sector tips
554 106 : elem = mesh->add_elem(std::make_unique<Quad4>());
555 106 : elem->set_node(0, nodes[index1]);
556 106 : elem->set_node(1, nodes[index1 - 1]);
557 106 : elem->set_node(2, nodes[index2]);
558 106 : elem->set_node(3, nodes[index3]);
559 106 : elem->subdomain_id() = subdomainIDs.back() + 1;
560 :
561 106 : if (standard == 2)
562 10 : boundary_info.add_side(elem, 1, 2);
563 :
564 : // adding elements for the right mid bottom part.
565 :
566 106 : index = Utility::pow<2>(standard / 2 + 1) + standard / 2 +
567 106 : (standard + 1) * (total_concentric_circles.size() - 1) - 2;
568 106 : index1 = Utility::pow<2>(standard / 2 + 1) +
569 318 : (standard + 1) * total_concentric_circles.size() +
570 106 : (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 2 +
571 106 : (_rings.back() + 1) * 2;
572 :
573 106 : limit = Utility::pow<2>(standard / 2 + 1) + standard / 2 +
574 106 : (standard + 1) * (total_concentric_circles.size() - 1) - standard / 2;
575 :
576 106 : if (standard != 2)
577 : {
578 248 : while (index >= limit)
579 : {
580 : // outer square elements in sector B touching the inner circle
581 152 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
582 152 : elem->set_node(0, nodes[index]);
583 152 : elem->set_node(1, nodes[index1]);
584 152 : elem->set_node(2, nodes[index1 - (_rings.back() + 1)]);
585 152 : elem->set_node(3, nodes[index + 1]);
586 152 : elem->subdomain_id() = subdomainIDs.back() + 1;
587 :
588 152 : if (index == limit)
589 96 : boundary_info.add_side(elem, 0, 2);
590 152 : --index;
591 152 : index1 = index1 + (_rings.back() + 1);
592 : }
593 : }
594 :
595 : // adding elements for the right low part.
596 106 : index = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
597 106 : (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 2;
598 :
599 106 : index1 = index - (_rings.back() + 2);
600 : // dummy condition for elem definition
601 106 : if (standard >= 2)
602 : {
603 : // single elements between A and B on the outside of the square
604 106 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
605 106 : elem->set_node(3, nodes[index]);
606 106 : elem->set_node(2, nodes[index + 1]);
607 106 : elem->set_node(1, nodes[index + 2]);
608 106 : elem->set_node(0, nodes[index1]);
609 106 : elem->subdomain_id() = subdomainIDs.back() + 1;
610 :
611 106 : boundary_info.add_side(elem, 2, 3);
612 :
613 106 : if (standard == 2)
614 10 : boundary_info.add_side(elem, 1, 2);
615 : }
616 :
617 106 : index = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
618 106 : (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 2 -
619 106 : (_rings.back() + 2);
620 :
621 106 : limit = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
622 106 : (_rings.back() + 1) * (standard / 2) + (_rings.back() + 2) * 2 - 2;
623 :
624 106 : int k = 1;
625 210 : while (index > limit)
626 : {
627 104 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
628 104 : elem->set_node(3, nodes[index]);
629 104 : elem->set_node(2, nodes[index + (_rings.back() + 2) * k + k + 1]);
630 104 : elem->set_node(1, nodes[index + (_rings.back() + 2) * k + k + 2]);
631 104 : elem->set_node(0, nodes[index - _rings.back() - 2]);
632 104 : elem->subdomain_id() = subdomainIDs.back() + 1;
633 104 : index = index - (_rings.back() + 2);
634 104 : ++k;
635 :
636 104 : if (standard == 2)
637 0 : boundary_info.add_side(elem, 1, 2);
638 : }
639 :
640 106 : index = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
641 106 : (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 1;
642 106 : initial = Utility::pow<2>(standard / 2 + 1) +
643 318 : (standard + 1) * total_concentric_circles.size() +
644 106 : (_rings.back() + 1) * (standard / 2) + Utility::pow<2>(_rings.back() + 2) - 1;
645 106 : limit = Utility::pow<2>(standard / 2 + 1) + (standard + 1) * total_concentric_circles.size() +
646 106 : (_rings.back() + 1) * (standard / 2) * 2 + Utility::pow<2>(_rings.back() + 2) - 2 -
647 106 : _rings.back() - 1;
648 :
649 106 : initial2 = Utility::pow<2>(standard / 2 + 1) +
650 318 : (standard + 1) * total_concentric_circles.size() +
651 106 : (_rings.back() + 1) * (standard / 2) * 2 + Utility::pow<2>(_rings.back() + 2) - 2 -
652 106 : (_rings.back() + 1) * 2;
653 :
654 106 : if (standard > 2)
655 : {
656 552 : while (index < limit)
657 : {
658 360 : Elem * elem = mesh->add_elem(std::make_unique<Quad4>());
659 360 : elem->set_node(0, nodes[index]);
660 360 : elem->set_node(1, nodes[index + 1]);
661 360 : elem->set_node(2, nodes[index + 1 + _rings.back() + 1]);
662 360 : elem->set_node(3, nodes[index + 1 + _rings.back()]);
663 360 : elem->subdomain_id() = subdomainIDs.back() + 1;
664 :
665 360 : if (index > initial2)
666 200 : boundary_info.add_side(elem, 2, 2);
667 :
668 360 : if ((index - initial) == 0)
669 152 : boundary_info.add_side(elem, 3, 3);
670 :
671 360 : ++index;
672 :
673 360 : if ((index - initial) % static_cast<int>(_rings.back()) == 0)
674 : {
675 152 : ++index;
676 152 : initial = initial + (static_cast<int>(_rings.back()) + 1);
677 : }
678 : }
679 : }
680 : }
681 : }
682 :
683 : // This is to set boundary names.
684 218 : boundary_info.sideset_name(1) = "left";
685 218 : boundary_info.sideset_name(2) = "bottom";
686 :
687 218 : if (!_has_outer_square)
688 112 : boundary_info.sideset_name(3) = "outer";
689 : else
690 : {
691 106 : boundary_info.sideset_name(3) = "right";
692 106 : boundary_info.sideset_name(4) = "top";
693 : }
694 :
695 218 : if (_portion == "top_left")
696 : {
697 10 : MeshTools::Modification::rotate(*mesh, 90, 0, 0);
698 10 : boundary_info.sideset_name(1) = "bottom";
699 10 : boundary_info.sideset_name(2) = "right";
700 :
701 10 : if (!_has_outer_square)
702 10 : boundary_info.sideset_name(3) = "outer";
703 : else
704 : {
705 0 : boundary_info.sideset_name(3) = "top";
706 0 : boundary_info.sideset_name(4) = "left";
707 : }
708 : }
709 208 : else if (_portion == "bottom_left")
710 : {
711 10 : MeshTools::Modification::rotate(*mesh, 180, 0, 0);
712 10 : boundary_info.sideset_name(1) = "right";
713 10 : boundary_info.sideset_name(2) = "top";
714 :
715 10 : if (!_has_outer_square)
716 10 : boundary_info.sideset_name(3) = "outer";
717 : else
718 : {
719 0 : boundary_info.sideset_name(3) = "left";
720 0 : boundary_info.sideset_name(4) = "bottom";
721 : }
722 : }
723 198 : else if (_portion == "bottom_right")
724 : {
725 10 : MeshTools::Modification::rotate(*mesh, 270, 0, 0);
726 10 : boundary_info.sideset_name(1) = "top";
727 10 : boundary_info.sideset_name(2) = "left";
728 :
729 10 : if (!_has_outer_square)
730 10 : boundary_info.sideset_name(3) = "outer";
731 : else
732 : {
733 0 : boundary_info.sideset_name(3) = "bottom";
734 0 : boundary_info.sideset_name(4) = "right";
735 : }
736 : }
737 :
738 188 : else if (_portion == "top_half")
739 : {
740 0 : ReplicatedMesh other_mesh(*mesh);
741 : // This is to rotate the mesh and also to reset boundary IDs.
742 0 : MeshTools::Modification::rotate(other_mesh, 90, 0, 0);
743 0 : if (_has_outer_square)
744 : {
745 0 : MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
746 0 : MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
747 0 : MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
748 0 : MeshTools::Modification::change_boundary_id(other_mesh, 4, 1);
749 0 : MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
750 0 : MeshTools::Modification::change_boundary_id(other_mesh, 6, 3);
751 0 : MeshTools::Modification::change_boundary_id(other_mesh, 7, 4);
752 0 : mesh->prepare_for_use();
753 0 : other_mesh.prepare_for_use();
754 0 : mesh->stitch_meshes(other_mesh, 1, 3, TOLERANCE, true, /*verbose=*/false);
755 0 : mesh->get_boundary_info().sideset_name(1) = "left";
756 0 : mesh->get_boundary_info().sideset_name(2) = "bottom";
757 0 : mesh->get_boundary_info().sideset_name(3) = "right";
758 0 : mesh->get_boundary_info().sideset_name(4) = "top";
759 : }
760 : else
761 : {
762 0 : MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
763 0 : MeshTools::Modification::change_boundary_id(other_mesh, 2, 1);
764 0 : MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
765 0 : mesh->prepare_for_use();
766 0 : other_mesh.prepare_for_use();
767 0 : mesh->stitch_meshes(other_mesh, 1, 1, TOLERANCE, true, /*verbose=*/false);
768 :
769 0 : MeshTools::Modification::change_boundary_id(*mesh, 2, 1);
770 0 : MeshTools::Modification::change_boundary_id(*mesh, 3, 2);
771 0 : mesh->get_boundary_info().sideset_name(1) = "bottom";
772 0 : mesh->get_boundary_info().sideset_name(2) = "outer";
773 : }
774 0 : other_mesh.clear();
775 0 : }
776 :
777 188 : else if (_portion == "right_half")
778 : {
779 0 : ReplicatedMesh other_mesh(*mesh);
780 : // This is to rotate the mesh and also to reset boundary IDs.
781 0 : MeshTools::Modification::rotate(other_mesh, 270, 0, 0);
782 0 : if (_has_outer_square)
783 : {
784 0 : MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
785 0 : MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
786 0 : MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
787 0 : MeshTools::Modification::change_boundary_id(other_mesh, 4, 3);
788 0 : MeshTools::Modification::change_boundary_id(other_mesh, 5, 4);
789 0 : MeshTools::Modification::change_boundary_id(other_mesh, 6, 1);
790 0 : MeshTools::Modification::change_boundary_id(other_mesh, 7, 2);
791 0 : mesh->prepare_for_use();
792 0 : other_mesh.prepare_for_use();
793 0 : mesh->stitch_meshes(other_mesh, 2, 4, TOLERANCE, true, /*verbose=*/false);
794 0 : mesh->get_boundary_info().sideset_name(1) = "left";
795 0 : mesh->get_boundary_info().sideset_name(2) = "bottom";
796 0 : mesh->get_boundary_info().sideset_name(3) = "right";
797 0 : mesh->get_boundary_info().sideset_name(4) = "top";
798 : }
799 : else
800 : {
801 0 : MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
802 0 : MeshTools::Modification::change_boundary_id(other_mesh, 2, 1);
803 0 : MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
804 0 : mesh->prepare_for_use();
805 0 : other_mesh.prepare_for_use();
806 0 : mesh->stitch_meshes(other_mesh, 2, 2, TOLERANCE, true, /*verbose=*/false);
807 :
808 0 : MeshTools::Modification::change_boundary_id(*mesh, 3, 2);
809 0 : mesh->get_boundary_info().sideset_name(1) = "left";
810 0 : mesh->get_boundary_info().sideset_name(2) = "outer";
811 : }
812 0 : other_mesh.clear();
813 0 : }
814 188 : else if (_portion == "left_half")
815 : {
816 0 : ReplicatedMesh other_mesh(*mesh);
817 :
818 : // This is to rotate the mesh and to reset boundary IDs.
819 0 : MeshTools::Modification::rotate(other_mesh, 90, 0, 0);
820 0 : MeshTools::Modification::rotate(*mesh, 180, 0, 0);
821 0 : if (_has_outer_square)
822 : {
823 : // The other mesh is created by rotating the original mesh about 90 degrees.
824 0 : MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
825 0 : MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
826 0 : MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
827 0 : MeshTools::Modification::change_boundary_id(other_mesh, 4, 1);
828 0 : MeshTools::Modification::change_boundary_id(other_mesh, 5, 2);
829 0 : MeshTools::Modification::change_boundary_id(other_mesh, 6, 3);
830 0 : MeshTools::Modification::change_boundary_id(other_mesh, 7, 4);
831 : // The original mesh is then rotated about 180 degrees.
832 0 : MeshTools::Modification::change_boundary_id(*mesh, 1, 5);
833 0 : MeshTools::Modification::change_boundary_id(*mesh, 2, 6);
834 0 : MeshTools::Modification::change_boundary_id(*mesh, 3, 7);
835 0 : MeshTools::Modification::change_boundary_id(*mesh, 4, 2);
836 0 : MeshTools::Modification::change_boundary_id(*mesh, 5, 3);
837 0 : MeshTools::Modification::change_boundary_id(*mesh, 6, 4);
838 0 : MeshTools::Modification::change_boundary_id(*mesh, 7, 1);
839 0 : mesh->prepare_for_use();
840 0 : other_mesh.prepare_for_use();
841 0 : mesh->stitch_meshes(other_mesh, 4, 2, TOLERANCE, true, /*verbose=*/false);
842 0 : mesh->get_boundary_info().sideset_name(1) = "left";
843 0 : mesh->get_boundary_info().sideset_name(2) = "bottom";
844 0 : mesh->get_boundary_info().sideset_name(3) = "right";
845 0 : mesh->get_boundary_info().sideset_name(4) = "top";
846 : }
847 : else
848 : {
849 0 : MeshTools::Modification::change_boundary_id(*mesh, 1, 5);
850 0 : MeshTools::Modification::change_boundary_id(*mesh, 2, 1);
851 0 : MeshTools::Modification::change_boundary_id(*mesh, 5, 2);
852 0 : mesh->prepare_for_use();
853 0 : other_mesh.prepare_for_use();
854 0 : mesh->stitch_meshes(other_mesh, 1, 1, TOLERANCE, true, /*verbose=*/false);
855 :
856 0 : MeshTools::Modification::change_boundary_id(*mesh, 2, 1);
857 0 : MeshTools::Modification::change_boundary_id(*mesh, 3, 2);
858 0 : mesh->get_boundary_info().sideset_name(1) = "right";
859 0 : mesh->get_boundary_info().sideset_name(2) = "outer";
860 : }
861 0 : other_mesh.clear();
862 0 : }
863 188 : else if (_portion == "bottom_half")
864 : {
865 0 : ReplicatedMesh other_mesh(*mesh);
866 : // This is to rotate the mesh and also to reset boundary IDs.
867 0 : MeshTools::Modification::rotate(other_mesh, 180, 0, 0);
868 0 : MeshTools::Modification::rotate(*mesh, 270, 0, 0);
869 0 : if (_has_outer_square)
870 : {
871 : // The other mesh is created by rotating the original mesh about 180 degrees.
872 0 : MeshTools::Modification::change_boundary_id(other_mesh, 1, 5);
873 0 : MeshTools::Modification::change_boundary_id(other_mesh, 2, 6);
874 0 : MeshTools::Modification::change_boundary_id(other_mesh, 3, 7);
875 0 : MeshTools::Modification::change_boundary_id(other_mesh, 4, 2);
876 0 : MeshTools::Modification::change_boundary_id(other_mesh, 5, 3);
877 0 : MeshTools::Modification::change_boundary_id(other_mesh, 6, 4);
878 0 : MeshTools::Modification::change_boundary_id(other_mesh, 7, 1);
879 : // The original mesh is rotated about 270 degrees.
880 0 : MeshTools::Modification::change_boundary_id(*mesh, 1, 5);
881 0 : MeshTools::Modification::change_boundary_id(*mesh, 2, 6);
882 0 : MeshTools::Modification::change_boundary_id(*mesh, 3, 7);
883 0 : MeshTools::Modification::change_boundary_id(*mesh, 4, 3);
884 0 : MeshTools::Modification::change_boundary_id(*mesh, 5, 4);
885 0 : MeshTools::Modification::change_boundary_id(*mesh, 6, 1);
886 0 : MeshTools::Modification::change_boundary_id(*mesh, 7, 2);
887 0 : mesh->prepare_for_use();
888 0 : other_mesh.prepare_for_use();
889 0 : mesh->stitch_meshes(other_mesh, 1, 3, TOLERANCE, true, /*verbose=*/false);
890 0 : mesh->get_boundary_info().sideset_name(1) = "left";
891 0 : mesh->get_boundary_info().sideset_name(2) = "bottom";
892 0 : mesh->get_boundary_info().sideset_name(3) = "right";
893 0 : mesh->get_boundary_info().sideset_name(4) = "top";
894 : }
895 : else
896 : {
897 0 : MeshTools::Modification::change_boundary_id(*mesh, 1, 5);
898 0 : MeshTools::Modification::change_boundary_id(*mesh, 2, 1);
899 0 : MeshTools::Modification::change_boundary_id(*mesh, 5, 2);
900 0 : mesh->prepare_for_use();
901 0 : other_mesh.prepare_for_use();
902 0 : mesh->stitch_meshes(other_mesh, 1, 1, TOLERANCE, true, /*verbose=*/false);
903 :
904 0 : MeshTools::Modification::change_boundary_id(*mesh, 2, 1);
905 0 : MeshTools::Modification::change_boundary_id(*mesh, 3, 2);
906 0 : mesh->get_boundary_info().sideset_name(1) = "top";
907 0 : mesh->get_boundary_info().sideset_name(2) = "outer";
908 : }
909 0 : other_mesh.clear();
910 0 : }
911 188 : else if (_portion == "full")
912 : {
913 98 : ReplicatedMesh portion_two(*mesh);
914 :
915 : // This is to rotate the mesh and also to reset boundary IDs.
916 98 : MeshTools::Modification::rotate(portion_two, 90, 0, 0);
917 :
918 98 : if (_has_outer_square)
919 : {
920 : // Portion 2: 2nd quadrant
921 66 : MeshTools::Modification::change_boundary_id(portion_two, 1, 5);
922 66 : MeshTools::Modification::change_boundary_id(portion_two, 2, 6);
923 66 : MeshTools::Modification::change_boundary_id(portion_two, 3, 7);
924 66 : MeshTools::Modification::change_boundary_id(portion_two, 4, 1);
925 66 : MeshTools::Modification::change_boundary_id(portion_two, 5, 2);
926 66 : MeshTools::Modification::change_boundary_id(portion_two, 6, 3);
927 66 : MeshTools::Modification::change_boundary_id(portion_two, 7, 4);
928 66 : mesh->prepare_for_use();
929 66 : portion_two.prepare_for_use();
930 : // 'top_half'
931 66 : mesh->stitch_meshes(portion_two, 1, 3, TOLERANCE, true, /*verbose=*/false);
932 :
933 : // 'bottom_half'
934 66 : ReplicatedMesh portion_bottom(*mesh);
935 66 : MeshTools::Modification::rotate(portion_bottom, 180, 0, 0);
936 66 : MeshTools::Modification::change_boundary_id(portion_bottom, 1, 5);
937 66 : MeshTools::Modification::change_boundary_id(portion_bottom, 2, 6);
938 66 : MeshTools::Modification::change_boundary_id(portion_bottom, 3, 7);
939 66 : MeshTools::Modification::change_boundary_id(portion_bottom, 4, 2);
940 66 : MeshTools::Modification::change_boundary_id(portion_bottom, 5, 3);
941 66 : MeshTools::Modification::change_boundary_id(portion_bottom, 6, 4);
942 66 : MeshTools::Modification::change_boundary_id(portion_bottom, 7, 1);
943 66 : mesh->prepare_for_use();
944 66 : portion_bottom.prepare_for_use();
945 : // 'full'
946 66 : mesh->stitch_meshes(portion_bottom, 2, 4, TOLERANCE, true, /*verbose=*/false);
947 :
948 66 : mesh->get_boundary_info().sideset_name(1) = "left";
949 66 : mesh->get_boundary_info().sideset_name(2) = "bottom";
950 66 : mesh->get_boundary_info().sideset_name(3) = "right";
951 66 : mesh->get_boundary_info().sideset_name(4) = "top";
952 66 : portion_bottom.clear();
953 66 : }
954 : else
955 : {
956 32 : MeshTools::Modification::change_boundary_id(portion_two, 1, 5);
957 32 : MeshTools::Modification::change_boundary_id(portion_two, 2, 1);
958 32 : MeshTools::Modification::change_boundary_id(portion_two, 5, 2);
959 : // 'top half'
960 32 : mesh->prepare_for_use();
961 32 : portion_two.prepare_for_use();
962 32 : mesh->stitch_meshes(portion_two, 1, 1, TOLERANCE, true, /*verbose=*/false);
963 : // 'bottom half'
964 32 : ReplicatedMesh portion_bottom(*mesh);
965 32 : MeshTools::Modification::rotate(portion_bottom, 180, 0, 0);
966 : // 'full'
967 32 : mesh->prepare_for_use();
968 32 : portion_bottom.prepare_for_use();
969 32 : mesh->stitch_meshes(portion_bottom, 2, 2, TOLERANCE, true, /*verbose=*/false);
970 32 : MeshTools::Modification::change_boundary_id(*mesh, 3, 1);
971 32 : mesh->get_boundary_info().sideset_name(1) = "outer";
972 32 : portion_bottom.clear();
973 32 : }
974 98 : portion_two.clear();
975 98 : }
976 :
977 436 : if (_portion != "top_half" && _portion != "right_half" && _portion != "left_half" &&
978 436 : _portion != "bottom_half" && _portion != "full")
979 120 : mesh->prepare_for_use();
980 :
981 : // Laplace smoothing
982 218 : libMesh::LaplaceMeshSmoother lms(*mesh);
983 218 : lms.smooth(_smoothing_max_it);
984 :
985 218 : mesh->prepare_for_use();
986 436 : return dynamic_pointer_cast<MeshBase>(mesh);
987 218 : }
|