13 #include "libmesh/cell_prism6.h" 14 #include "libmesh/unstructured_mesh.h" 18 DetailedQuadInterWrapperMeshGenerator,
27 "Creates a detailed mesh of the inter-wrapper cells around square lattice subassemblies");
30 "Outer side lengths of assembly in x [m] - including duct");
32 "Outer side lengths of assembly in y [m] - including duct");
33 params.
addParam<
Real>(
"unheated_length_entry", 0.0,
"Unheated length at entry [m]");
35 params.
addParam<
Real>(
"unheated_length_exit", 0.0,
"Unheated length at exit [m]");
36 params.
addRequiredParam<
unsigned int>(
"n_cells",
"The number of cells in the axial direction");
37 params.
addRequiredParam<
unsigned int>(
"nx",
"Number of channels in the x direction [-]");
38 params.
addRequiredParam<
unsigned int>(
"ny",
"Number of channels in the y direction [-]");
40 params.
addParam<
unsigned int>(
"block_id", 0,
"Block ID used for the mesh subdomain.");
47 _unheated_length_entry(getParam<
Real>(
"unheated_length_entry")),
48 _heated_length(getParam<
Real>(
"heated_length")),
49 _unheated_length_exit(getParam<
Real>(
"unheated_length_exit")),
50 _assembly_pitch(getParam<
Real>(
"assembly_pitch")),
51 _assembly_side_x(getParam<
Real>(
"assembly_side_x")),
52 _assembly_side_y(getParam<
Real>(
"assembly_side_y")),
53 _n_cells(getParam<unsigned
int>(
"n_cells")),
54 _nx(getParam<unsigned
int>(
"nx") + 1),
55 _ny(getParam<unsigned
int>(
"ny") + 1),
56 _n_channels((_nx + 1) * (_ny + 1)),
57 _side_bypass_length(getParam<
Real>(
"side_bypass")),
58 _block_id(getParam<unsigned
int>(
"block_id"))
62 for (
unsigned int i = 0; i <
_n_cells + 1; i++)
66 for (
unsigned int iy = 0; iy <
_ny; iy++)
68 for (
unsigned int ix = 0; ix <
_nx; ix++)
70 unsigned int i_ch =
_nx * iy + ix;
71 bool is_corner = (ix == 0 && iy == 0) || (ix ==
_nx - 1 && iy == 0) ||
72 (ix == 0 && iy ==
_ny - 1) || (ix ==
_nx - 1 && iy ==
_ny - 1);
73 bool is_edge = (ix == 0 || iy == 0 || ix ==
_nx - 1 || iy ==
_ny - 1);
85 std::unique_ptr<MeshBase>
89 BoundaryInfo & boundary_info = mesh_base->get_boundary_info();
90 mesh_base->set_spatial_dimension(3);
93 const unsigned int theta_res = 16;
95 const unsigned int points_per_quad = theta_res / 4 + 1;
100 const unsigned int points_per_center = points_per_quad * 4 + 1;
103 const unsigned int points_per_corner = points_per_quad * 1 + 1 + 3;
106 const unsigned int points_per_side = points_per_quad * 2 + 1 + 2;
110 const unsigned int elems_per_center = theta_res + 4;
111 const unsigned int elems_per_corner = theta_res / 4 + 4;
112 const unsigned int elems_per_side = theta_res / 2 + 4;
115 unsigned int n_center, n_side, n_corner;
118 n_side = 2 * (
_ny - 2) + 2 * (
_nx - 2);
122 const unsigned int points_per_level =
123 n_corner * points_per_corner + n_side * points_per_side + n_center * points_per_center;
124 const unsigned int elems_per_level =
125 n_corner * elems_per_corner + n_side * elems_per_side + n_center * elems_per_center;
126 const unsigned int n_points = points_per_level * (
_n_cells + 1);
127 const unsigned int n_elems = elems_per_level *
_n_cells;
128 mesh_base->reserve_nodes(n_points);
129 mesh_base->reserve_elem(n_elems);
134 std::array<Point, theta_res + 1> circle_points;
138 for (
unsigned int i = 0; i < theta_res + 1; i++)
140 u =
radius * std::cos(theta);
142 Real val_check_u = std::abs(u) - std::sqrt(2.0) / 2.0;
143 Real val_check_v = std::abs(
v) - std::sqrt(2.0) / 2.0;
144 if (val_check_u < 1e-5 && val_check_v < 1e-5)
146 circle_points[i](0) = u * 2.0 / std::sqrt(2);
147 circle_points[i](1) =
v * 2.0 / std::sqrt(2);
151 circle_points[i](0) =
154 circle_points[i](1) =
160 theta += 2 * M_PI / theta_res;
168 const Real shrink_factor = 0.99999;
169 std::array<Point, 4> quadrant_centers;
170 quadrant_centers[0] =
172 quadrant_centers[1] =
174 quadrant_centers[2] =
176 quadrant_centers[3] =
179 const unsigned int m = theta_res / 4;
187 std::array<Point, points_per_center> center_points;
190 for (
unsigned int i = 0; i < 4; i++)
200 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
202 auto c_pt = circle_points[start - ii];
203 center_points[i * points_per_quad + ii + 1] = quadrant_centers[i] + c_pt;
215 std::array<Point, points_per_corner> tl_corner_points;
217 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
219 auto c_pt = circle_points[2 * m - ii];
220 tl_corner_points[ii + 1] = quadrant_centers[3] + c_pt;
222 tl_corner_points[points_per_quad + 1] =
225 tl_corner_points[points_per_quad + 3] =
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] =
246 tr_corner_points[points_per_quad + 3] =
257 std::array<Point, points_per_corner> bl_corner_points;
259 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
261 auto c_pt = circle_points[3 * m - ii];
262 bl_corner_points[ii + 1] = quadrant_centers[0] + c_pt;
264 bl_corner_points[points_per_quad + 1] =
267 bl_corner_points[points_per_quad + 3] =
278 std::array<Point, points_per_corner> br_corner_points;
280 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
282 auto c_pt = circle_points[4 * m - ii];
283 br_corner_points[ii + 1] = quadrant_centers[1] + c_pt;
285 br_corner_points[points_per_quad + 1] =
288 br_corner_points[points_per_quad + 3] =
299 std::array<Point, points_per_side> top_points;
301 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
303 auto c_pt = circle_points[m - ii];
304 top_points[ii + 1] = quadrant_centers[2] + c_pt;
306 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
308 auto c_pt = circle_points[2 * m - ii];
309 top_points[points_per_quad + ii + 1] = quadrant_centers[3] + c_pt;
311 top_points[2 * points_per_quad + 1] =
313 top_points[2 * points_per_quad + 2] =
324 std::array<Point, points_per_side> left_points;
326 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
328 auto c_pt = circle_points[2 * m - ii];
329 left_points[ii + 1] = quadrant_centers[3] + c_pt;
331 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
333 auto c_pt = circle_points[3 * m - ii];
334 left_points[points_per_quad + ii + 1] = quadrant_centers[0] + c_pt;
336 left_points[2 * points_per_quad + 1] =
338 left_points[2 * points_per_quad + 2] =
349 std::array<Point, points_per_side> bottom_points;
351 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
353 auto c_pt = circle_points[3 * m - ii];
354 bottom_points[ii + 1] = quadrant_centers[0] + c_pt;
356 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
358 auto c_pt = circle_points[4 * m - ii];
359 bottom_points[points_per_quad + ii + 1] = quadrant_centers[1] + c_pt;
361 bottom_points[2 * points_per_quad + 1] =
363 bottom_points[2 * points_per_quad + 2] =
374 std::array<Point, points_per_side> right_points;
376 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
378 auto c_pt = circle_points[4 * m - ii];
379 right_points[ii + 1] = quadrant_centers[1] + c_pt;
381 for (
unsigned int ii = 0; ii < points_per_quad; ii++)
383 auto c_pt = circle_points[m - ii];
384 right_points[points_per_quad + ii + 1] = quadrant_centers[2] + c_pt;
386 right_points[2 * points_per_quad + 1] =
388 right_points[2 * points_per_quad + 2] =
394 unsigned int node_id = 0;
397 for (
unsigned int iy = 0; iy <
_ny; iy++)
400 for (
unsigned int ix = 0; ix <
_nx; ix++)
403 if (ix == 0 && iy == 0)
408 for (
unsigned int i = 0; i < points_per_corner; i++)
409 mesh_base->add_point(bl_corner_points[i] + x0 + y0 + z0, node_id++);
412 else if (ix ==
_nx - 1 && iy == 0)
417 for (
unsigned int i = 0; i < points_per_corner; i++)
418 mesh_base->add_point(br_corner_points[i] + x0 + y0 + z0, node_id++);
421 else if (ix == 0 && iy ==
_ny - 1)
426 for (
unsigned int i = 0; i < points_per_corner; i++)
427 mesh_base->add_point(tl_corner_points[i] + x0 + y0 + z0, node_id++);
430 else if (ix ==
_nx - 1 && iy ==
_ny - 1)
435 for (
unsigned int i = 0; i < points_per_corner; i++)
436 mesh_base->add_point(tr_corner_points[i] + x0 + y0 + z0, node_id++);
439 else if (ix == 0 && (iy !=
_ny - 1 || iy != 0))
444 for (
unsigned int i = 0; i < points_per_side; i++)
445 mesh_base->add_point(left_points[i] + x0 + y0 + z0, node_id++);
448 else if (ix ==
_nx - 1 && (iy !=
_ny - 1 || iy != 0))
453 for (
unsigned int i = 0; i < points_per_side; i++)
454 mesh_base->add_point(right_points[i] + x0 + y0 + z0, node_id++);
457 else if (iy == 0 && (ix !=
_nx - 1 || ix != 0))
462 for (
unsigned int i = 0; i < points_per_side; i++)
463 mesh_base->add_point(bottom_points[i] + x0 + y0 + z0, node_id++);
466 else if (iy ==
_ny - 1 && (ix !=
_nx - 1 || ix != 0))
471 for (
unsigned int i = 0; i < points_per_side; i++)
472 mesh_base->add_point(top_points[i] + x0 + y0 + z0, node_id++);
480 for (
unsigned int i = 0; i < points_per_center; i++)
481 mesh_base->add_point(center_points[i] + x0 + y0 + z0, node_id++);
490 unsigned int elem_id = 0;
491 unsigned int number_of_corner = 0;
492 unsigned int number_of_side = 0;
493 unsigned int number_of_center = 0;
494 unsigned int elems_per_channel = 0;
495 unsigned int points_per_channel = 0;
496 for (
unsigned int iy = 0; iy <
_ny; iy++)
498 for (
unsigned int ix = 0; ix <
_nx; ix++)
500 unsigned int i_ch =
_nx * iy + ix;
505 elems_per_channel = elems_per_corner;
506 points_per_channel = points_per_corner;
511 elems_per_channel = elems_per_side;
512 points_per_channel = points_per_side;
517 elems_per_channel = elems_per_center;
518 points_per_channel = points_per_center;
520 for (
unsigned int iz = 0; iz <
_n_cells; iz++)
522 unsigned int elapsed_points = number_of_corner * points_per_corner * (
_n_cells + 1) +
523 number_of_side * points_per_side * (
_n_cells + 1) +
524 number_of_center * points_per_center * (
_n_cells + 1) -
525 points_per_channel * (
_n_cells + 1);
527 unsigned int indx1 = iz * points_per_channel + elapsed_points;
529 unsigned int indx2 = (iz + 1) * points_per_channel + elapsed_points;
531 for (
unsigned int i = 0; i < elems_per_channel; i++)
533 Elem * elem =
new Prism6;
535 elem->set_id(elem_id++);
536 elem = mesh_base->add_elem(elem);
538 elem->set_node(0, mesh_base->node_ptr(indx1));
539 elem->set_node(1, mesh_base->node_ptr(indx1 + i + 1));
540 if (i != elems_per_channel - 1)
541 elem->set_node(2, mesh_base->node_ptr(indx1 + i + 2));
543 elem->set_node(2, mesh_base->node_ptr(indx1 + 1));
545 elem->set_node(3, mesh_base->node_ptr(indx2));
546 elem->set_node(4, mesh_base->node_ptr(indx2 + i + 1));
547 if (i != elems_per_channel - 1)
548 elem->set_node(5, mesh_base->node_ptr(indx2 + i + 2));
550 elem->set_node(5, mesh_base->node_ptr(indx2 + 1));
553 boundary_info.add_side(elem, 0, 0);
555 boundary_info.add_side(elem, 4, 1);
560 boundary_info.sideset_name(0) =
"inlet";
561 boundary_info.sideset_name(1) =
"outlet";
563 mesh_base->prepare_for_use();
const Real _assembly_side_y
const Real _assembly_side_x
Fuel assembly dimensions.
const unsigned int _nx
Number of subchannels in the x direction.
const Real _heated_length
heated length of the fuel Pin
std::vector< Real > _z_grid
axial location of nodes
const unsigned int _ny
Number of subchannels in the y direction.
virtual const std::string & name() const
static InputParameters validParams()
EChannelType getSubchannelType(unsigned int index) const
const Real _side_bypass_length
Half of gap between adjacent assemblies.
virtual std::unique_ptr< MeshBase > generate() override
unsigned int _n_channels
Total number of subchannels.
const Real _unheated_length_entry
unheated length of the fuel Pin at the entry of the assembly
std::vector< EChannelType > _subch_type
Subchannel type.
static InputParameters validParams()
const Real _unheated_length_exit
unheated length of the fuel Pin at the exit of the assembly
const Real _assembly_pitch
Distance between the neighbor fuel pins, pitch.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
SCMDetailedQuadInterWrapperMeshGenerator(const InputParameters ¶meters)
registerMooseObject("SubChannelApp", SCMDetailedQuadInterWrapperMeshGenerator)
const unsigned int _n_cells
Number of cells in the axial direction.
registerMooseObjectRenamed("SubChannelApp", DetailedQuadInterWrapperMeshGenerator, "06/30/2025 24:00", SCMDetailedQuadInterWrapperMeshGenerator)
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
const unsigned int & _block_id
Subdomain ID used for the mesh block.
Mesh generator that builds a 3D mesh representing quadrilateral subchannels.
MooseUnits pow(const MooseUnits &, int)
void ErrorVector unsigned int