Skip to content

Commit 305312f

Browse files
committed
documentation updates
1 parent f3b73ff commit 305312f

File tree

8 files changed

+159745
-23
lines changed

8 files changed

+159745
-23
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
# vs code folders
77
.vscode/
88
*.p3d
9+
# Allow test data p3d files
10+
!python/tests/data/cross_plane_pair.p3d
911
*.x
1012
*.lock
1113
python/mesh.pickle

docs/notes/connectivity.rst

Lines changed: 122 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,86 @@ When faces lie on **different constant planes** (e.g., a K-face connects to a J-
5252

5353
**4 × 2 = 8 total permutations. lb/ub only encodes 4.**
5454

55-
The ``orientation`` vector solves this. It is computed by ``_compute_orientation()`` in ``connectivity.py`` and maps each face1 axis to a face2 axis:
55+
Permutation Matrix System
56+
~~~~~~~~~~~~~~~~~~~~~~~~~~
5657

57-
.. code-block:: python
58-
59-
# orientation = [d1_maps_to, d2_maps_to, d3_maps_to]
60-
# 1-indexed: 1=I, 2=J, 3=K
61-
#
62-
# Example: orientation = [2, 1, 3]
63-
# face1 I-axis -> face2 J-axis
64-
# face1 J-axis -> face2 I-axis
65-
# face1 K-axis -> face2 K-axis
58+
Both the Python and Rust implementations encode all 8 orientations as a 3-bit ``permutation_index`` into an array of 2×2 signed matrices (``PERMUTATION_MATRICES``):
6659

67-
Direction (forward/reverse) is encoded in the ``lb/ub`` values, not in the orientation vector. The ``verify.py`` module's ``_generate_permutations()`` tests all 8 combinations (4 direct + 4 transposed) to confirm the match.
60+
.. code-block:: text
6861
69-
For a detailed analysis with diagrams, see the `Root Cause Analysis <https://github.com/nasa/Plot3D_utilities/blob/main/docs/notes/unverified_connectivity_findings.md>`_ document.
62+
permutation_index = u_reversed | (v_reversed << 1) | (swapped << 2)
7063
71-
**Rust version**: The `plot3d-rs <https://github.com/pjuangph/plot3d-rs>`_ crate mirrors this logic but stores orientation as flags: ``Orientation { swapped, u_reversed, v_reversed }``. Both representations encode the same 8 permutations.
64+
.. list-table:: The 8 Permutation Matrices
65+
:header-rows: 1
66+
:widths: 8 8 8 8 8 20 20
67+
68+
* - Index
69+
- Binary
70+
- u_rev
71+
- v_rev
72+
- swap
73+
- Matrix
74+
- Effect
75+
* - 0
76+
- ``000``
77+
- no
78+
- no
79+
- no
80+
- ``[[ 1, 0],[ 0, 1]]``
81+
- identity
82+
* - 1
83+
- ``001``
84+
- yes
85+
- no
86+
- no
87+
- ``[[-1, 0],[ 0, 1]]``
88+
- flip u
89+
* - 2
90+
- ``010``
91+
- no
92+
- yes
93+
- no
94+
- ``[[ 1, 0],[ 0,-1]]``
95+
- flip v
96+
* - 3
97+
- ``011``
98+
- yes
99+
- yes
100+
- no
101+
- ``[[-1, 0],[ 0,-1]]``
102+
- flip both
103+
* - 4
104+
- ``100``
105+
- no
106+
- no
107+
- yes
108+
- ``[[ 0, 1],[ 1, 0]]``
109+
- transpose
110+
* - 5
111+
- ``101``
112+
- yes
113+
- no
114+
- yes
115+
- ``[[ 0,-1],[ 1, 0]]``
116+
- transpose + flip u
117+
* - 6
118+
- ``110``
119+
- no
120+
- yes
121+
- yes
122+
- ``[[ 0, 1],[-1, 0]]``
123+
- transpose + flip v
124+
* - 7
125+
- ``111``
126+
- yes
127+
- yes
128+
- yes
129+
- ``[[ 0,-1],[-1, 0]]``
130+
- transpose + both
131+
132+
In **Python**, the ``PERMUTATION_MATRICES`` constant is defined in ``connectivity.py`` and ``_orient_vec_to_permutation()`` converts the legacy orientation vector to a ``permutation_index``.
133+
134+
In **Rust**, the ``PERMUTATION_MATRICES`` constant is in ``face_record.rs`` and each ``FaceMatch`` carries an ``Orientation { permutation_index, plane }`` set by ``verify_connectivity``.
72135

73136
The ``u`` and ``v`` names are abstract — they map to concrete i/j/k axes depending on which axis is constant:
74137

@@ -91,6 +154,52 @@ The ``u`` and ``v`` names are abstract — they map to concrete i/j/k axes depen
91154

92155
So ``u_reversed: true`` means the outer-loop axis runs opposite direction on block2 vs block1, and ``v_reversed: true`` means the inner-loop axis runs opposite.
93156

157+
Legacy Orientation Vector
158+
~~~~~~~~~~~~~~~~~~~~~~~~~~
159+
160+
The older Python ``_compute_orientation()`` in ``connectivity.py`` produces an orientation vector that maps each face1 axis to a face2 axis:
161+
162+
.. code-block:: python
163+
164+
# orientation = [d1_maps_to, d2_maps_to, d3_maps_to]
165+
# 1-indexed: 1=I, 2=J, 3=K
166+
#
167+
# Example: orientation = [2, 1, 3]
168+
# face1 I-axis -> face2 J-axis
169+
# face1 J-axis -> face2 I-axis
170+
# face1 K-axis -> face2 K-axis
171+
172+
Direction (forward/reverse) is encoded in the ``lb/ub`` values, not in the orientation vector. The ``_orient_vec_to_permutation()`` function converts this vector to a ``permutation_index`` for the unified system. The verification modules (``verify_connectivity`` / ``verify_periodicity``) test all 8 permutations to confirm the match.
173+
174+
For a detailed analysis with diagrams, see the `Root Cause Analysis <https://github.com/nasa/Plot3D_utilities/blob/main/docs/notes/unverified_connectivity_findings.md>`_ document.
175+
176+
177+
Directed Diagonal for GHT_CONN Export
178+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
179+
180+
The GlennHT connectivity file (``.ght_conn``) uses a **directed diagonal** convention where each face is specified by two corners ``(IMIN, JMIN, KMIN)`` and ``(IMAX, JMAX, KMAX)``. For cross-plane matches, the traversal direction is encoded by allowing the "max" corner to be less than the "min" corner on reversed axes. For example:
181+
182+
.. code-block:: text
183+
184+
1 1 1 1 25 409 1
185+
2 409 1 1 1 1 25
186+
187+
Here block 2's i-axis runs 409 → 1 (reversed), encoding the cross-plane orientation without a separate permutation matrix.
188+
189+
When connectivity is computed in **Python** (via ``connectivity_fast``), the ``lb``/``ub`` values already encode the directed diagonal from the point-match traversal order.
190+
191+
When connectivity is computed in **Rust** (via the ``connectivity-finder`` binary in grid-packed), the JSON output uses ascending ``lo``/``hi`` bounds with a ``permutation_index`` (0-7). Use ``reconstruct_directed_diagonal()`` to convert these to directed ``lb``/``ub`` before exporting:
192+
193+
.. code-block:: python
194+
195+
from plot3d.connectivity import reconstruct_directed_diagonal
196+
197+
# face_match has ascending lb/ub + permutation_index from Rust JSON
198+
directed_match = reconstruct_directed_diagonal(face_match)
199+
# directed_match now has directed lb/ub and permutation_index = -1
200+
201+
The ``export_to_glennht_conn()`` function applies this reconstruction automatically, so callers do not need to call it explicitly.
202+
94203

95204
Plotting Connectivity using Paraview
96205
****************************************

docs/notes/exporting.rst

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
Exporting to GlennHT Connectivity Files
22
###############################################
3-
This is an example of how I read a mesh, convert it to ascii, save it, find connectivity, find periodicty and export to glennht format.
3+
4+
.. note::
5+
6+
The GHT_CONN file uses a **directed diagonal** convention where cross-plane
7+
matches encode traversal direction in the corner ordering (e.g., ``IMIN > IMAX``
8+
means the i-axis is reversed). ``export_to_glennht_conn()`` handles this
9+
automatically via ``reconstruct_directed_diagonal()``. See
10+
:ref:`Directed Diagonal for GHT_CONN Export <connectivity>` for details.
11+
12+
This is an example of how I read a mesh, convert it to ascii, save it, find connectivity, find periodicty and export to glennht format.
413
In this example we will use the file `PahtCascade-ASCII <https://nasa-public-data.s3.amazonaws.com/plot3d_utilities/PahtCascade-ASCII.xyz>`_
514

615
.. code-block:: python

docs/notes/periodicity.rst

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,20 @@ In this example we will use the file `PahtCascade-ASCII <https://nasa-public-da
3232
:width: 800px
3333
:align: center
3434
:alt: periodic surface block 2 exit of the domain
35-
:figclass: align-center
35+
:figclass: align-center
36+
37+
Verification
38+
**************
39+
40+
After computing periodic matches, call ``verify_periodicity`` to confirm that
41+
face pairs align after rotation and to set the correct ``permutation_index``
42+
(0-7) from the ``PERMUTATION_MATRICES`` system. This is the same 8-permutation
43+
scheme used for connectivity — see :doc:`connectivity` for the full table.
44+
45+
.. code-block:: python
46+
47+
from plot3d import verify_periodicity
48+
49+
verified, mismatched = verify_periodicity(
50+
blocks, periodic_surfaces, rotation_angle_rad, rotation_axis='x', tol=1e-4
51+
)

python/plot3d/connectivity.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@
8686
"""
8787

8888

89-
9089
def _orient_vec_to_permutation(orient_vec: list, lb1: list, ub1: list,
9190
lb2: list, ub2: list) -> Tuple[int, str]:
9291
"""Convert an orientation vector to a ``(permutation_index, plane)`` tuple.

python/plot3d/glennht/export_functions.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -551,22 +551,22 @@ def summarize_contiguous(records: List[Dict[str, Any]]) -> Dict[str, Any]:
551551
}
552552

553553

554-
def export_to_glennht_conn(matches:List[Dict[str, Dict[int, str]]],outer_faces:List[Dict[str,int]],filename:str,
554+
def export_to_glennht_conn(matches:List[Dict[str, Dict[int, str]]],outer_faces:List[Dict[str,int]],filename:str,
555555
gif_pairs:List[List[Dict[str, int]]],gif_faces:List[List[Dict[str, int]]],
556556
volume_zones:List[Dict[str,Any]]):
557-
"""Exports the connectivity to GlennHT format
557+
"""Exports the connectivity to GlennHT format
558558
559559
Args:
560-
matches (Dict[str,Dict[int,str]]): Any matching faces between blocks
561-
outer_faces (Dict[str,int]): Non matching faces of all blocks or surfaces to consider
560+
matches (Dict[str,Dict[int,str]]): Any matching faces between blocks
561+
outer_faces (Dict[str,int]): Non matching faces of all blocks or surfaces to consider
562562
"""
563563
lines = list()
564-
564+
565565
# Print face matches
566566
blocks = ['block1','block2']
567567
nMatches = len(matches)
568-
lines.append(f'{nMatches}\n') # Print number of matches
569-
for match in matches:
568+
lines.append(f'{nMatches}\n') # Print number of matches
569+
for match in matches:
570570
for block in blocks:
571571
block_indx = match[block]['block_index']+1 # type: ignore # block1 and block2 are arbitrary names, the key is the block index
572572
lb = match[block]['lb'] # type: ignore

0 commit comments

Comments
 (0)