You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guides/representations.md
+28Lines changed: 28 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -138,12 +138,40 @@ Current built-in representation conversions are point-first:
138
138
139
139
The representation design is intentionally extensible. Future geometric kinds (for example tangent and cotangent objects) can use different transformation categories (such as Jacobian pushforward/pullback) while keeping the same chart and manifold interfaces.
140
140
141
+
## Tangent Basis Changes
142
+
143
+
`change_basis` handles a narrower problem than `cconvert`: it keeps the chart fixed and only changes how tangent components are interpreted with respect to a basis.
144
+
145
+
In the current v1 implementation, this is intentionally limited to tangent data in Cartesian charts:
146
+
147
+
- supported basis changes: `CoordinateBasis` $
148
+
ightleftarrows$ `PhysicalBasis`
149
+
- supported representations: tangent representations such as `coord_disp` and `phys_disp`
150
+
- unsupported: point data (`NoBasis`) and non-Cartesian charts
In Cartesian charts the coordinate basis and physical basis coincide, so the component values are unchanged. The API exists so code can state basis intent explicitly and remain extensible to nontrivial basis changes later.
167
+
141
168
## Quick Reference
142
169
143
170
- Need only a same-manifold coordinate rewrite: `pt_map`
144
171
- Need general point mapping behavior: `pt_map`
145
172
- Need manifold compatibility checks: manifold methods like `M.pt_map`
146
173
- Need representation-aware conversions: `cconvert`
174
+
- Need same-chart tangent basis conversion: `change_basis`
147
175
- Need reusable conversion callables: `cmap`
148
176
- Need to infer basis kind from data: `guess_basis_kind`
149
177
- Need to infer semantic kind from data: `guess_semantic_kind`
- `from_rep`: source `Representation` (must have `TangentGeometry`).
1753
+
- `to_chart`: target chart.
1754
+
- `to_geom`: target geometry.
1755
+
- `to_rep`: target `Representation`.
1756
+
- `at`: `CDict` — base point in `from_chart` coordinates at which the tangent space is attached. Required for non-Cartesian charts (since the Jacobian depends on the base point).
1757
+
1758
+
**Semantics by basis:**
1759
+
1760
+
- **`CoordinateBasis`**: delegates to `jac_pt_map(at, from_chart, to_chart)` to obtain the Jacobian $J^j{}_i = \partial\tilde{q}^j/\partial q^i$, then applies $\tilde{v}^j = J^j{}_i v^i$.
1761
+
- **`PhysicalBasis`**: fetch the orthonormal frame matrices $B_{\rm from}$ (columns = physical basis vectors in Cartesian) and $B_{\rm to}$ via `frame_cart`, compute $R = B_{\rm to}^T B_{\rm from}$, apply $\hat{v}' = R \hat{v}$.
1762
+
1763
+
**Same-chart optimisation:** when `from_chart is to_chart`, returns `v` unchanged.
1764
+
1765
+
**`cconvert` integration:** `cconvert` dispatches to `tangent_map` when the source representation has `TangentGeometry`, passing `at` through the `at` keyword argument.
1766
+
1767
+
**Same-chart basis conversion:** `change_basis(v, chart, from_basis, to_basis, /, *, at)` changes tangent component conventions without changing charts. In v1 it is defined only for Cartesian charts and `CoordinateBasis` $
- [`MinkowskiMetric`](#software-spec-minkowskimetric): Lorentzian metric $\eta = \operatorname{diag}(-1, 1, 1, 1)$ on Minkowski spacetime; diagonal in the canonical Cartesian spacetime chart.
2626
2664
- [`HyperSphericalMetric`](#software-spec-hypersphericalmetric): round metric on $S^{n-1}$; diagonal entries follow the cumulative-sine rule $g_{kk} = \prod_{j < k}\sin^2\!\theta_j$.
2627
2665
2666
+
(software-spec-abstractdiagonalmetric)=
2667
+
2668
+
!!! info `AbstractDiagonalMetric`
2669
+
2670
+
`AbstractDiagonalMetric` is an abstract subclass of `AbstractMetric` for metrics whose matrix is diagonal at every base point in every compatible chart.
2671
+
2672
+
A metric is **diagonal** (equivalently, the coordinate chart is an **orthogonal coordinate system**) when all off-diagonal entries of the metric matrix vanish:
2673
+
2674
+
$$g_{ij}(p) = 0 \quad \text{for } i \neq j \quad \forall\, p \in U.$$
2675
+
2676
+
The coordinate basis vectors $\partial/\partial q^i$ are mutually orthogonal. The diagonal entries $g_{ii}(p)$ give the squared scale factors
2677
+
2678
+
$$h_i(p)^2 = g_{ii}(p),$$
2679
+
2680
+
and the infinitesimal line element simplifies to
2681
+
2682
+
$$ds^2 = \sum_i g_{ii}(q)\,(dq^i)^2.$$
2683
+
2684
+
**Role: structural marker, not behavioral interface.**
2685
+
2686
+
`AbstractDiagonalMetric` adds no new abstract methods beyond those of `AbstractMetric`. Its sole purpose is to **declare** that `metric_matrix` will always return a diagonal matrix. This allows:
2687
+
2688
+
- Dispatch specialisations that compute `scale_factors` more efficiently
2689
+
(e.g., extracting only the diagonal of $g$, or using squared Jacobian
2690
+
column norms instead of the full $J^\top J$).
2691
+
- Type-level distinction between orthogonal and general metrics in
2692
+
multiple-dispatch registrations.
2693
+
2694
+
**Subclassing contract:**
2695
+
2696
+
Subclasses must implement the two abstract members inherited from
2697
+
`AbstractMetric`:
2698
+
2699
+
- `signature` (abstract property): a tuple of $\pm 1$ of length `ndim`
2700
+
encoding the metric signature in coordinate order. Positive entries
2701
+
are Riemannian (space-like); a ``-1`` entry is pseudo-Riemannian
2702
+
(time-like).
2703
+
- `metric_matrix(chart, /, *, at, usys=None)` (abstract method): must
2704
+
return a diagonal `QuantityMatrix` (or plain `Array`) of shape
2705
+
`(ndim, ndim)` with all off-diagonal entries exactly zero.
2706
+
2707
+
All other behavioral requirements of `AbstractMetric` also apply:
2708
+
immutability (frozen dataclass), static JAX PyTree registration, and
2709
+
`jit`/`vmap` compatibility.
2710
+
2711
+
**Relationship to `AbstractMetric.is_diagonal`:**
2712
+
2713
+
`AbstractMetric.is_diagonal(chart, at=at)` inspects the metric matrix at
2714
+
a **specific base point** and returns a `bool`.
2715
+
`AbstractDiagonalMetric` makes this an unconditional **structural
2716
+
promise** across all base points: instances are always diagonal,
Copy file name to clipboardExpand all lines: docs/tutorials/cdict_objects.md
+19Lines changed: 19 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -184,6 +184,25 @@ Identity transform returns the exact same object:
184
184
True
185
185
```
186
186
187
+
## Changing Tangent Basis In-Place
188
+
189
+
Use `cxr.change_basis()` when a CDict already lives in the correct chart and you only need to reinterpret tangent components with respect to a different basis.
190
+
191
+
In v1 this supports Cartesian tangent data only. For Cartesian charts, coordinate and physical bases coincide, so the values are preserved.
0 commit comments