Cutting¶
Marching cubes algorithm and 3D structured grid cutting utilities.
This module implements the marching cubes algorithm for extracting isosurfaces from 3D structured grids, along with utilities for creating both structured meridional cuts and unstructured triangulated cuts. The marching cubes implementation uses precomputed lookup tables (EDGETABLE and TRITABLE) to efficiently determine which cell edges intersect an isosurface and how to triangulate those intersections. Key functionality includes extracting unstructured triangular cuts using signed distance fields, creating structured 2D meridional slices by interpolating along grid lines, and converting between structured quad meshes and unstructured triangle meshes. The module supports both direct marching cubes output and subsequent interpolation of unstructured data back onto structured grids for easier analysis.
Cuts along grid surfaces by index¶
The functions here extract cuts along an arbitrary meridional curve. To take a
cut along a grid surface of constant index, none of them are needed: a
Block supports numpy-style indexing, so block[i] or
block[:, j] returns a lower-dimensional structured cut that shares the
parent’s data as a zero-copy view. See the indexing section of
ember.block for the full rules.
- ember.cut.unstructured(grid, xr_cut)[source]¶
Take an unstructured cut through a grid using marching cubes.
Extracts a triangulated isosurface where the meridional cut curve intersects the grid, by running the marching cubes algorithm on the signed distance field of each block. Triangles from all intersected blocks are concatenated into a single unstructured block.
- Parameters:
- Returns:
cut – Unstructured triangulated cut, or None if the curve does not intersect any block.
- Return type:
- ember.cut.structured_meridional(grid, xr_cut)[source]¶
Slice a grid along a meridional curve into structured 2D cuts.
For each block, walks every \((i, k)\) grid line and linearly interpolates to the first
jlocation where the signed distance to the cut curve changes sign, producing one structured(ni, nk)cut per intersected block.- Parameters:
- Returns:
cut – Grid of 2D structured blocks, each shape (ni, nk), holding the cut data. Blocks that the curve does not intersect are omitted, so the grid is empty when there is no intersection.
- Return type:
- ember.cut.interpolate_to_structured(unstructured_block, interp_shape, Beta=0.0, periodic=True, rtol=0.05)[source]¶
Interpolate an unstructured triangular cut onto a structured grid.
Builds a structured
(ni, nj)grid that conforms to the meridional line of the cut and resolves the circumferential direction, then interpolates the triangle-vertex point cloud onto it:index
iruns along the meridional line. A constant-igridline has(x, r) = constand varies only in theta. Nodes are cosine-clustered along the normalised arc length \(\zeta \in [0, 1]\) (double-sided cosine clustering), resolving both extremities of the line.index
jruns in theta. A constant-jgridline hastheta = const(straight lines), laid out uniformly over one full pitch.
Straight constant-theta lines rely on the solution being periodic in theta with period
pitch = 2*pi/Nb: source points are wrapped modulo the pitch so a single uniform theta window is fully covered however the cut’s theta band skews along the line. Flow variables are interpolated in the unfolded \((\zeta, \theta)\) unit space using linear interpolation with a nearest-neighbour fallback at the arc-length ends.- Parameters:
unstructured_block (Block, shape (ntri, 3)) – Unstructured triangulated cut, for example from
unstructured().interp_shape (tuple of int) – Target structured grid shape
(ni, nj).Beta (float, optional) – Pitch angle in degrees fixing the meridional travel direction: the arc-length-zero end is the one with the smallest projection onto
d = (-sin Beta, cos Beta).Beta = 0puts arc length 0 at minimum r;Beta = +/-90at maximum / minimum x. Default 0.periodic (bool, optional) – If True (default), wrap theta modulo the pitch so the uniform theta window is fully populated. If False, span the raw cloud theta range and rely on the nearest-neighbour fallback outside the data hull.
rtol (float, optional) – Relative tolerance for the periodic coverage check. With
periodic=Truethe cloud theta span must be at least(1 - rtol) * pitchor aValueErroris raised. Default 0.05.
- Returns:
cut – Structured block with data interpolated onto the line-conforming grid.
- Return type: