Connectivity
Connectivity detection for multi-block structured (Plot3D) meshes.
The algorithm runs in three phases:
Phase 1 – Candidate pairing: Block pairs whose axis-aligned bounding boxes (AABBs) overlap are identified by
candidate_neighbor_pairs(). Only these pairs proceed to expensive point matching.Phase 2 – Face matching: For each candidate pair,
find_matching_blocks()compares every outer face of block i against every outer face of block j. Each comparison (get_face_intersection()) tries three strategies in order:Step 1 (same-size fast path) – if both faces have the same number of points, try all 8 permutations via
_try_permutations_with_transpose().Step 2 (sub-region) – for different-size faces, locate the smaller face’s diagonal corners on the larger face to extract a sub-region, then try the same 8 permutations.
Step 3 (fallback) – per-point geometric matching for any remaining cases.
Phase 3 – Fresh-face validation: Outer faces left unmatched after Phase 2 (because a partner block’s face pool was consumed by an earlier pair) are re-checked against fresh (un-consumed) outer faces of neighbouring blocks.
Orientation system
When two faces match, the module records how their local (u, v) axes
relate. Because each of the two varying axes can independently be reversed
and the two axes can be swapped, there are 2 x 2 x 2 = 8 distinct
orientations, encoded as 2x2 signed permutation matrices in
PERMUTATION_MATRICES.
The index into that array is computed with the bit formula:
index = u_reversed | (v_reversed << 1) | (swapped << 2)
where u_reversed / v_reversed are booleans indicating whether the traversal direction along that axis is flipped between the two faces, and swapped indicates whether the u and v axes of face 1 map to v and u of face 2 (a cross-plane match). Indices 0–3 are the four direct (non-swapped) permutations; indices 4–7 are the four transposed (swapped) permutations.
JSON export convention
The exported permutation_index follows the diagonal (lb/ub) convention:
In-plane matches (perm 0–3):
permutation_indexis -1 because the traversal direction is fully encoded in block2’s lb/ub ordering.Cross-plane matches (perm 4–7):
permutation_indexis the actual index because lb/ub alone cannot represent an axis swap.
The permutation_matrix field always contains the actual 2x2 matrix.
- plot3d.connectivity.PERMUTATION_MATRICES = array([[[ 1, 0], [ 0, 1]], [[-1, 0], [ 0, 1]], [[ 1, 0], [ 0, -1]], [[-1, 0], [ 0, -1]], [[ 0, 1], [ 1, 0]], [[ 0, -1], [ 1, 0]], [[ 0, 1], [-1, 0]], [[ 0, -1], [-1, 0]]], dtype=int8)
8 canonical 2x2 signed permutation matrices.
Bit encoding:
index = u_reversed | (v_reversed << 1) | (swapped << 2)
- plot3d.connectivity.candidate_neighbor_pairs(blocks: List[Block], tol: float = 1e-06)[source]
Returns candidate block pairs whose AABBs overlap or nearly touch.
This replaces the former centroid-distance approach which only considered the N nearest blocks and could miss neighbours for L-shaped or elongated geometries. AABB overlap is both more robust and more correct.
- Parameters:
blocks (List[Block]) – list of all your blocks
tol (float) – AABB expansion tolerance
- Returns:
candidate (i, j) pairs with i < j
- Return type:
List[Tuple[int,int]]
- plot3d.connectivity.combinations_of_nearest_blocks(blocks: List[Block], nearest_nblocks: int = 4)[source]
Returns the indices of the nearest N blocks based on their centroid.
Deprecated since version Use:
candidate_neighbor_pairs()instead for AABB-based pairing.- Parameters:
blocks (List[Block]) – list of all your blocks
nearest_nblocks (int) – number of nearest blocks to consider
- Returns:
combinations of nearest blocks
- Return type:
List[Tuple[int,int]]
- plot3d.connectivity.connectivity(blocks: List[Block])[source]
Returns a dictionary outlining the connectivity of the blocks along with any exterior surfaces.
Each face match dict includes an
orientationsub-dict with:permutation_index: -1 for in-plane matches (direction encoded in lb/ub), or the actual index (4-7) for cross-plane matches.plane:'in-plane'or'cross-plane'.permutation_matrix: the actual 2x2 signed permutation matrix.
- Parameters:
blocks (List[Block]) – List of all blocks in multi-block plot3d mesh
- Returns:
All matching faces formatted as a list of { ‘block1’: {‘block_index’, ‘lb’, ‘ub’} } (List[Dict]): All exterior surfaces formatted as a list of { ‘block_index’, ‘lb’, ‘ub’, ‘id’ }
- Return type:
(List[Dict])
- plot3d.connectivity.connectivity_fast(blocks: List[Block])[source]
Find connectivity by GCD-reducing blocks first for speed.
Computes the minimum GCD across all block dimensions, reduces all blocks uniformly, runs
connectivity(), then scales bounds back up.Face match dicts follow the diagonal (lb/ub) convention:
permutation_indexis -1 for in-plane, actual index for cross-plane.- Parameters:
blocks (List[Block]) – List of blocks to find connectivity for.
- Returns:
Face matches with orientation info. (List[Dict]): Outer (non-connected) faces.
- Return type:
(List[Dict])
- plot3d.connectivity.face_matches_to_dict(face1: Face, face2: Face, block1: Block, block2: Block)[source]
Makes sure the diagonal of face 1 match the diagonal of face 2
- plot3d.connectivity.find_matching_blocks(block1: Block, block2: Block, block1_outer: List[Face], block2_outer: List[Face], tol: float = 1e-06)[source]
Takes two blocks and finds all matching pairs
- Parameters:
Note
This function was changed to be given an input of outer faces for block 1 and block 2. Outer faces can change and we should use the updated value
- Returns:
- containing
df (pandas.DataFrame): corners of matching pair as block1_corners,block2_corners ([imin,jmin,kmin],[imax,jmax,kmax]), ([imin,jmin,kmin],[imax,jmax,kmax])
block1_outer (List[Face]):
block2_outer (List[Face]):
- Return type:
(tuple)
- plot3d.connectivity.get_face_intersection(face1: Face, face2: Face, block1: Block, block2: Block, tol: float = 1e-06)[source]
Get the index of the intersection between two faces located on two different blocks.
- Three-step approach:
Step 1 (fast): Same-size faces — try 8 permutations (4 direction + 4 transposed). Step 2 (subregion): Different-size faces — find smaller face’s corners on larger
face to identify subregion, then try 8 permutations on subregion.
Step 3 (fallback): Per-point geometric matching for any remaining cases.
- Parameters:
- Returns:
containing
(pandas.DataFrame): dataframe with matches. Columns = i1, j1, k1, i2, j2, k2
(List[Face]): any split faces from block 1
(List[Face]): any split faces from block 2
- Return type:
(Tuple)
- plot3d.connectivity.select_multi_dimensional(T: ndarray, dim1: tuple, dim2: tuple, dim3: tuple)[source]
- Takes a block (T) and selects X,Y,Z from the block given a face’s dimensions
theres really no good way to do this in python
- Parameters:
T (np.ndarray) – arbitrary array so say a full matrix containing X
dim1 (tuple) – 20,50 this selects X in the i direction from i=20 to 50
dim2 (tuple) – 40,60 this selects X in the j direction from j=40 to 60
dim3 (tuple) – 10,20 this selects X in the k direction from k=10 to 20
- Returns:
returns X or Y or Z given some range of I,J,K
- Return type:
np.ndarray