21 const Real pin_diameter,
22 const Real wire_diameter,
23 const Real wire_pitch,
24 const unsigned int n_rings,
25 const unsigned int axis,
26 const Real rotation_around_axis)
27 : _bundle_pitch(bundle_inner_flat_to_flat),
28 _pin_pitch(pin_pitch),
29 _pin_diameter(pin_diameter),
30 _wire_diameter(wire_diameter),
31 _wire_pitch(wire_pitch),
34 _rotation_around_axis(rotation_around_axis),
39 _bundle_side_length(hexagonSide(_bundle_pitch)),
40 _pin_area(M_PI * _pin_diameter * _pin_diameter / 4.0),
41 _pin_circumference(M_PI * _pin_diameter),
42 _wire_area(M_PI * _wire_diameter * _wire_diameter / 4.0),
43 _wire_circumference(M_PI * _wire_diameter),
44 _pin_surface_area_per_pitch(M_PI * _pin_diameter * _wire_pitch),
45 _pin_volume_per_pitch(_pin_area * _wire_pitch),
46 _P_over_D(_pin_pitch / _pin_diameter),
47 _L_over_D(_wire_pitch / _pin_diameter)
55 mooseError(
"The HexagonalLatticeUtils is currently limited to 'axis = 2'!");
63 " cannot fit between pin-pin space of " +
70 if (rotation_around_axis != 0)
95 " is too small to fit the given pins and wire wrap!");
112 unsigned int total = 0;
113 for (
unsigned int i = 1; i <= n; ++i)
125 while (remaining > 0)
128 remaining -=
pins(i);
132 mooseError(
"Number of pins " + std::to_string(n) +
133 " not evenly divisible in a hexagonal lattice!");
141 return pitch / std::sqrt(3.0);
148 return 3 *
SIN60 * side * side;
161 return std::sqrt(area /
SIN60);
179 return height /
SIN60;
206 Real l = std::sqrt(distance_to_corner * distance_to_corner - distance_to_wall * distance_to_wall);
227 mooseError(
"Unhandled ChannelTypeEnum in HexagonalLattice!");
243 mooseError(
"Unhandled ChannelTypeEnum in HexagonalLattice!");
283 Point rotated =
_rotation_matrix * Point(corner_shiftx[i], corner_shifty[i], 0);
284 corner_shiftx[i] = rotated(0);
285 corner_shifty[i] = rotated(1);
287 edge_shiftx[i] = rotated(0);
288 edge_shifty[i] = rotated(1);
295 for (
unsigned int i = 2; i <=
_n_rings; ++i)
297 auto n_total_in_ring =
pins(i);
352 unsigned int n = i == 5 ? 0 : i + 1;
417 for (
unsigned int i =
_n_rings; i > 0; --i)
437 for (
unsigned int i = 1; i <
_n_rings; ++i)
456 unsigned int n_wire_coils = 1;
457 Real wire_length_per_coil =
459 Real wire_length = wire_length_per_coil * n_wire_coils;
484 std::vector<std::vector<unsigned int>> starts;
489 starts[i][0] = (i == 0) ? 0 :
totalPins(i);
492 starts[i][
j] = starts[i][
j - 1] + i;
499 unsigned int channels_per_sector = channels /
NUM_SIDES;
503 auto prev_inner = starts[i][
j];
504 auto prev_outer = starts[i + 1][
j];
506 for (
const auto k :
make_range(channels_per_sector))
508 bool downward =
k % 2 == 0;
525 if (
k == channels_per_sector - 1)
531 if (
k == channels_per_sector - 2 && i > 0)
554 const std::vector<Point>
556 const unsigned int interior_channel_id)
const 558 std::vector<Point> corners;
560 for (
const auto & pin : pin_indices)
566 const std::vector<Point>
569 std::vector<Point> corners;
578 corners.push_back(pin1);
579 corners.push_back(pin2);
581 unsigned int sector = edge_channel_id / (
_n_rings - 1);
582 corners.push_back(pin2 +
584 corners.push_back(pin1 +
590 const std::vector<Point>
593 std::vector<Point> corners;
597 corners.push_back(pin);
601 unsigned int side1 = corner_channel_id == 0 ?
NUM_SIDES - 1 : corner_channel_id - 1;
602 unsigned int side2 = corner_channel_id;
604 corners.push_back(pin +
607 corners.push_back(pin +
616 int n_pins =
pins.size();
617 Point centroid(0.0, 0.0, 0.0);
618 for (
const auto & p :
pins)
619 centroid += p / n_pins;
634 Real distance_from_pin = std::sqrt(dx * dx + dy * dy);
638 if (distance_from_pin > side)
653 unsigned int start_index = 0;
659 auto min_distance = std::numeric_limits<Real>::max();
660 unsigned int index_min = 0;
661 for (
unsigned int i = start_index; i <
_n_pins; ++i)
666 Real distance_from_pin = std::sqrt(dx * dx + dy * dy);
668 if (distance_from_pin < min_distance)
670 min_distance = distance_from_pin;
720 "Point (" + std::to_string(point(0)) +
", " + std::to_string(point(1)) +
", " +
721 std::to_string(point(2)) +
722 ") is not in any channel! This can sometimes happen " 723 "due to:\n\n a) Points in the mesh actually being outside the domain specified with the " 724 "HexagonalLatticeUtils.\n b) Small floating point errors - we recommend using a CONSTANT " 725 "MONOMIAL variable with all related objects.\nYou can also try slightly decreasing the pin " 727 "increasing the bundle pitch.");
733 std::vector<Point> lattice_corners(6);
739 lattice_corners[i] = translation;
746 unsigned int & row_index,
747 unsigned int & within_row_index)
const 751 const auto ring_index =
ringIndex(pin_index);
755 const auto n_pin_sectors =
pins(ring_index) / 6;
761 if (local_i < n_pin_sectors)
763 else if (local_i < 3 * n_pin_sectors)
765 else if (local_i < 4 * n_pin_sectors)
767 else if (local_i < 5 * n_pin_sectors)
780 mooseAssert(row_index < 2 *
_n_rings - 1,
"Inverse indexing failed");
781 mooseAssert(within_row_index < 2 *
_n_rings - 1,
"Inverse indexing failed");
787 std::set<std::pair<int, int>> indices;
790 std::pair<int, int> gap0 = {std::min(
pins[0],
pins[1]), std::max(
pins[0],
pins[1])};
791 std::pair<int, int> gap1 = {std::min(
pins[0],
pins[2]), std::max(
pins[0],
pins[2])};
792 std::pair<int, int> gap2 = {std::min(
pins[2],
pins[1]), std::max(
pins[2],
pins[1])};
794 indices.insert(gap0);
795 indices.insert(gap1);
796 indices.insert(gap2);
799 for (
const auto & it : indices)
813 pin += n_edge_gaps - 1;
824 std::pair<int, int> gap0 = {std::min(
pins[0],
pins[1]), std::max(
pins[0],
pins[1])};
825 std::pair<int, int> gap1 = {std::min(
pins[1],
pins[2]), std::max(
pins[1],
pins[2])};
826 std::pair<int, int> gap2 = {std::min(
pins[2],
pins[0]), std::max(
pins[2],
pins[0])};
838 std::pair<int, int> gap0 = {std::min(
pins[0],
pins[1]), std::max(
pins[0],
pins[1])};
885 int side = std::abs(
pins.second) - 1;
904 if (gap.first == local_gap.first && gap.second == local_gap.second)
908 mooseError(
"Failed to find local gap in global gap array!");
925 unsigned int index = 0;
933 index = gap_indices[i];
942 unsigned int & index,
943 Real & distance)
const 948 distance = std::numeric_limits<Real>::max();
956 index = gap_indices[i];
964 mooseAssert(ring > 0,
"Ring indexing starts at 1");
974 mooseAssert(ring > 0,
"Ring indexing starts at 1");
1000 for (
unsigned int i = 2; i <=
_n_rings; ++i)
1002 bool one_is_first_pin =
false;
1003 bool one_is_last_pin =
false;
1008 if (
pins.first == first_pin ||
pins.second == first_pin)
1009 one_is_first_pin =
true;
1011 if (
pins.first == last_pin ||
pins.second == last_pin)
1012 one_is_last_pin =
true;
1014 if (one_is_first_pin && one_is_last_pin)
const Real _wire_diameter
Wire diameter.
Real hexagonPitch(const Real volume) const
Get the pitch of a hexagonal prism based on its per-wire-pitch volume.
void computeGapIndices()
Determine the global gap indices, sorted first by lower pin ID and next by higher pin ID...
std::vector< Point > _gap_unit_normals
Unit normal vectors for each gap.
unsigned int _n_interior_pins
Number of interior pins.
ChannelTypeEnum
Type of subchannel.
const RealTensorValue _rotation_matrix
Rotation matrix to apply the rotation why.
unsigned int _n_interior_gaps
Number of gaps that touch an interior channel.
const unsigned int _n_rings
Total number of rings of pins.
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
constexpr auto increment(std::index_sequence< first, tail... >)
std::vector< std::vector< Point > > _pin_centered_corner_coordinates
Corner coordinates of a hexagon surrounding each pin.
Real _corner_flow_volume
Flow volume of a corner channel per wire pitch.
Real _wire_volume_per_pitch
Single-wire volume per wire pitch.
libMesh::Point projectPoint(const libMesh::Real x0, const libMesh::Real x1, const unsigned int axis)
GenericRealTensorValue< is_ad > rotVec2DToX(const GenericRealVectorValue< is_ad > &vec)
void computeHydraulicDiameters()
Compute the hydraulic diameters for each channel type.
const Real _wire_area
Wire cross-sectional area.
void get2DInputPatternIndex(const unsigned int pin_index, unsigned int &row_index, unsigned int &within_row_index) const
Conversion from lattice pin indexing to the 2D input file index.
unsigned int rings(const unsigned int n) const
Get the number of rings for a specified number of pins.
unsigned int pinIndex(const Point &point) const
Get the pin index given a point.
const Real _pin_diameter
Pin diameter.
Real distanceFromGap(const Point &pt, const unsigned int gap_index) const
Distance from a point and a gap.
void mooseError(Args &&... args)
Real hexagonSide(const Real pitch) const
Get the side length of a hexagon with given flat-to-flat distance (pitch)
Real _flow_volume
Bundle-wide flow volume per wire pitch.
libMesh::Real projectedDistanceFromLine(libMesh::Point pt, libMesh::Point line0, libMesh::Point line1, const unsigned int axis)
Real _corner_volume
Total volume of a corner channel per wire pitch.
unsigned int totalPins(const unsigned int n) const
Get the total number of pins for all rings.
const Real _rotation_around_axis
Rotation around the axis to apply to the lattice.
unsigned int channelIndex(const Point &point) const
Get the channel index given a point.
channel_type::ChannelTypeEnum channelType(const Point &p) const
Get the channel type (interior, edge, corner) given a point.
void computePinAndChannelTypes()
Compute the number of pins and channels and their types for the lattice.
const std::vector< Point > cornerChannelCornerCoordinates(const unsigned int corner_channel_id) const
Get the corner coordinates of a corner channel given an ID (relative to the start of the corner chann...
libMesh::Point projectedUnitNormal(libMesh::Point pt1, libMesh::Point pt2, const unsigned int axis)
Real hexagonArea(const Real pitch) const
Get the area of a hexagon with given flat-to-flat distance (pitch)
Real minDuctWallDistance(const Point &p) const
Get the minimum distance from a point to the duct inner surface.
std::vector< Point > _gap_centers
Center points of all the gaps.
void computePinBundleSpacing()
Compute the spacing between the outer pins and the duct inner walls.
Real pinBundleSpacing() const
Get the distance between the outermost pins and the duct walls.
static const std::string axis
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
unsigned int _n_interior_channels
Total number of interior channels.
std::vector< std::vector< unsigned int > > _edge_channel_pin_indices
Pin indices forming two of the corners of each edge channel.
const std::vector< Point > edgeChannelCornerCoordinates(const unsigned int edge_channel_id) const
Get the corner coordinates of an edge channel given an ID (relative to the start of the edge channels...
Real distance(const Point &p)
unsigned int interiorChannels(const unsigned int ring)
Get the number of interior channels between ring and ring - 1 (0 indexing)
unsigned int gapIndex(const Point &point) const
Get the index for the gap closest to the point.
const Real _wire_pitch
Wire pitch.
const unsigned int _axis
Vertical axis of the bundle along which the pins are aligned.
Real _interior_wetted_area
Wetted area of an interior channel per wire pitch.
std::vector< Point > _pin_centers
Pin center coordinates.
Real triangleVolume(const Real side) const
Get the volume of an equilateral triangle prism per wire pitch.
Real _corner_Dh
Hydraulic diameter of corner channel.
Real _corner_edge_length
Half the distance for which a corner channel is in contact with the duct.
const Real _bundle_pitch
Bundle pitch (distance across bundle measured flat-to-flat on the inside of the duct) ...
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
void computeChannelPinIndices()
Get the pin indices that form the corners of each channel type.
const Real _pin_pitch
Pin pitch.
Real _interior_volume
Total volume of an interior channel per wire pitch.
HexagonalLatticeUtils(const Real bundle_inner_flat_to_flat, const Real pin_pitch, const Real pin_diameter, const Real wire_diameter, const Real wire_pitch, const unsigned int n_rings, const unsigned int axis, const Real rotation_around_axis=0)
static const std::string pitch
Real _interior_Dh
Hydraulic diameter of interior channel.
unsigned int globalGapIndex(const std::pair< int, int > &local_gap) const
Get the global gap index from the local gap index.
std::vector< std::vector< unsigned int > > _corner_channel_pin_indices
Pin indices forming one of the corners of each corner channel.
Real _interior_flow_volume
Flow volume of an interior channel per wire pitch.
unsigned int _iy
Index representing "second" coordinate of 2-D plane.
std::pair< unsigned int, unsigned int > projectedIndices(const unsigned int axis)
unsigned int _ix
Index representing "first" coordinate of 2-D plane.
unsigned int pins(const unsigned int n) const
Get the number of pins in a given ring.
Real _pin_bundle_spacing
Spacing between the duct inner wall and the pin surface.
libMesh::Real minDistanceToPoints(const libMesh::Point &pt, const std::vector< libMesh::Point > &candidates, const unsigned int axis)
std::vector< std::pair< int, int > > _gap_indices
Gap indices, connecting two pins or one pin and a side, ordered by global gap ID. ...
Real _wetted_area
Wetted area of entire bundle per wire pitch.
const Real _pin_volume_per_pitch
Single-pin volume per wire pitch.
unsigned int closestPinIndex(const Point &point) const
Get the closest pin index given a point outside the lattice.
Real channelHydraulicDiameter(const channel_type::ChannelTypeEnum &channel) const
Get the hydraulic diameter of a channel.
std::vector< std::vector< unsigned int > > _interior_channel_pin_indices
Pin indices forming the corner of each interior channel.
void computePinAndDuctCoordinates()
Compute the pin center coordinates and the duct corner coordinates.
std::vector< std::vector< int > > _local_to_global_gaps
Local-to-global gap indexing, ordered by channel ID.
const Real _bundle_side_length
Side length of duct.
unsigned int _n_corner_pins
Number of corner pins.
void computeWettedAreas()
Compute the wetted areas for each channel type.
bool lastGapInRing(const unsigned int gap_index) const
Whether this gap is the "last" in the ring, i.e.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int _n_edge_pins
Number of edge pins.
bool pointInPolygon(const libMesh::Point &point, const std::vector< libMesh::Point > &corners, const unsigned int axis)
const std::vector< Point > interiorChannelCornerCoordinates(const unsigned int interior_channel_id) const
Get the corner coordinates of an interior channel given an ID (relative to the start of the interior ...
Real pinRadius() const
Get the pin outer radius.
void computeWireVolumeAndAreaPerPitch()
Compute the volume and surface area const occupied by the wire in one with pitch. ...
Real _edge_Dh
Hydraulic diameter of edge channel.
Real channelSpecificSurfaceArea(const channel_type::ChannelTypeEnum &channel) const
Get the specific surface area of a channel.
unsigned int _n_gaps
Total number of gaps.
Real _edge_wetted_area
Wetted area of an edge channel per wire pitch.
std::vector< std::vector< Point > > _gap_points
Two points on each gap, in order to compute distance-from-gap calculations.
IntRange< T > make_range(T beg, T end)
const Real _pin_surface_area_per_pitch
Pin surface area per wire pitch.
unsigned int _n_channels
Total number of channels.
Real _Dh
Bundle-wide hydraulic diameter.
std::vector< Real > _unit_translation_y
(unitless) y-translations to apply to move from a center point to a side of a hexagon ...
Real _corner_wetted_area
Wetted area of a corner channel per wire pitch.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
void computeFlowVolumes()
Compute the flow volumes for each channel type.
unsigned int _n_corner_channels
Total number of corner channels.
unsigned int _n_pins
Total number of pins.
Real triangleHeight(const Real side) const
Get the height of an equilateral triangle with given side length.
Point channelCentroid(const std::vector< Point > &corners) const
Get the centroid of a channel given the corner coordinates.
Real triangleArea(const Real side) const
Get the area of an equilateral triangle with given side length.
std::vector< std::vector< Real > > _duct_coeffs
Coefficients in the line equations defining each duct wall.
unsigned int ringIndex(const unsigned int pin) const
Get the index of the ring for a certain pin index.
unsigned int firstPinInRing(const unsigned int ring) const
Get the index of the "first" pin in a ring.
std::vector< Point > _duct_corners
Six corner coordinates for the ducts.
MooseUnits pow(const MooseUnits &, int)
Real triangleSide(const Real height) const
Get the side of an equilateral triangle with given height.
static const std::string k
Real _edge_flow_volume
Flow volume of an edge channel per wire pitch.
unsigned int _n_edge_channels
Total number of edge channels.
void ErrorVector unsigned int
auto index_range(const T &sizable)
Real minDuctCornerDistance(const Point &p) const
Get the minimum distance from a point to the duct corners.
Real hexagonVolume(const Real side) const
Get the volume of a hexagonal prism per wire pitch.
Real _edge_volume
Total volume of an edge channel per wire pitch.
std::vector< Real > _unit_translation_x
(unitless) x-translations to apply to move from a center point to a side of a hexagon ...
static const std::string center
unsigned int lastPinInRing(const unsigned int ring) const
Get the index of the "last" pin in a ring.
const Real _wire_circumference
Wire circumference.
void gapIndexAndDistance(const Point &point, unsigned int &index, Real &distance) const
Get the gap index and distance to that gap for a given point.
static const unsigned int NUM_SIDES
Number of sides in a hexagon.
Real _wire_surface_area_per_pitch
Wire surface area per wire pitch.
bool insideLattice(const Point &point) const
Whether the point is inside the lattice.