armi.reactor.grids.structuredgrid module

class armi.reactor.grids.structuredgrid.GridParameters(unitSteps, bounds, unitStepLimits, offset, geomType, symmetry)

Bases: tuple

Create new instance of GridParameters(unitSteps, bounds, unitStepLimits, offset, geomType, symmetry)

bounds

Alias for field number 1

geomType

Alias for field number 4

offset

Alias for field number 3

symmetry

Alias for field number 5

unitStepLimits

Alias for field number 2

unitSteps

Alias for field number 0

class armi.reactor.grids.structuredgrid.StructuredGrid(unitSteps=(0, 0, 0), bounds=(None, None, None), unitStepLimits=((0, 1), (0, 1), (0, 1)), offset=None, geomType='', symmetry='', armiObject=None)[source]

Bases: Grid

A connected set of cells characterized by indices mapping to space and vice versa.

The cells may be characterized by any mixture of regular repeating steps and user-defined steps in any direction.

For example, a 2-D hex lattice has constant, regular steps whereas a 3-D hex mesh may have user-defined axial meshes. Similar for Cartesian, RZT, etc.

Parameters:
  • unitSteps (tuple of tuples, optional) –

    Describes the grid spatially as a function on indices. Each tuple describes how each (x,y,or z) dimension is influenced by (i,j,k). In other words, it is:

    (dxi, dxj, jxk), (dyi, dyj, dyk), (dzi, dzj, dzk)
    

    where dmn is the distance (in cm) that dimension m will change as a function of index n.

    Unit steps are used as a generic method for defining repetitive grids in a variety of geometries, including hexagonal and Cartesian. The tuples are not vectors in the direction of the translation, but rather grouped by direction. If the bounds argument is described for a direction, the bounds will be used rather than the unit step information. The default of (0, 0, 0) makes all dimensions insensitive to indices since the coordinates are calculated by the dot product of this and the indices. With this default, any dimension that is desired to change with indices should be defined with bounds. RZtheta grids are created exclusively with bounds.

  • bounds (3-tuple) – Absolute increasing bounds in cm including endpoints of a non-uniform grid. Each item represents the boundaries in the associated direction. Use Nones when unitSteps should be applied instead. Most useful for thetaRZ grids or other non-uniform grids.

  • unitStepLimits (3-tuple) – The limit of the steps in all three directions. This constrains step-defined grids to be finite so we can populate them with SpatialLocator objects.

  • offset (3-tuple, optional) – Offset in cm for each axis. By default the center of the (0,0,0)-th object is in the center of the grid. Offsets can move it so that the (0,0,0)-th object can be fully within a quadrant (i.e. in a Cartesian grid).

  • armiObject (ArmiObject, optional) – The ArmiObject that this grid describes. For example if it’s a 1-D assembly grid, the armiObject is the assembly. Note that self.armiObject.spatialGrid is self.

Examples

A 2D a rectangular grid with width (x) 2 and height (y) 3 would be:

>>> grid = Grid(unitSteps=((2, 0, 0), (0, 3, 0),(0, 0, 0)))

A regular hex grid with pitch 1 is:

>>> grid = Grid(unitSteps= ((sqrt(3)/2, 0.0, 0.0), (0.5, 1.0, 0.0), (0, 0, 0))

Note

For this unit hex the magnitude of the vector constructed using the 0th index of each tuple is 1.0.

Notes

Each dimension must either be defined through unitSteps or bounds. The combination of unitSteps with bounds was settled upon after some struggle to have one unified definition of a grid (i.e. just bounds). A hexagonal grid is somewhat challenging to represent with bounds because the axes are not orthogonal, so a unit-direction vector plus bounds would be required. And then the bounds would be wasted space because they can be derived simply by unit steps. Memory efficiency is important in this object so the compact representation of unitSteps-when-possible, bounds-otherwise was settled upon.

Design considerations include:

  • unitSteps are more intuitive as operations starting from the center of a cell, particularly with hexagons and rectangles. Otherwise the 0,0 position of a hexagon in the center of 1/3-symmetric hexagon is at the phantom bottom left of the hexagon.

  • Users generally prefer to input mesh bounds rather than centers (e.g. starting at 0.5 instead of 0.0 in a unit mesh is weird).

  • If we store bounds, computing bounds is simple and computing centers takes ~2x the effort. If we store centers, it’s the opposite.

  • Regardless of how we store things, we’ll need a Grid that has the lower-left assembly fully inside the problem (i.e. for full core Cartesian) as well as another one that has the lower-left assembly half-way or quarter-way sliced off (for 1/2, 1/4, and 1/8 symmetries). The offset parameter handles this.

  • Looking up mesh boundaries (to define a mesh in another code) is generally more common than looking up centers (for plotting or measuring distance).

  • A grid can be anchored to the object that it is in with a backreference. This gives it the ability to traverse the composite tree and map local to global locations without having to duplicate the composite pattern on grids. This remains optional so grids can be used for non-reactor-package reasons. It may seem slightly cleaner to set the armiObject to the parent’s spatialLocator itself but the major disadvantage of this is that when an object moves, the armiObject would have to be updated. By anchoring directly to Composite objects, the parent is always up to date no matter where or how things get moved.

  • Unit step calculations use dot products and must not be polluted by the bound indices. Thus we reduce the size of the unitSteps tuple accordingly.

property isAxialOnly: bool
reduce() GridParameters[source]

Recreate the parameter necessary to create this grid.

property offset: ndarray

Offset in cm for each axis.

items() Iterable[Tuple[Tuple[int, int, int], IndexLocation]][source]
backUp()[source]

Gather internal info that should be restored within a retainState.

restoreBackup()[source]
getCoordinates(indices, nativeCoords=False) ndarray[source]

Return the coordinates of the center of the mesh cell at the given indices in cm.

getCellBase(indices) ndarray[source]

Get the mesh base (lower left) of this mesh cell in cm.

getCellTop(indices) ndarray[source]

Get the mesh top (upper right) of this mesh cell in cm.

static getNeighboringCellIndices(i, j=0, k=0)[source]

Return the indices of the immediate neighbors of a mesh point in the plane.

static getAboveAndBelowCellIndices(indices)[source]
getIndexBounds()[source]

Get min index and number of indices in this grid.

Step-defined grids would be infinite but for the step limits defined in the constructor.

Notes

This produces output that is intended to be passed to a range statement.

getBounds() Tuple[Optional[Sequence[float]], Optional[Sequence[float]], Optional[Sequence[float]]][source]

Return the grid bounds for each dimension, if present.

getLocatorFromRingAndPos(ring, pos, k=0)[source]

Return the location based on ring and position.

Parameters:
  • ring (int) – Ring number (1-based indexing)

  • pos (int) – Position number (1-based indexing)

  • k (int, optional) – Axial index (0-based indexing)

See also

getIndicesFromRingAndPos

This implements the transform into i, j indices based on ring and position.

abstract static getIndicesFromRingAndPos(ring: int, pos: int)[source]

Return i, j indices given ring and position.

Note

This should be implemented as a staticmethod, since no Grids currently in exsistence actually need any instance data to perform this task, and staticmethods provide the convenience of calling the method without an instance of the class in the first place.

abstract getMinimumRings(n: int) int[source]

Return the minimum number of rings needed to fit n objects.

Warning

While this is useful and safe for answering the question of “how many rings do I need to hold N things?”, is generally not safe to use it to answer “I have N things; within how many rings are they distributed?”. This function provides a lower bound, assuming that objects are densely-packed. If they are not actually densely packed, this may be unphysical.

abstract getPositionsInRing(ring: int) int[source]

Return the number of positions within a ring.

getRingPos(indices) Tuple[int, int][source]

Get ring and position number in this grid.

For non-hex grids this is just i and j.

A tuple is returned so that it is easy to compare pairs of indices.

getAllIndices()[source]

Get all possible indices in this grid.

armiObject: Optional[ArmiObject]
abstract property pitch: Union[float, Tuple[float, float]]

Grid pitch.

Some implementations may rely on a single pitch, such as axial or hexagonal grids. Cartesian grids may use a single pitch between elements or separate pitches for the x and y dimensions.

Returns:

Grid spacing in cm

Return type:

float or tuple of (float, float)