13 #include "libmesh/face_quad4.h" 14 #include "libmesh/unstructured_mesh.h" 23 "Creates a mesh of 2D duct cells around a triangular lattice subassembly");
24 params.
addRequiredParam<MeshGeneratorName>(
"input",
"The corresponding subchannel mesh");
25 params.
addParam<
unsigned int>(
"block_id", 2,
"Domain Index");
26 params.
addRequiredParam<
unsigned int>(
"n_cells",
"The number of cells in the axial direction");
27 params.
addParam<
Real>(
"unheated_length_entry", 0.0,
"Unheated length at entry [m]");
29 params.
addParam<
Real>(
"unheated_length_exit", 0.0,
"Unheated length at exit [m]");
31 params.
addRequiredParam<
unsigned int>(
"nrings",
"Number of fuel Pin rings in the assembly [-]");
33 "Flat to flat distance for the hexagonal assembly [m]");
40 _n_cells(getParam<unsigned
int>(
"n_cells")),
41 _unheated_length_entry(getParam<
Real>(
"unheated_length_entry")),
42 _heated_length(getParam<
Real>(
"heated_length")),
43 _unheated_length_exit(getParam<
Real>(
"unheated_length_exit")),
44 _block_id(getParam<unsigned
int>(
"block_id")),
45 _pitch(getParam<
Real>(
"pitch")),
46 _n_rings(getParam<unsigned
int>(
"nrings")),
47 _flat_to_flat(getParam<
Real>(
"flat_to_flat"))
53 std::unique_ptr<MeshBase>
56 std::unique_ptr<MeshBase> mesh_base = std::move(
_input);
57 mesh_base->set_mesh_dimension(3);
59 std::vector<Point> corners;
61 std::vector<Point> cross_sec;
63 std::vector<Point> points;
65 std::vector<std::vector<size_t>> elem_point_indices;
67 std::vector<Node *> duct_nodes;
71 mesh_base->prepare_for_use();
75 sch_mesh._duct_mesh_exist =
true;
83 const Point &
center)
const 90 Point
corner = {r_corner * std::cos(theta), r_corner * std::sin(theta)};
97 const std::vector<Point> & corners,
110 const Real side_length = (corners[0] - corners[1]).
norm();
113 const Real start_offset = 0.5 * (side_length - (nrings - 2) *
pitch);
116 if (start_offset < 0.0)
117 mooseError(
"SCMTriDuctMeshGenerator: computed start_offset is negative (",
119 "). Check 'nrings', 'pitch', and duct side length.");
121 for (
size_t i = 0; i < corners.size(); i++)
123 const Point left = corners[i];
124 const Point right = corners[(i + 1) % corners.size()];
127 cross_sec.push_back(left);
130 const Point direc = (right - left).unit();
136 const Real offset_from_corner = start_offset +
k *
pitch;
137 cross_sec.push_back(left + direc * offset_from_corner);
145 unsigned int point)
const 147 return layer * points_per_layer + point;
152 const std::vector<Point> & cross_sec,
153 const std::vector<Real> & z_layers)
const 155 points.resize(cross_sec.size() * z_layers.size());
156 for (
size_t i = 0; i < z_layers.size(); i++)
157 for (
size_t j = 0;
j < cross_sec.size();
j++)
159 Point(cross_sec[
j](0), cross_sec[
j](1), z_layers[i]);
164 unsigned int n_layers,
165 unsigned int points_per_layer)
const 167 elem_point_indices.clear();
168 for (
unsigned int i = 0; i < n_layers - 1; i++)
170 unsigned int bottom = i;
171 unsigned int top = i + 1;
172 for (
unsigned int j = 0;
j < points_per_layer;
j++)
174 unsigned int left =
j;
175 unsigned int right = (
j + 1) % points_per_layer;
176 elem_point_indices.push_back({
ductPointIndex(points_per_layer, bottom, left),
186 std::vector<Node *> & duct_nodes,
187 const std::vector<Point> & points,
188 const std::vector<std::vector<size_t>> & elem_point_indices,
193 duct_nodes.reserve(points.size());
194 for (
const auto &
p : points)
195 duct_nodes.push_back(
mesh->add_point(
p));
198 for (
const auto & elem_indices : elem_point_indices)
200 mooseAssert(elem_indices.size() == 4,
201 "Expected 4 node indices per element when building QUAD4 elements.");
203 auto elem = Elem::build(ElemType::QUAD4);
204 elem->subdomain_id() = block;
207 for (
unsigned int i = 0; i < 4; ++i)
209 const auto idx = elem_indices[i];
210 mooseAssert(
idx < duct_nodes.size(),
"Element node index out of range.");
211 elem->set_node(i, duct_nodes[
idx]);
215 mesh->add_elem(elem.release());
void ductElems(std::vector< std::vector< size_t >> &elem_point_indices, unsigned int n_layers, unsigned int points_per_layer) const
Determines element connectivity for the duct mesh.
void ductPoints(std::vector< Point > &points, const std::vector< Point > &cross_sec, const std::vector< Real > &z_layers) const
Computes all 3D point locations used to construct the duct mesh.
const Real _unheated_length_entry
unheated length of the fuel Pin at the entry of the assembly
T & getMesh(MooseMesh &mesh)
function to cast mesh
void ductCrossSec(std::vector< Point > &cross_sec, const std::vector< Point > &corners, unsigned int nrings, Real pitch) const
Generates the points along the duct cross-section sides.
static const unsigned int N_CORNERS
number of corners in the duct x-sec
std::unique_ptr< MeshBase > generate() override
const Real _flat_to_flat
the distance between flat surfaces of the duct facing each other
const Real _unheated_length_exit
unheated length of the fuel Pin at the exit of the assembly
static void generateZGrid(Real unheated_length_entry, Real heated_length, Real unheated_length_exit, unsigned int n_cells, std::vector< Real > &z_grid)
Generate the spacing in z-direction using heated and unteaded lengths.
static InputParameters validParams()
const unsigned int _n_cells
number of axial cells
const std::string & name() const
static const std::string pitch
const unsigned int _block_id
block index
registerMooseObject("SubChannelApp", SCMTriDuctMeshGenerator)
std::unique_ptr< MeshBase > & _input
Mesh that comes from another generator.
static InputParameters validParams()
void buildDuct(std::unique_ptr< MeshBase > &mesh, std::vector< Node *> &duct_nodes, const std::vector< Point > &points, const std::vector< std::vector< size_t >> &elem_point_indices, SubdomainID block) const
Builds duct mesh nodes and elements and inserts them into the mesh.
const Real _pitch
Distance between the neighbor fuel pins, pitch.
Mesh class for triangular, edge and corner subchannels for hexagonal lattice fuel assemblies...
const unsigned int _n_rings
number of rings of fuel pins
SCMTriDuctMeshGenerator(const InputParameters ¶meters)
void ductCorners(std::vector< Point > &corners, Real flat_to_flat, const Point ¢er) const
Computes the x-y corner coordinates of the duct cross-section.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< Real > _z_grid
axial location of nodes
void setChannelToDuctMaps(const std::vector< Node *> &duct_nodes)
Function that sets the channel-to-duct maps.
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
size_t ductPointIndex(unsigned int points_per_layer, unsigned int layer, unsigned int point) const
Maps a duct cross-section point and axial layer to a linear point index.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
const Real _heated_length
heated length of the fuel Pin
static const std::string k
void ErrorVector unsigned int
static const std::string center
Mesh generator for hexagonal duct.