11 #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" 28 "full top_right top_left bottom_left bottom_right right_half left_half top_half bottom_half",
31 "num_sectors % 2 = 0, num_sectors > 0" 32 "Number of azimuthal sectors in each quadrant" 33 "'num_sectors' must be an even number.");
34 params.
addRequiredParam<std::vector<Real>>(
"radii",
"Radii of major concentric circles");
36 "rings",
"Number of rings in each circle or in the moderator");
38 "Length of inner square / radius of the innermost circle");
41 "It determines if meshes for a outer square are added to concentric circle meshes.");
46 "The moderator can be added to complete meshes for one unit cell of fuel assembly." 47 "Elements are quad meshes.");
48 params.
addParam<
MooseEnum>(
"portion", portion,
"Control of which part of mesh is created");
50 "preserve_volumes",
"Volume of concentric circles can be preserved using this function.");
51 params.
addClassDescription(
"This ConcentricCircleMesh source code is to generate concentric " 58 _num_sectors(getParam<unsigned
int>(
"num_sectors")),
59 _radii(getParam<
std::vector<
Real>>(
"radii")),
60 _rings(getParam<
std::vector<unsigned
int>>(
"rings")),
61 _inner_mesh_fraction(getParam<
Real>(
"inner_mesh_fraction")),
62 _has_outer_square(getParam<bool>(
"has_outer_square")),
63 _pitch(getParam<
Real>(
"pitch")),
64 _preserve_volumes(getParam<bool>(
"preserve_volumes")),
69 mooseError(
"ConcentricCircleMesh: num_sectors must be an even number.");
72 for (
unsigned i = 0; i <
_radii.size() - 1; ++i)
74 mooseError(
"Radii must be provided in order by starting with the smallest radius and " 75 "providing the following gradual radii.");
79 mooseError(
"The aspect ratio can not be larger than cos(PI/4).");
85 mooseError(
"The size of 'rings' must be equal to the size of 'radii' plus 1.");
90 mooseError(
"The size of 'rings' must be equal to the size of 'radii'.");
94 for (
unsigned i = 0; i <
_radii.size(); ++i)
96 mooseError(
"The pitch / 2 must be larger than any radii.");
99 std::unique_ptr<MooseMesh>
109 ReplicatedMesh &
mesh = cast_ref<ReplicatedMesh &>(
getMesh());
111 mesh.set_mesh_dimension(2);
112 mesh.set_spatial_dimension(2);
113 BoundaryInfo & boundary_info =
mesh.get_boundary_info();
117 std::vector<Real> total_concentric_circles;
133 total_concentric_circles.push_back(
_radii[j - 1] +
145 Real original_radius = 0.0;
146 for (
unsigned i = 0; i < total_concentric_circles.size(); ++i)
153 original_radius = total_concentric_circles[i];
154 total_concentric_circles[i] = modified_radius;
163 original_radius = total_concentric_circles[i];
164 total_concentric_circles[i] = modified_radius;
170 unsigned num_total_nodes = 0;
179 std::vector<Node *> nodes(num_total_nodes);
180 unsigned node_id = 0;
189 nodes[node_id] =
mesh.add_point(Point(x, y, 0.0), node_id);
195 Real current_radius = 0.0;
197 for (
unsigned layers = 0; layers < total_concentric_circles.size(); ++layers)
199 current_radius = total_concentric_circles[layers];
200 for (
unsigned num_outer_nodes = 0; num_outer_nodes <=
_num_sectors; ++num_outer_nodes)
202 const Real x = current_radius *
std::cos(num_outer_nodes * d_angle);
203 const Real y = current_radius *
std::sin(num_outer_nodes * d_angle);
204 nodes[node_id] =
mesh.add_point(Point(x, y, 0.0), node_id);
212 Real current_radius_moderator = 0.0;
213 for (
unsigned i = 1; i <=
_rings.back(); ++i)
215 current_radius_moderator =
217 total_concentric_circles.push_back(current_radius_moderator);
218 for (
unsigned num_outer_nodes = 0; num_outer_nodes <=
_num_sectors; ++num_outer_nodes)
220 const Real x = current_radius_moderator *
std::cos(num_outer_nodes * d_angle);
221 const Real y = current_radius_moderator *
std::sin(num_outer_nodes * d_angle);
222 nodes[node_id] =
mesh.add_point(Point(x, y, 0.0), node_id);
230 const Real y =
_pitch / 2 * std::tan(j * d_angle);
231 nodes[node_id] =
mesh.add_point(Point(x, y, 0.0), node_id);
240 nodes[node_id] =
mesh.add_point(Point(x, y, 0.0), node_id);
253 int additional_term = 0;
254 int counter = standard;
257 counter = counter - 2;
258 additional_term = additional_term + counter;
260 limit = standard + additional_term;
262 else if (standard == 4)
266 std::vector<unsigned int> subdomainIDs;
267 for (
unsigned int i = 0; i <
_rings.size(); ++i)
268 for (
unsigned int j = 0; j <
_rings[i]; ++j)
269 subdomainIDs.push_back(i + 1);
272 subdomainIDs.push_back(subdomainIDs.back());
274 while (index <= limit)
276 Elem *
elem =
mesh.add_elem(
new Quad4);
277 elem->set_node(0, nodes[index]);
280 elem->set_node(3, nodes[index + 1]);
281 elem->subdomain_id() = subdomainIDs[0];
283 if (index < standard / 2)
284 boundary_info.add_side(
elem, 3, 1);
285 if (index % (standard / 2 + 1) == 0)
286 boundary_info.add_side(
elem, 0, 2);
289 if ((index - standard / 2) % (standard / 2 + 1) == 0)
297 while (index < limit)
299 Elem *
elem =
mesh.add_elem(
new Quad4);
300 elem->set_node(0, nodes[index]);
303 elem->set_node(3, nodes[index + 1]);
304 elem->subdomain_id() = subdomainIDs[0];
306 if (index == (standard / 2 + 1) * (standard / 2))
307 boundary_info.add_side(
elem, 0, 2);
314 while (index != standard / 2)
316 Elem *
elem =
mesh.add_elem(
new Quad4);
317 elem->set_node(0, nodes[index]);
321 elem->subdomain_id() = subdomainIDs[0];
323 if (index == standard + 1)
324 boundary_info.add_side(
elem, 2, 1);
332 limit =
static_cast<int>(num_total_nodes) - standard - 2;
336 while (index < limit)
339 Elem *
elem =
mesh.add_elem(
new Quad4);
340 elem->set_node(0, nodes[index]);
343 elem->set_node(3, nodes[index + 1]);
345 for (
int i = 0; i < static_cast<int>(subdomainIDs.size()) - 1; ++i)
346 if (index < limit - (standard + 1) * i && index >= limit - (standard + 1) * (i + 1))
347 elem->subdomain_id() = subdomainIDs[subdomainIDs.size() - 1 - i];
352 if ((index - initial) % (standard + 1) == 0)
353 boundary_info.add_side(
elem, 0, 2);
354 if ((index -
final) % (standard + 1) == 0)
355 boundary_info.add_side(
elem, 2, 1);
356 if (index > limit - (standard + 1))
360 if (index < limit - standard + standard / 2)
361 boundary_info.add_side(
elem, 1, 3);
363 boundary_info.add_side(
elem, 1, 4);
367 boundary_info.add_side(
elem, 1, 3);
371 if (index == (num_nodes_boundary + counter * (standard + 1)) - 1)
379 boundary_info.sideset_name(1) =
"left";
380 boundary_info.sideset_name(2) =
"bottom";
383 boundary_info.sideset_name(3) =
"outer";
386 boundary_info.sideset_name(3) =
"right";
387 boundary_info.sideset_name(4) =
"top";
393 boundary_info.sideset_name(1) =
"bottom";
394 boundary_info.sideset_name(2) =
"right";
397 boundary_info.sideset_name(3) =
"outer";
400 boundary_info.sideset_name(3) =
"top";
401 boundary_info.sideset_name(4) =
"left";
407 boundary_info.sideset_name(1) =
"right";
408 boundary_info.sideset_name(2) =
"top";
411 boundary_info.sideset_name(3) =
"outer";
414 boundary_info.sideset_name(3) =
"left";
415 boundary_info.sideset_name(4) =
"bottom";
418 else if (
_portion ==
"bottom_right")
421 boundary_info.sideset_name(1) =
"top";
422 boundary_info.sideset_name(2) =
"left";
425 boundary_info.sideset_name(3) =
"outer";
428 boundary_info.sideset_name(3) =
"bottom";
429 boundary_info.sideset_name(4) =
"right";
435 ReplicatedMesh other_mesh(
mesh);
447 mesh.prepare_for_use();
448 other_mesh.prepare_for_use();
449 mesh.stitch_meshes(other_mesh, 1, 3, TOLERANCE,
true);
450 mesh.get_boundary_info().sideset_name(1) =
"left";
451 mesh.get_boundary_info().sideset_name(2) =
"bottom";
452 mesh.get_boundary_info().sideset_name(3) =
"right";
453 mesh.get_boundary_info().sideset_name(4) =
"top";
460 mesh.prepare_for_use();
461 other_mesh.prepare_for_use();
462 mesh.stitch_meshes(other_mesh, 1, 1, TOLERANCE,
true);
466 mesh.get_boundary_info().sideset_name(1) =
"bottom";
467 mesh.get_boundary_info().sideset_name(2) =
"outer";
474 ReplicatedMesh other_mesh(
mesh);
486 mesh.prepare_for_use();
487 other_mesh.prepare_for_use();
488 mesh.stitch_meshes(other_mesh, 2, 4, TOLERANCE,
true);
489 mesh.get_boundary_info().sideset_name(1) =
"left";
490 mesh.get_boundary_info().sideset_name(2) =
"bottom";
491 mesh.get_boundary_info().sideset_name(3) =
"right";
492 mesh.get_boundary_info().sideset_name(4) =
"top";
499 mesh.prepare_for_use();
500 other_mesh.prepare_for_use();
501 mesh.stitch_meshes(other_mesh, 2, 2, TOLERANCE,
true);
504 mesh.get_boundary_info().sideset_name(1) =
"left";
505 mesh.get_boundary_info().sideset_name(2) =
"outer";
511 ReplicatedMesh other_mesh(
mesh);
534 mesh.prepare_for_use();
535 other_mesh.prepare_for_use();
536 mesh.stitch_meshes(other_mesh, 4, 2, TOLERANCE,
true);
537 mesh.get_boundary_info().sideset_name(1) =
"left";
538 mesh.get_boundary_info().sideset_name(2) =
"bottom";
539 mesh.get_boundary_info().sideset_name(3) =
"right";
540 mesh.get_boundary_info().sideset_name(4) =
"top";
547 mesh.prepare_for_use();
548 other_mesh.prepare_for_use();
549 mesh.stitch_meshes(other_mesh, 1, 1, TOLERANCE,
true);
553 mesh.get_boundary_info().sideset_name(1) =
"right";
554 mesh.get_boundary_info().sideset_name(2) =
"outer";
560 ReplicatedMesh other_mesh(
mesh);
582 mesh.prepare_for_use();
583 other_mesh.prepare_for_use();
584 mesh.stitch_meshes(other_mesh, 1, 3, TOLERANCE,
true);
585 mesh.get_boundary_info().sideset_name(1) =
"left";
586 mesh.get_boundary_info().sideset_name(2) =
"bottom";
587 mesh.get_boundary_info().sideset_name(3) =
"right";
588 mesh.get_boundary_info().sideset_name(4) =
"top";
595 mesh.prepare_for_use();
596 other_mesh.prepare_for_use();
597 mesh.stitch_meshes(other_mesh, 1, 1, TOLERANCE,
true);
601 mesh.get_boundary_info().sideset_name(1) =
"top";
602 mesh.get_boundary_info().sideset_name(2) =
"outer";
608 ReplicatedMesh portion_two(
mesh);
623 mesh.prepare_for_use();
624 portion_two.prepare_for_use();
626 mesh.stitch_meshes(portion_two, 1, 3, TOLERANCE,
true);
629 ReplicatedMesh portion_bottom(
mesh);
638 mesh.prepare_for_use();
639 portion_bottom.prepare_for_use();
641 mesh.stitch_meshes(portion_bottom, 2, 4, TOLERANCE,
true);
643 mesh.get_boundary_info().sideset_name(1) =
"left";
644 mesh.get_boundary_info().sideset_name(2) =
"bottom";
645 mesh.get_boundary_info().sideset_name(3) =
"right";
646 mesh.get_boundary_info().sideset_name(4) =
"top";
647 portion_bottom.clear();
655 mesh.prepare_for_use();
656 portion_two.prepare_for_use();
657 mesh.stitch_meshes(portion_two, 1, 1, TOLERANCE,
true);
659 ReplicatedMesh portion_bottom(
mesh);
662 mesh.prepare_for_use();
663 portion_bottom.prepare_for_use();
664 mesh.stitch_meshes(portion_bottom, 2, 2, TOLERANCE,
true);
666 mesh.get_boundary_info().sideset_name(1) =
"outer";
667 portion_bottom.clear();
673 mesh.prepare_for_use();
static InputParameters validParams()
Typical "Moose-style" constructor and copy constructor.
virtual std::unique_ptr< MooseMesh > safeClone() const override
A safer version of the clone() method that hands back an allocated object wrapped in a smart pointer...
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
Real _inner_mesh_fraction
Size of inner square in relation to radius of the innermost concentric circle.
virtual void buildMesh() override
Must be overridden by child classes.
static InputParameters validParams()
unsigned int _num_sectors
Number of sectors in one quadrant.
std::vector< Real > _radii
Radii of concentric circles.
std::unique_ptr< T > copyConstruct(const T &object)
Copy constructs the object object.
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
MooseApp & _app
The MOOSE application this is associated with.
ConcentricCircleMesh(const InputParameters ¶meters)
bool _has_outer_square
Adding the moderator is optional.
std::vector< unsigned int > _rings
Number of rings in each circle or in the moderator.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
registerMooseObject("MooseApp", ConcentricCircleMesh)
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
Mesh generated from parameters.
virtual Elem * elem(const dof_id_type i)
Various accessors (pointers/references) for Elem "i".
bool _preserve_volumes
Volume preserving function is optional.
void ErrorVector unsigned int
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template pow< 2 >(tan(_arg))+1.0) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(sqrt
MooseEnum _portion
Control of which portion of mesh will be developed.