Block utilities¶
Operations on Block instances that don’t belong on the class itself.
Each function below takes one or more Blocks and
returns a new one (or mutates in place, per its docstring). Grid-level
counterparts such as resample() and
interp_from_grid() are thin loops over these
block-granularity functions.
Combining and reshaping blocks¶
|
Concatenate multiple blocks along a specified axis. |
|
Return copies of block, each one blade pitch further round. |
|
Resample 3D block with vectorized interpolation while preserving patch connectivity. |
Interface-aligned velocities¶
Paired functions that rotate the meridional velocity components (Vx, Vr) by a
precomputed 2x2 matrix from rotation_matrices(), each the
inverse of its partner.
|
Convert meridional velocity to interface-aligned velocities. |
|
Convert interface-aligned velocities back to meridional components. |
Solution transfer¶
|
Interpolate a flow field onto |
|
Interpolate the solution on |
Post-processing and I/O¶
|
y+ on all six wall-adjacent boundary faces of |
|
Write a triangulated cut to a tm3 binary file. |
- block_util.concatenate(*blocks, axis=0)[source]¶
Concatenate multiple blocks along a specified axis.
- Parameters:
- Returns:
New block containing concatenated data
- Return type:
- Raises:
ValueError – If no blocks provided, blocks have incompatible working fluids, incompatible shapes, or patches on concatenation interfaces
- block_util.resolve_to_interface(block, rot_to)[source]¶
Convert meridional velocity to interface-aligned velocities.
Resolves the meridional velocity components \((V_x, V_r)\) to velocities aligned with an interface: velocity through the interface \(V_n\) and velocity in it \(V_s\),
\[\begin{split}V_n &= \cos\chi\, V_x + \sin\chi\, V_r \\ V_s &= -\sin\chi\, V_x + \cos\chi\, V_r\end{split}\]for the interface angle \(\chi\) that
rot_towas built from byrotation_matrices(). Inverse ofresolve_from_interface(). Applies the rotation directly to the nondimensional momentum inconserved_nd, the same approach asresolve_to_interface()on a patch’s averaging plane.- Parameters:
block (Block) – Block containing velocity data to be resolved.
rot_to (Array, shape
chi.shape + (2, 2)) – Rotation matrix, the first of the pair returned byrotation_matrices(). Building it once and reusing it across repeated to/from calls at the same angle – asmix_out()does each Newton iteration – avoids re-deriving the same sine and cosine on every call.
- Returns:
The input block with momentum updated to interface-aligned form. \(V_n\) becomes the new Vx, \(V_s\) becomes the new Vr, Vt unchanged.
- Return type:
- block_util.resolve_from_interface(block, rot_from)[source]¶
Convert interface-aligned velocities back to meridional components.
Converts interface-aligned velocities (\(V_n\) =
block.Vxthrough the interface, \(V_s\) =block.Vrin it) back to meridional components \((V_x, V_r)\),\[\begin{split}V_x &= \cos\chi\, V_n - \sin\chi\, V_s \\ V_r &= \sin\chi\, V_n + \cos\chi\, V_s\end{split}\]for the interface angle \(\chi\) that
rot_fromwas built from byrotation_matrices(). Inverse ofresolve_to_interface(). Applies the rotation directly to the nondimensional momentum inconserved_nd, the same approach asresolve_from_interface()on a patch’s averaging plane.- Parameters:
block (Block) – Block containing interface-aligned velocities (Vn=block.Vx, Vs=block.Vr).
rot_from (Array, shape
chi.shape + (2, 2)) – Rotation matrix, the second of the pair returned byrotation_matrices().
- Returns:
The input block with momentum updated to meridional form.
- Return type:
- block_util.resample(block, factors)[source]¶
Resample 3D block with vectorized interpolation while preserving patch connectivity.
Creates a new block by resampling with given factor(s). Critical indices from patch boundaries are preserved to maintain connectivity. Uses scipy.interpn for efficient multi-dimensional interpolation.
- Parameters:
- Returns:
New resampled block with updated patch indices and preserved metadata
- Return type:
- block_util.STATE = ('P', 'T', 'Vx', 'Vr', 'Vt', 'mu_turb')¶
Quantities transferred by the interpolation functions below.
Primitives, not the conserved variables. Conserved energy is measured from its fluid’s datum, so copying it between blocks whose fluids differ silently reinterprets it – a datum 600 K apart turns 400 K into 1000 K, with nothing raised. Pressure, temperature and velocity are datum-free and cross unchanged, which is also why interpolating them cannot produce a negative temperature the way interpolating
rhoecan.
- block_util.interp_from_arrays(block, arrays, crit=None)[source]¶
Interpolate a flow field onto
blockby index-space trilinear interpolation.The caller must have already set the fluid on block.
- Parameters:
block (Block) – Target block to receive the field.
arrays (sequence of Array) – One array per entry of
STATE, in that order, all of the same shape and all dimensional. They need not matchblock’s shape.crit (list of tuple, optional) – One
(src, block)pair of critical index arrays per dimension, locations to be held fixed through the mapping. None for a bare field, which maps end to end instead. Built from patches byinterp_from_grid(); this function has no notion of a patch.
- Raises:
AssertionError – If a different-shape interpolation produces values outside the source’s range – trilinear interpolation must not create new extrema.
- block_util.interp_from_grid(block, src)[source]¶
Interpolate the solution on
srcontoblock.A thin unpacking of
interp_from_arrays(): the state is read offsrcdimensionally, so the two blocks may carry different fluids – different reference scales, and different entropy and energy datums – without any conversion being needed.
- block_util.repeat_pitchwise(block, n_passage)[source]¶
Return copies of block, each one blade pitch further round.
A single passage is all a periodic solver computes, but it is rarely all anyone wants to look at: repeating it shows the flow as a cascade, where the passage-to-passage picture reads at a glance. The copies are successively rotated by
pitch, the first left where it is.Copies rather than one concatenated block, deliberately. Joining them would need to know which index runs pitchwise, which is a property of a grid’s topology and not something to guess; and a consumer that draws blocks — a contour plot, a mesh view — draws a list just as happily, while keeping one colour scale across the set.
Patches are dropped. A rotated copy is a view of the flow, not a member of a connected grid, and its periodic patches would claim connections that no longer hold.
- Parameters:
- Returns:
n_passage blocks, rotated by 0, 1, … pitches.
- Return type:
- Raises:
ValueError – If n_passage is less than one.
- block_util.wall_yplus(block)[source]¶
y+ on all six wall-adjacent boundary faces of
block.Post-processing only – NOT part of the per-step viscous kernel.
wall_yplus_field(_fortran/viscous.f90) reuses the exact Re/cf/d thatset_visc_force’s own wall function uses (both call the sharedwall_core), so this cannot silently drift from what the solver actually modeled at a face; it carries none ofset_visc_force’s k-slab/rolling-buffer machinery since it costs O(surface) per call, not O(volume) per step.The height is the wall-adjacent cell thickness
vol/|dA|, i.e. the distance to the first off-wall node – the point whose velocity the wall function actually samples in this cell-vertex scheme, so this is y+ where the closure is evaluated. Cell-centred codes report y+ at the first cell centroid instead, which is the usual “first cell y+” of mesh-sizing guidance; halve these values for that convention, since y+ is linear in wall distance at fixed friction velocity. That is not a conversion for comparing against another code’s number on the same mesh, though: a cell-centred solver samples its velocity at the half height too, so it infers its own friction velocity and does not simply see half of this.- Parameters:
block (Block)
- Returns:
Keys
yplus_i1,yplus_j1,yplus_k1,yplus_ni,yplus_nj,yplus_nk, each shaped like the correspondingijk_wall_viscface array, zero on non-wall cells.- Return type:
- block_util.to_tm3(block, filename, clip_quantile=0.01, **kwargs)[source]¶
Write a triangulated cut to a tm3 binary file.
- Parameters:
block (Block) – Triangulated block with shape
(ntri, 3).filename (str or path-like) – Output file path.
clip_quantile (float, optional) – Quantile used to clip the property colour range. The range is set to [q, 1-q] percentiles so that extreme outliers do not dominate the colour scale. Default is 0.01 (1%). Set to 0 to use the full min/max range.
**kwargs (array_like, shape (ntri, 3)) – Exactly one keyword argument: the key is used as the property name in the file, the value is the per-vertex scalar array.
- Raises:
ValueError – If the block is not triangulated, kwargs count != 1, or the value shape does not match the block shape.