13 #include "libmesh/cell_prism6.h" 14 #include "libmesh/unstructured_mesh.h" 23 "Creates a detailed mesh of subchannels in a square lattice arrangement");
26 params.
addParam<
Real>(
"unheated_length_entry", 0.0,
"Unheated length at entry [m]");
28 params.
addParam<
Real>(
"unheated_length_exit", 0.0,
"Unheated length at exit [m]");
29 params.
addRequiredParam<
unsigned int>(
"n_cells",
"The number of cells in the axial direction");
30 params.
addRequiredParam<
unsigned int>(
"nx",
"Number of channels in the x direction [-]");
31 params.
addRequiredParam<
unsigned int>(
"ny",
"Number of channels in the y direction [-]");
34 "The side gap, not to be confused with the gap between pins, this refers to the gap " 35 "next to the duct or else the distance between the subchannel centroid to the duct wall." 36 "distance(edge pin center, duct wall) = pitch / 2 + side_gap [m]");
38 params.
addParam<
unsigned int>(
"block_id", 0,
"Block ID used for the mesh subdomain.");
45 _unheated_length_entry(getParam<
Real>(
"unheated_length_entry")),
46 _heated_length(getParam<
Real>(
"heated_length")),
47 _unheated_length_exit(getParam<
Real>(
"unheated_length_exit")),
48 _pitch(getParam<
Real>(
"pitch")),
49 _pin_diameter(getParam<
Real>(
"pin_diameter")),
50 _n_cells(getParam<unsigned
int>(
"n_cells")),
51 _nx(getParam<unsigned
int>(
"nx")),
52 _ny(getParam<unsigned
int>(
"ny")),
53 _n_channels(_nx * _ny),
54 _side_gap(getParam<
Real>(
"side_gap")),
55 _block_id(getParam<unsigned
int>(
"block_id"))
59 for (
unsigned int i = 0; i <
_n_cells + 1; i++)
66 for (
unsigned int j = 0;
j < 3;
j++)
73 for (
unsigned int iy = 0; iy <
_ny; iy++)
75 for (
unsigned int ix = 0; ix <
_nx; ix++)
77 unsigned int i_ch =
_nx * iy + ix;
78 bool is_corner = (ix == 0 && iy == 0) || (ix ==
_nx - 1 && iy == 0) ||
79 (ix == 0 && iy ==
_ny - 1) || (ix ==
_nx - 1 && iy ==
_ny - 1);
80 bool is_edge = (ix == 0 || iy == 0 || ix ==
_nx - 1 || iy ==
_ny - 1);
98 std::unique_ptr<MeshBase>
102 BoundaryInfo & boundary_info = mesh_base->get_boundary_info();
103 mesh_base->set_spatial_dimension(3);
106 const unsigned int theta_res = 16;
108 const unsigned int points_per_quad = theta_res / 4 + 1;
113 const unsigned int points_per_center = points_per_quad * 4 + 1;
116 const unsigned int points_per_corner = points_per_quad * 1 + 1 + 3;
119 const unsigned int points_per_side = points_per_quad * 2 + 1 + 2;
123 const unsigned int elems_per_center = theta_res + 4;
124 const unsigned int elems_per_corner = theta_res / 4 + 4;
125 const unsigned int elems_per_side = theta_res / 2 + 4;
128 unsigned int n_center, n_side, n_corner;
144 n_side = 2 * (
_ny - 2) + 2 * (
_nx - 2);
149 const unsigned int points_per_level =
150 n_corner * points_per_corner + n_side * points_per_side + n_center * points_per_center;
151 const unsigned int elems_per_level =
152 n_corner * elems_per_corner + n_side * elems_per_side + n_center * elems_per_center;
153 const unsigned int n_points = points_per_level * (
_n_cells + 1);
154 const unsigned int n_elems = elems_per_level *
_n_cells;
155 mesh_base->reserve_nodes(n_points);
156 mesh_base->reserve_elem(n_elems);
159 std::array<Point, theta_res + 1> circle_points;
162 for (
unsigned int i = 0; i < theta_res + 1; i++)
164 circle_points[i](0) =
radius * std::cos(theta);
165 circle_points[i](1) =
radius * std::sin(theta);
166 theta += 2 * M_PI / theta_res;
174 const Real shrink_factor = 0.99999;
175 std::array<Point, 4> quadrant_centers;
176 quadrant_centers[0] = Point(
_pitch * 0.5 * shrink_factor,
_pitch * 0.5 * shrink_factor, 0);
177 quadrant_centers[1] = Point(-
_pitch * 0.5 * shrink_factor,
_pitch * 0.5 * shrink_factor, 0);
178 quadrant_centers[2] = Point(-
_pitch * 0.5 * shrink_factor, -
_pitch * 0.5 * shrink_factor, 0);
179 quadrant_centers[3] = Point(
_pitch * 0.5 * shrink_factor, -
_pitch * 0.5 * shrink_factor, 0);
181 const unsigned int m = theta_res / 4;
189 std::array<Point, points_per_center> center_points;
192 for (
unsigned int i = 0; i < 4; i++)
202 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
204 auto c_pt = circle_points[start - ii];
205 center_points[i * points_per_quad + ii + 1] = quadrant_centers[i] + c_pt;
217 std::array<Point, points_per_corner> tl_corner_points;
219 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
221 auto c_pt = circle_points[2 * m - ii];
222 tl_corner_points[ii + 1] = quadrant_centers[3] + c_pt;
224 tl_corner_points[points_per_quad + 1] = Point(
_pitch * 0.5 * shrink_factor,
_side_gap, 0);
226 tl_corner_points[points_per_quad + 3] = Point(-
_side_gap, -
_pitch * 0.5 * shrink_factor, 0);
236 std::array<Point, points_per_corner> tr_corner_points;
238 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
240 auto c_pt = circle_points[m - ii];
241 tr_corner_points[ii + 1] = quadrant_centers[2] + c_pt;
243 tr_corner_points[points_per_quad + 1] = Point(
_side_gap, -
_pitch * 0.5 * shrink_factor, 0);
245 tr_corner_points[points_per_quad + 3] = Point(-
_pitch * 0.5 * shrink_factor,
_side_gap, 0);
255 std::array<Point, points_per_corner> bl_corner_points;
257 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
259 auto c_pt = circle_points[3 * m - ii];
260 bl_corner_points[ii + 1] = quadrant_centers[0] + c_pt;
262 bl_corner_points[points_per_quad + 1] = Point(-
_side_gap,
_pitch * 0.5 * shrink_factor, 0);
264 bl_corner_points[points_per_quad + 3] = Point(
_pitch * 0.5 * shrink_factor, -
_side_gap, 0);
274 std::array<Point, points_per_corner> br_corner_points;
276 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
278 auto c_pt = circle_points[4 * m - ii];
279 br_corner_points[ii + 1] = quadrant_centers[1] + c_pt;
281 br_corner_points[points_per_quad + 1] = Point(-
_pitch * 0.5 * shrink_factor, -
_side_gap, 0);
283 br_corner_points[points_per_quad + 3] = Point(
_side_gap,
_pitch * 0.5 * shrink_factor, 0);
293 std::array<Point, points_per_side> top_points;
295 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
297 auto c_pt = circle_points[m - ii];
298 top_points[ii + 1] = quadrant_centers[2] + c_pt;
300 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
302 auto c_pt = circle_points[2 * m - ii];
303 top_points[points_per_quad + ii + 1] = quadrant_centers[3] + c_pt;
305 top_points[2 * points_per_quad + 1] = Point(
_pitch * 0.5 * shrink_factor,
_side_gap, 0);
306 top_points[2 * points_per_quad + 2] = Point(-
_pitch * 0.5 * shrink_factor,
_side_gap, 0);
316 std::array<Point, points_per_side> left_points;
318 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
320 auto c_pt = circle_points[2 * m - ii];
321 left_points[ii + 1] = quadrant_centers[3] + c_pt;
323 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
325 auto c_pt = circle_points[3 * m - ii];
326 left_points[points_per_quad + ii + 1] = quadrant_centers[0] + c_pt;
328 left_points[2 * points_per_quad + 1] = Point(-
_side_gap,
_pitch * 0.5 * shrink_factor, 0);
329 left_points[2 * points_per_quad + 2] = Point(-
_side_gap, -
_pitch * 0.5 * shrink_factor, 0);
339 std::array<Point, points_per_side> bottom_points;
341 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
343 auto c_pt = circle_points[3 * m - ii];
344 bottom_points[ii + 1] = quadrant_centers[0] + c_pt;
346 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
348 auto c_pt = circle_points[4 * m - ii];
349 bottom_points[points_per_quad + ii + 1] = quadrant_centers[1] + c_pt;
351 bottom_points[2 * points_per_quad + 1] = Point(-
_pitch * 0.5 * shrink_factor, -
_side_gap, 0);
352 bottom_points[2 * points_per_quad + 2] = Point(
_pitch * 0.5 * shrink_factor, -
_side_gap, 0);
362 std::array<Point, points_per_side> right_points;
364 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
366 auto c_pt = circle_points[4 * m - ii];
367 right_points[ii + 1] = quadrant_centers[1] + c_pt;
369 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
371 auto c_pt = circle_points[m - ii];
372 right_points[points_per_quad + ii + 1] = quadrant_centers[2] + c_pt;
374 right_points[2 * points_per_quad + 1] = Point(
_side_gap, -
_pitch * 0.5 * shrink_factor, 0);
375 right_points[2 * points_per_quad + 2] = Point(
_side_gap,
_pitch * 0.5 * shrink_factor, 0);
381 unsigned int node_id = 0;
384 for (
unsigned int iy = 0; iy <
_ny; iy++)
386 Point y0 = {0,
_pitch * iy - offset_y, 0};
387 for (
unsigned int ix = 0; ix <
_nx; ix++)
389 Point x0 = {
_pitch * ix - offset_x, 0, 0};
393 if (
_nx == 1 && iy == 0)
395 for (
unsigned int i = 0; i < points_per_side; i++)
396 mesh_base->add_point(bottom_points[i] + x0 + y0 + z0, node_id++);
398 if (
_nx == 1 && iy == 1)
400 for (
unsigned int i = 0; i < points_per_side; i++)
401 mesh_base->add_point(top_points[i] + x0 + y0 + z0, node_id++);
403 if (
_ny == 1 && ix == 0)
405 for (
unsigned int i = 0; i < points_per_side; i++)
406 mesh_base->add_point(left_points[i] + x0 + y0 + z0, node_id++);
408 if (
_ny == 1 && ix == 1)
410 for (
unsigned int i = 0; i < points_per_side; i++)
411 mesh_base->add_point(right_points[i] + x0 + y0 + z0, node_id++);
419 unsigned int node_id = 0;
422 for (
unsigned int iy = 0; iy <
_ny; iy++)
424 Point y0 = {0,
_pitch * iy - offset_y, 0};
425 for (
unsigned int ix = 0; ix <
_nx; ix++)
427 Point x0 = {
_pitch * ix - offset_x, 0, 0};
435 for (
unsigned int i = 0; i < points_per_side; i++)
436 mesh_base->add_point(bottom_points[i] + x0 + y0 + z0, node_id++);
438 else if (iy ==
_ny - 1)
440 for (
unsigned int i = 0; i < points_per_side; i++)
441 mesh_base->add_point(top_points[i] + x0 + y0 + z0, node_id++);
445 for (
unsigned int i = 0; i < points_per_center; i++)
446 mesh_base->add_point(center_points[i] + x0 + y0 + z0, node_id++);
453 for (
unsigned int i = 0; i < points_per_side; i++)
454 mesh_base->add_point(left_points[i] + x0 + y0 + z0, node_id++);
456 else if (ix ==
_nx - 1)
458 for (
unsigned int i = 0; i < points_per_side; i++)
459 mesh_base->add_point(right_points[i] + x0 + y0 + z0, node_id++);
463 for (
unsigned int i = 0; i < points_per_center; i++)
464 mesh_base->add_point(center_points[i] + x0 + y0 + z0, node_id++);
473 unsigned int node_id = 0;
476 for (
unsigned int iy = 0; iy <
_ny; iy++)
478 Point y0 = {0,
_pitch * iy - offset_y, 0};
479 for (
unsigned int ix = 0; ix <
_nx; ix++)
481 Point x0 = {
_pitch * ix - offset_x, 0, 0};
482 if (ix == 0 && iy == 0)
487 for (
unsigned int i = 0; i < points_per_corner; i++)
488 mesh_base->add_point(bl_corner_points[i] + x0 + y0 + z0, node_id++);
491 else if (ix ==
_nx - 1 && iy == 0)
496 for (
unsigned int i = 0; i < points_per_corner; i++)
497 mesh_base->add_point(br_corner_points[i] + x0 + y0 + z0, node_id++);
500 else if (ix == 0 && iy ==
_ny - 1)
505 for (
unsigned int i = 0; i < points_per_corner; i++)
506 mesh_base->add_point(tl_corner_points[i] + x0 + y0 + z0, node_id++);
509 else if (ix ==
_nx - 1 && iy ==
_ny - 1)
514 for (
unsigned int i = 0; i < points_per_corner; i++)
515 mesh_base->add_point(tr_corner_points[i] + x0 + y0 + z0, node_id++);
518 else if (ix == 0 && (iy !=
_ny - 1 || iy != 0))
523 for (
unsigned int i = 0; i < points_per_side; i++)
524 mesh_base->add_point(left_points[i] + x0 + y0 + z0, node_id++);
527 else if (ix ==
_nx - 1 && (iy !=
_ny - 1 || iy != 0))
532 for (
unsigned int i = 0; i < points_per_side; i++)
533 mesh_base->add_point(right_points[i] + x0 + y0 + z0, node_id++);
536 else if (iy == 0 && (ix !=
_nx - 1 || ix != 0))
541 for (
unsigned int i = 0; i < points_per_side; i++)
542 mesh_base->add_point(bottom_points[i] + x0 + y0 + z0, node_id++);
545 else if (iy ==
_ny - 1 && (ix !=
_nx - 1 || ix != 0))
550 for (
unsigned int i = 0; i < points_per_side; i++)
551 mesh_base->add_point(top_points[i] + x0 + y0 + z0, node_id++);
559 for (
unsigned int i = 0; i < points_per_center; i++)
560 mesh_base->add_point(center_points[i] + x0 + y0 + z0, node_id++);
572 unsigned int elem_id = 0;
573 for (
unsigned int iy = 0; iy <
_ny; iy++)
575 for (
unsigned int ix = 0; ix <
_nx; ix++)
577 unsigned int i_ch =
_nx * iy + ix;
578 for (
unsigned int iz = 0; iz <
_n_cells; iz++)
580 for (
unsigned int i = 0; i < elems_per_side; i++)
582 Elem * elem =
new Prism6;
584 elem->set_id(elem_id++);
585 elem = mesh_base->add_elem(elem);
587 unsigned int indx1 = iz * points_per_side + points_per_side * (
_n_cells + 1) * i_ch;
590 (iz + 1) * points_per_side + points_per_side * (
_n_cells + 1) * i_ch;
591 unsigned int elems_per_channel = elems_per_side;
592 elem->set_node(0, mesh_base->node_ptr(indx1));
593 elem->set_node(1, mesh_base->node_ptr(indx1 + i + 1));
594 if (i != elems_per_channel - 1)
595 elem->set_node(2, mesh_base->node_ptr(indx1 + i + 2));
597 elem->set_node(2, mesh_base->node_ptr(indx1 + 1));
599 elem->set_node(3, mesh_base->node_ptr(indx2));
600 elem->set_node(4, mesh_base->node_ptr(indx2 + i + 1));
601 if (i != elems_per_channel - 1)
602 elem->set_node(5, mesh_base->node_ptr(indx2 + i + 2));
604 elem->set_node(5, mesh_base->node_ptr(indx2 + 1));
607 boundary_info.add_side(elem, 0, 0);
609 boundary_info.add_side(elem, 4, 1);
614 boundary_info.sideset_name(0) =
"inlet";
615 boundary_info.sideset_name(1) =
"outlet";
617 mesh_base->prepare_for_use();
621 unsigned int elem_id = 0;
622 unsigned int number_of_corner = 0;
623 unsigned int number_of_side = 0;
624 unsigned int number_of_center = 0;
625 unsigned int elems_per_channel = 0;
626 unsigned int points_per_channel = 0;
627 for (
unsigned int iy = 0; iy <
_ny; iy++)
629 for (
unsigned int ix = 0; ix <
_nx; ix++)
631 unsigned int i_ch =
_nx * iy + ix;
637 elems_per_channel = elems_per_side;
638 points_per_channel = points_per_side;
644 elems_per_channel = elems_per_center;
645 points_per_channel = points_per_center;
647 for (
unsigned int iz = 0; iz <
_n_cells; iz++)
649 unsigned int elapsed_points = number_of_corner * points_per_corner * (
_n_cells + 1) +
650 number_of_side * points_per_side * (
_n_cells + 1) +
651 number_of_center * points_per_center * (
_n_cells + 1) -
652 points_per_channel * (
_n_cells + 1);
654 unsigned int indx1 = iz * points_per_channel + elapsed_points;
656 unsigned int indx2 = (iz + 1) * points_per_channel + elapsed_points;
658 for (
unsigned int i = 0; i < elems_per_channel; i++)
660 Elem * elem =
new Prism6;
662 elem->set_id(elem_id++);
663 elem = mesh_base->add_elem(elem);
665 elem->set_node(0, mesh_base->node_ptr(indx1));
666 elem->set_node(1, mesh_base->node_ptr(indx1 + i + 1));
667 if (i != elems_per_channel - 1)
668 elem->set_node(2, mesh_base->node_ptr(indx1 + i + 2));
670 elem->set_node(2, mesh_base->node_ptr(indx1 + 1));
672 elem->set_node(3, mesh_base->node_ptr(indx2));
673 elem->set_node(4, mesh_base->node_ptr(indx2 + i + 1));
674 if (i != elems_per_channel - 1)
675 elem->set_node(5, mesh_base->node_ptr(indx2 + i + 2));
677 elem->set_node(5, mesh_base->node_ptr(indx2 + 1));
680 boundary_info.add_side(elem, 0, 0);
682 boundary_info.add_side(elem, 4, 1);
687 boundary_info.sideset_name(0) =
"inlet";
688 boundary_info.sideset_name(1) =
"outlet";
690 mesh_base->prepare_for_use();
694 unsigned int elem_id = 0;
695 unsigned int number_of_corner = 0;
696 unsigned int number_of_side = 0;
697 unsigned int number_of_center = 0;
698 unsigned int elems_per_channel = 0;
699 unsigned int points_per_channel = 0;
700 for (
unsigned int iy = 0; iy <
_ny; iy++)
702 for (
unsigned int ix = 0; ix <
_nx; ix++)
704 unsigned int i_ch =
_nx * iy + ix;
709 elems_per_channel = elems_per_corner;
710 points_per_channel = points_per_corner;
715 elems_per_channel = elems_per_side;
716 points_per_channel = points_per_side;
721 elems_per_channel = elems_per_center;
722 points_per_channel = points_per_center;
724 for (
unsigned int iz = 0; iz <
_n_cells; iz++)
726 unsigned int elapsed_points = number_of_corner * points_per_corner * (
_n_cells + 1) +
727 number_of_side * points_per_side * (
_n_cells + 1) +
728 number_of_center * points_per_center * (
_n_cells + 1) -
729 points_per_channel * (
_n_cells + 1);
731 unsigned int indx1 = iz * points_per_channel + elapsed_points;
733 unsigned int indx2 = (iz + 1) * points_per_channel + elapsed_points;
735 for (
unsigned int i = 0; i < elems_per_channel; i++)
737 Elem * elem =
new Prism6;
739 elem->set_id(elem_id++);
740 elem = mesh_base->add_elem(elem);
742 elem->set_node(0, mesh_base->node_ptr(indx1));
743 elem->set_node(1, mesh_base->node_ptr(indx1 + i + 1));
744 if (i != elems_per_channel - 1)
745 elem->set_node(2, mesh_base->node_ptr(indx1 + i + 2));
747 elem->set_node(2, mesh_base->node_ptr(indx1 + 1));
749 elem->set_node(3, mesh_base->node_ptr(indx2));
750 elem->set_node(4, mesh_base->node_ptr(indx2 + i + 1));
751 if (i != elems_per_channel - 1)
752 elem->set_node(5, mesh_base->node_ptr(indx2 + i + 2));
754 elem->set_node(5, mesh_base->node_ptr(indx2 + 1));
757 boundary_info.add_side(elem, 0, 0);
759 boundary_info.add_side(elem, 4, 1);
764 boundary_info.sideset_name(0) =
"inlet";
765 boundary_info.sideset_name(1) =
"outlet";
767 mesh_base->prepare_for_use();
registerMooseObject("SubChannelApp", SCMDetailedQuadSubChannelMeshGenerator)
const Real _pitch
Distance between the neighbor fuel pins, pitch.
const unsigned int _n_cells
Number of cells in the axial direction.
const Real _heated_length
heated length of the fuel Pin
std::vector< Real > _z_grid
axial location of nodes
unsigned int _n_channels
Total number of subchannels.
const unsigned int _nx
Number of subchannels in the x direction.
const std::string & name() const
std::vector< std::vector< Real > > _subchannel_position
x,y coordinates of the subchannel centroids
const Real _side_gap
The side gap, not to be confused with the gap between pins, this refers to the gap next to the duct o...
static InputParameters validParams()
const Real _pin_diameter
fuel Pin diameter
SCMDetailedQuadSubChannelMeshGenerator(const InputParameters ¶meters)
const unsigned int _ny
Number of subchannels in the y direction.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Mesh generator that builds a 3D mesh representing quadrilateral subchannels.
const Real _unheated_length_exit
unheated length of the fuel Pin at the exit of the assembly
std::vector< EChannelType > _subch_type
Subchannel type.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
EChannelType getSubchannelType(unsigned int index) const
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
const Real _unheated_length_entry
unheated length of the fuel Pin at the entry of the assembly
const unsigned int & _block_id
Subdomain ID used for the mesh block.
static InputParameters validParams()
virtual std::unique_ptr< MeshBase > generate() override
void ErrorVector unsigned int