Mesh

Contents

Mesh#

class Mesh(code, ndim)[source]#

Bases: object

Compact, immutable representation of a multi-axis mesh stagger code.

A Mesh is a frozen dataclass that bundles two integers: a binary stagger code and the axis count ndim. Together they describe, for a ndim-dimensional array, which axes are sampled on the half mesh (face or edge midpoints, bit 1) versus the main mesh (cell-center nodes, bit 0). Because it replaces the legacy two-member Mesh enum, a single instance now encodes the stagger of every axis at once rather than one axis per enum member.

The bit-to-axis mapping follows PSI’s Fortran column-major HDF convention: the most-significant bit maps to the first logical axis (physical \(r\)), descending to the least-significant bit at the last axis (\(\varphi\)). For a 3-bit code the axes therefore read \((r, \theta, \varphi)\) from MSB to LSB. For example, code=0b100, ndim=3 means \(r\) is on the half mesh while \(\theta\) and \(\varphi\) are on the main mesh (the MAS \(B_r\) stagger).

Once built, a Mesh supports rich operations: it iterates as a sequence of per-axis booleans (__iter__()), indexes to a single-axis Mesh (__getitem__()), reports its remesh requirements against a target via remesh() / the >> operator, reverses axis order with reverse(), and acts as a plain integer code in index contexts (__index__()).

Prefer constructing via parse() rather than calling the constructor directly: parse() accepts every form described by MeshCodeType (integers, the shorthand strings 'main'/'half', per-axis token strings such as 'MMH', and per-axis boolean/int sequences) and infers or validates ndim for you. The direct constructor accepts only an explicit integer code and ndim.

Parameters:
codeint

Binary-encoded stagger integer. Bit i (counting from the LSB) sets the stagger of logical axis ndim - 1 - i: 1 for half mesh, 0 for main mesh. Must fit within ndim bits (i.e. 0 <= code < 2**ndim).

ndimint

Number of array dimensions (and therefore significant bits) represented by this code. Fixes the width of the stagger field and the length of the iterated/indexed sequence.

Raises:
ValueError

If code has any bit set at or above position ndim (i.e. code >= 2**ndim), since that bit could not correspond to a real axis.

See also

Mesh.parse

Build a Mesh from any MeshCodeType form.

Mesh.remesh

Per-axis flags for moving from this stagger to a target.

remesh_array

Apply an actual half-to-main mesh shift to a NumPy array.

Examples

>>> from psi_io.mesh import Mesh
>>> str(Mesh.parse(0b100, ndim=3))
'HALF, MAIN, MAIN'
>>> str(Mesh.parse('MMH', ndim=3))
'MAIN, MAIN, HALF'
>>> str(Mesh.parse([True, False, True], ndim=3))
'HALF, MAIN, HALF'

The direct constructor takes an explicit code and dimension count:

>>> Mesh(code=0b100, ndim=3)
Mesh(HALF, MAIN, MAIN)

Methods

parse()

Normalize mesh_code into a Mesh.

remesh(target[, strict])

Return per-axis flags indicating which axes require averaging.

reverse()

Return a new Mesh with the axis order reversed (MSB to LSB).

Class Methods

_(mesh_code[, ndim])