13 #include "libmesh/cell_prism6.h" 14 #include "libmesh/unstructured_mesh.h" 18 DetailedQuadSubChannelMeshGenerator,
27 "Creates a detailed mesh of subchannels in a square lattice arrangement");
30 params.
addParam<
Real>(
"unheated_length_entry", 0.0,
"Unheated length at entry [m]");
32 params.
addParam<
Real>(
"unheated_length_exit", 0.0,
"Unheated length at exit [m]");
33 params.
addRequiredParam<
unsigned int>(
"n_cells",
"The number of cells in the axial direction");
34 params.
addRequiredParam<
unsigned int>(
"nx",
"Number of channels in the x direction [-]");
35 params.
addRequiredParam<
unsigned int>(
"ny",
"Number of channels in the y direction [-]");
37 "(Its an added distance between a perimetric pin and the duct: " 38 "Edge Pitch W = pitch/2 - pin_diameter/2 + gap) [m]");
39 params.
addParam<
unsigned int>(
"block_id", 0,
"Block ID used for the mesh subdomain.");
46 _unheated_length_entry(getParam<
Real>(
"unheated_length_entry")),
47 _heated_length(getParam<
Real>(
"heated_length")),
48 _unheated_length_exit(getParam<
Real>(
"unheated_length_exit")),
49 _pitch(getParam<
Real>(
"pitch")),
50 _pin_diameter(getParam<
Real>(
"pin_diameter")),
51 _n_cells(getParam<unsigned
int>(
"n_cells")),
52 _nx(getParam<unsigned
int>(
"nx")),
53 _ny(getParam<unsigned
int>(
"ny")),
54 _n_channels(_nx * _ny),
55 _gap(getParam<
Real>(
"gap")),
56 _block_id(getParam<unsigned
int>(
"block_id"))
60 for (
unsigned int i = 0; i <
_n_cells + 1; i++)
67 for (
unsigned int j = 0;
j < 3;
j++)
74 for (
unsigned int iy = 0; iy <
_ny; iy++)
76 for (
unsigned int ix = 0; ix <
_nx; ix++)
78 unsigned int i_ch =
_nx * iy + ix;
79 bool is_corner = (ix == 0 && iy == 0) || (ix ==
_nx - 1 && iy == 0) ||
80 (ix == 0 && iy ==
_ny - 1) || (ix ==
_nx - 1 && iy ==
_ny - 1);
81 bool is_edge = (ix == 0 || iy == 0 || ix ==
_nx - 1 || iy ==
_ny - 1);
99 std::unique_ptr<MeshBase>
103 BoundaryInfo & boundary_info = mesh_base->get_boundary_info();
104 mesh_base->set_spatial_dimension(3);
107 const unsigned int theta_res = 16;
109 const unsigned int points_per_quad = theta_res / 4 + 1;
114 const unsigned int points_per_center = points_per_quad * 4 + 1;
117 const unsigned int points_per_corner = points_per_quad * 1 + 1 + 3;
120 const unsigned int points_per_side = points_per_quad * 2 + 1 + 2;
124 const unsigned int elems_per_center = theta_res + 4;
125 const unsigned int elems_per_corner = theta_res / 4 + 4;
126 const unsigned int elems_per_side = theta_res / 2 + 4;
129 unsigned int n_center, n_side, n_corner;
145 n_side = 2 * (
_ny - 2) + 2 * (
_nx - 2);
150 const unsigned int points_per_level =
151 n_corner * points_per_corner + n_side * points_per_side + n_center * points_per_center;
152 const unsigned int elems_per_level =
153 n_corner * elems_per_corner + n_side * elems_per_side + n_center * elems_per_center;
154 const unsigned int n_points = points_per_level * (
_n_cells + 1);
155 const unsigned int n_elems = elems_per_level *
_n_cells;
156 mesh_base->reserve_nodes(n_points);
157 mesh_base->reserve_elem(n_elems);
160 std::array<Point, theta_res + 1> circle_points;
163 for (
unsigned int i = 0; i < theta_res + 1; i++)
165 circle_points[i](0) =
radius * std::cos(theta);
166 circle_points[i](1) =
radius * std::sin(theta);
167 theta += 2 * M_PI / theta_res;
175 const Real shrink_factor = 0.99999;
176 std::array<Point, 4> quadrant_centers;
177 quadrant_centers[0] = Point(
_pitch * 0.5 * shrink_factor,
_pitch * 0.5 * shrink_factor, 0);
178 quadrant_centers[1] = Point(-
_pitch * 0.5 * shrink_factor,
_pitch * 0.5 * shrink_factor, 0);
179 quadrant_centers[2] = Point(-
_pitch * 0.5 * shrink_factor, -
_pitch * 0.5 * shrink_factor, 0);
180 quadrant_centers[3] = Point(
_pitch * 0.5 * shrink_factor, -
_pitch * 0.5 * shrink_factor, 0);
182 const unsigned int m = theta_res / 4;
190 std::array<Point, points_per_center> center_points;
193 for (
unsigned int i = 0; i < 4; i++)
203 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
205 auto c_pt = circle_points[start - ii];
206 center_points[i * points_per_quad + ii + 1] = quadrant_centers[i] + c_pt;
218 std::array<Point, points_per_corner> tl_corner_points;
220 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
222 auto c_pt = circle_points[2 * m - ii];
223 tl_corner_points[ii + 1] = quadrant_centers[3] + c_pt;
225 tl_corner_points[points_per_quad + 1] =
226 Point(
_pitch * 0.5 * shrink_factor,
_pitch * 0.25 * shrink_factor +
_gap, 0);
227 tl_corner_points[points_per_quad + 2] =
229 tl_corner_points[points_per_quad + 3] =
230 Point(-
_pitch * 0.25 * shrink_factor -
_gap, -
_pitch * 0.5 * shrink_factor, 0);
240 std::array<Point, points_per_corner> tr_corner_points;
242 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
244 auto c_pt = circle_points[m - ii];
245 tr_corner_points[ii + 1] = quadrant_centers[2] + c_pt;
247 tr_corner_points[points_per_quad + 1] =
248 Point(
_pitch * 0.25 * shrink_factor +
_gap, -
_pitch * 0.5 * shrink_factor, 0);
249 tr_corner_points[points_per_quad + 2] =
251 tr_corner_points[points_per_quad + 3] =
252 Point(-
_pitch * 0.5 * shrink_factor,
_pitch * 0.25 * shrink_factor +
_gap, 0);
262 std::array<Point, points_per_corner> bl_corner_points;
264 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
266 auto c_pt = circle_points[3 * m - ii];
267 bl_corner_points[ii + 1] = quadrant_centers[0] + c_pt;
269 bl_corner_points[points_per_quad + 1] =
270 Point(-
_pitch * 0.25 * shrink_factor -
_gap,
_pitch * 0.5 * shrink_factor, 0);
271 bl_corner_points[points_per_quad + 2] =
273 bl_corner_points[points_per_quad + 3] =
274 Point(
_pitch * 0.5 * shrink_factor, -
_pitch * 0.25 * shrink_factor -
_gap, 0);
284 std::array<Point, points_per_corner> br_corner_points;
286 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
288 auto c_pt = circle_points[4 * m - ii];
289 br_corner_points[ii + 1] = quadrant_centers[1] + c_pt;
291 br_corner_points[points_per_quad + 1] =
292 Point(-
_pitch * 0.5 * shrink_factor, -
_pitch * 0.25 * shrink_factor -
_gap, 0);
293 br_corner_points[points_per_quad + 2] =
295 br_corner_points[points_per_quad + 3] =
296 Point(
_pitch * 0.25 * shrink_factor +
_gap,
_pitch * 0.5 * shrink_factor, 0);
306 std::array<Point, points_per_side> top_points;
308 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
310 auto c_pt = circle_points[m - ii];
311 top_points[ii + 1] = quadrant_centers[2] + c_pt;
313 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
315 auto c_pt = circle_points[2 * m - ii];
316 top_points[points_per_quad + ii + 1] = quadrant_centers[3] + c_pt;
318 top_points[2 * points_per_quad + 1] =
319 Point(
_pitch * 0.5 * shrink_factor,
_pitch * 0.25 * shrink_factor +
_gap, 0);
320 top_points[2 * points_per_quad + 2] =
321 Point(-
_pitch * 0.5 * shrink_factor,
_pitch * 0.25 * shrink_factor +
_gap, 0);
331 std::array<Point, points_per_side> left_points;
333 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
335 auto c_pt = circle_points[2 * m - ii];
336 left_points[ii + 1] = quadrant_centers[3] + c_pt;
338 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
340 auto c_pt = circle_points[3 * m - ii];
341 left_points[points_per_quad + ii + 1] = quadrant_centers[0] + c_pt;
343 left_points[2 * points_per_quad + 1] =
344 Point(-
_pitch * 0.25 * shrink_factor -
_gap,
_pitch * 0.5 * shrink_factor, 0);
345 left_points[2 * points_per_quad + 2] =
346 Point(-
_pitch * 0.25 * shrink_factor -
_gap, -
_pitch * 0.5 * shrink_factor, 0);
356 std::array<Point, points_per_side> bottom_points;
358 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
360 auto c_pt = circle_points[3 * m - ii];
361 bottom_points[ii + 1] = quadrant_centers[0] + c_pt;
363 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
365 auto c_pt = circle_points[4 * m - ii];
366 bottom_points[points_per_quad + ii + 1] = quadrant_centers[1] + c_pt;
368 bottom_points[2 * points_per_quad + 1] =
369 Point(-
_pitch * 0.5 * shrink_factor, -
_pitch * 0.25 * shrink_factor -
_gap, 0);
370 bottom_points[2 * points_per_quad + 2] =
371 Point(
_pitch * 0.5 * shrink_factor, -
_pitch * 0.25 * shrink_factor -
_gap, 0);
381 std::array<Point, points_per_side> right_points;
383 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
385 auto c_pt = circle_points[4 * m - ii];
386 right_points[ii + 1] = quadrant_centers[1] + c_pt;
388 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
390 auto c_pt = circle_points[m - ii];
391 right_points[points_per_quad + ii + 1] = quadrant_centers[2] + c_pt;
393 right_points[2 * points_per_quad + 1] =
394 Point(
_pitch * 0.25 * shrink_factor +
_gap, -
_pitch * 0.5 * shrink_factor, 0);
395 right_points[2 * points_per_quad + 2] =
396 Point(
_pitch * 0.25 * shrink_factor +
_gap,
_pitch * 0.5 * shrink_factor, 0);
402 unsigned int node_id = 0;
405 for (
unsigned int iy = 0; iy <
_ny; iy++)
407 Point y0 = {0,
_pitch * iy - offset_y, 0};
408 for (
unsigned int ix = 0; ix <
_nx; ix++)
410 Point x0 = {
_pitch * ix - offset_x, 0, 0};
414 if (
_nx == 1 && iy == 0)
416 for (
unsigned int i = 0; i < points_per_side; i++)
417 mesh_base->add_point(bottom_points[i] + x0 + y0 + z0, node_id++);
419 if (
_nx == 1 && iy == 1)
421 for (
unsigned int i = 0; i < points_per_side; i++)
422 mesh_base->add_point(top_points[i] + x0 + y0 + z0, node_id++);
424 if (
_ny == 1 && ix == 0)
426 for (
unsigned int i = 0; i < points_per_side; i++)
427 mesh_base->add_point(left_points[i] + x0 + y0 + z0, node_id++);
429 if (
_ny == 1 && ix == 1)
431 for (
unsigned int i = 0; i < points_per_side; i++)
432 mesh_base->add_point(right_points[i] + x0 + y0 + z0, node_id++);
440 unsigned int node_id = 0;
443 for (
unsigned int iy = 0; iy <
_ny; iy++)
445 Point y0 = {0,
_pitch * iy - offset_y, 0};
446 for (
unsigned int ix = 0; ix <
_nx; ix++)
448 Point x0 = {
_pitch * ix - offset_x, 0, 0};
456 for (
unsigned int i = 0; i < points_per_side; i++)
457 mesh_base->add_point(bottom_points[i] + x0 + y0 + z0, node_id++);
459 else if (iy ==
_ny - 1)
461 for (
unsigned int i = 0; i < points_per_side; i++)
462 mesh_base->add_point(top_points[i] + x0 + y0 + z0, node_id++);
466 for (
unsigned int i = 0; i < points_per_center; i++)
467 mesh_base->add_point(center_points[i] + x0 + y0 + z0, node_id++);
474 for (
unsigned int i = 0; i < points_per_side; i++)
475 mesh_base->add_point(left_points[i] + x0 + y0 + z0, node_id++);
477 else if (ix ==
_nx - 1)
479 for (
unsigned int i = 0; i < points_per_side; i++)
480 mesh_base->add_point(right_points[i] + x0 + y0 + z0, node_id++);
484 for (
unsigned int i = 0; i < points_per_center; i++)
485 mesh_base->add_point(center_points[i] + x0 + y0 + z0, node_id++);
494 unsigned int node_id = 0;
497 for (
unsigned int iy = 0; iy <
_ny; iy++)
499 Point y0 = {0,
_pitch * iy - offset_y, 0};
500 for (
unsigned int ix = 0; ix <
_nx; ix++)
502 Point x0 = {
_pitch * ix - offset_x, 0, 0};
503 if (ix == 0 && iy == 0)
508 for (
unsigned int i = 0; i < points_per_corner; i++)
509 mesh_base->add_point(bl_corner_points[i] + x0 + y0 + z0, node_id++);
512 else if (ix ==
_nx - 1 && iy == 0)
517 for (
unsigned int i = 0; i < points_per_corner; i++)
518 mesh_base->add_point(br_corner_points[i] + x0 + y0 + z0, node_id++);
521 else if (ix == 0 && iy ==
_ny - 1)
526 for (
unsigned int i = 0; i < points_per_corner; i++)
527 mesh_base->add_point(tl_corner_points[i] + x0 + y0 + z0, node_id++);
530 else if (ix ==
_nx - 1 && iy ==
_ny - 1)
535 for (
unsigned int i = 0; i < points_per_corner; i++)
536 mesh_base->add_point(tr_corner_points[i] + x0 + y0 + z0, node_id++);
539 else if (ix == 0 && (iy !=
_ny - 1 || iy != 0))
544 for (
unsigned int i = 0; i < points_per_side; i++)
545 mesh_base->add_point(left_points[i] + x0 + y0 + z0, node_id++);
548 else if (ix ==
_nx - 1 && (iy !=
_ny - 1 || iy != 0))
553 for (
unsigned int i = 0; i < points_per_side; i++)
554 mesh_base->add_point(right_points[i] + x0 + y0 + z0, node_id++);
557 else if (iy == 0 && (ix !=
_nx - 1 || ix != 0))
562 for (
unsigned int i = 0; i < points_per_side; i++)
563 mesh_base->add_point(bottom_points[i] + x0 + y0 + z0, node_id++);
566 else if (iy ==
_ny - 1 && (ix !=
_nx - 1 || ix != 0))
571 for (
unsigned int i = 0; i < points_per_side; i++)
572 mesh_base->add_point(top_points[i] + x0 + y0 + z0, node_id++);
580 for (
unsigned int i = 0; i < points_per_center; i++)
581 mesh_base->add_point(center_points[i] + x0 + y0 + z0, node_id++);
593 unsigned int elem_id = 0;
594 for (
unsigned int iy = 0; iy <
_ny; iy++)
596 for (
unsigned int ix = 0; ix <
_nx; ix++)
598 unsigned int i_ch =
_nx * iy + ix;
599 for (
unsigned int iz = 0; iz <
_n_cells; iz++)
601 for (
unsigned int i = 0; i < elems_per_side; i++)
603 Elem * elem =
new Prism6;
605 elem->set_id(elem_id++);
606 elem = mesh_base->add_elem(elem);
608 unsigned int indx1 = iz * points_per_side + points_per_side * (
_n_cells + 1) * i_ch;
611 (iz + 1) * points_per_side + points_per_side * (
_n_cells + 1) * i_ch;
612 unsigned int elems_per_channel = elems_per_side;
613 elem->set_node(0, mesh_base->node_ptr(indx1));
614 elem->set_node(1, mesh_base->node_ptr(indx1 + i + 1));
615 if (i != elems_per_channel - 1)
616 elem->set_node(2, mesh_base->node_ptr(indx1 + i + 2));
618 elem->set_node(2, mesh_base->node_ptr(indx1 + 1));
620 elem->set_node(3, mesh_base->node_ptr(indx2));
621 elem->set_node(4, mesh_base->node_ptr(indx2 + i + 1));
622 if (i != elems_per_channel - 1)
623 elem->set_node(5, mesh_base->node_ptr(indx2 + i + 2));
625 elem->set_node(5, mesh_base->node_ptr(indx2 + 1));
628 boundary_info.add_side(elem, 0, 0);
630 boundary_info.add_side(elem, 4, 1);
635 boundary_info.sideset_name(0) =
"inlet";
636 boundary_info.sideset_name(1) =
"outlet";
638 mesh_base->prepare_for_use();
642 unsigned int elem_id = 0;
643 unsigned int number_of_corner = 0;
644 unsigned int number_of_side = 0;
645 unsigned int number_of_center = 0;
646 unsigned int elems_per_channel = 0;
647 unsigned int points_per_channel = 0;
648 for (
unsigned int iy = 0; iy <
_ny; iy++)
650 for (
unsigned int ix = 0; ix <
_nx; ix++)
652 unsigned int i_ch =
_nx * iy + ix;
658 elems_per_channel = elems_per_side;
659 points_per_channel = points_per_side;
665 elems_per_channel = elems_per_center;
666 points_per_channel = points_per_center;
668 for (
unsigned int iz = 0; iz <
_n_cells; iz++)
670 unsigned int elapsed_points = number_of_corner * points_per_corner * (
_n_cells + 1) +
671 number_of_side * points_per_side * (
_n_cells + 1) +
672 number_of_center * points_per_center * (
_n_cells + 1) -
673 points_per_channel * (
_n_cells + 1);
675 unsigned int indx1 = iz * points_per_channel + elapsed_points;
677 unsigned int indx2 = (iz + 1) * points_per_channel + elapsed_points;
679 for (
unsigned int i = 0; i < elems_per_channel; i++)
681 Elem * elem =
new Prism6;
683 elem->set_id(elem_id++);
684 elem = mesh_base->add_elem(elem);
686 elem->set_node(0, mesh_base->node_ptr(indx1));
687 elem->set_node(1, mesh_base->node_ptr(indx1 + i + 1));
688 if (i != elems_per_channel - 1)
689 elem->set_node(2, mesh_base->node_ptr(indx1 + i + 2));
691 elem->set_node(2, mesh_base->node_ptr(indx1 + 1));
693 elem->set_node(3, mesh_base->node_ptr(indx2));
694 elem->set_node(4, mesh_base->node_ptr(indx2 + i + 1));
695 if (i != elems_per_channel - 1)
696 elem->set_node(5, mesh_base->node_ptr(indx2 + i + 2));
698 elem->set_node(5, mesh_base->node_ptr(indx2 + 1));
701 boundary_info.add_side(elem, 0, 0);
703 boundary_info.add_side(elem, 4, 1);
708 boundary_info.sideset_name(0) =
"inlet";
709 boundary_info.sideset_name(1) =
"outlet";
711 mesh_base->prepare_for_use();
715 unsigned int elem_id = 0;
716 unsigned int number_of_corner = 0;
717 unsigned int number_of_side = 0;
718 unsigned int number_of_center = 0;
719 unsigned int elems_per_channel = 0;
720 unsigned int points_per_channel = 0;
721 for (
unsigned int iy = 0; iy <
_ny; iy++)
723 for (
unsigned int ix = 0; ix <
_nx; ix++)
725 unsigned int i_ch =
_nx * iy + ix;
730 elems_per_channel = elems_per_corner;
731 points_per_channel = points_per_corner;
736 elems_per_channel = elems_per_side;
737 points_per_channel = points_per_side;
742 elems_per_channel = elems_per_center;
743 points_per_channel = points_per_center;
745 for (
unsigned int iz = 0; iz <
_n_cells; iz++)
747 unsigned int elapsed_points = number_of_corner * points_per_corner * (
_n_cells + 1) +
748 number_of_side * points_per_side * (
_n_cells + 1) +
749 number_of_center * points_per_center * (
_n_cells + 1) -
750 points_per_channel * (
_n_cells + 1);
752 unsigned int indx1 = iz * points_per_channel + elapsed_points;
754 unsigned int indx2 = (iz + 1) * points_per_channel + elapsed_points;
756 for (
unsigned int i = 0; i < elems_per_channel; i++)
758 Elem * elem =
new Prism6;
760 elem->set_id(elem_id++);
761 elem = mesh_base->add_elem(elem);
763 elem->set_node(0, mesh_base->node_ptr(indx1));
764 elem->set_node(1, mesh_base->node_ptr(indx1 + i + 1));
765 if (i != elems_per_channel - 1)
766 elem->set_node(2, mesh_base->node_ptr(indx1 + i + 2));
768 elem->set_node(2, mesh_base->node_ptr(indx1 + 1));
770 elem->set_node(3, mesh_base->node_ptr(indx2));
771 elem->set_node(4, mesh_base->node_ptr(indx2 + i + 1));
772 if (i != elems_per_channel - 1)
773 elem->set_node(5, mesh_base->node_ptr(indx2 + i + 2));
775 elem->set_node(5, mesh_base->node_ptr(indx2 + 1));
778 boundary_info.add_side(elem, 0, 0);
780 boundary_info.add_side(elem, 4, 1);
785 boundary_info.sideset_name(0) =
"inlet";
786 boundary_info.sideset_name(1) =
"outlet";
788 mesh_base->prepare_for_use();
registerMooseObject("SubChannelApp", SCMDetailedQuadSubChannelMeshGenerator)
registerMooseObjectRenamed("SubChannelApp", DetailedQuadSubChannelMeshGenerator, "06/30/2025 24:00", 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 Real _gap
Half of gap between adjacent assemblies.
virtual const std::string & name() const
const unsigned int _nx
Number of subchannels in the x direction.
std::vector< std::vector< Real > > _subchannel_position
x,y coordinates of the subchannel centroids
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