@@ -62,6 +62,24 @@ def _ratio_zero_on_axis(num: Array, denom: Array, /) -> Array:
6262 return jnp .where (denom == 0 , jnp .zeros_like (ratio ), ratio )
6363
6464
65+ def _require_cart3d_phase_space (chart : Any , / , * , direction : str ) -> None :
66+ """Validate a two-factor ``Cart3D`` Cartesian phase-space product chart.
67+
68+ ``direction`` is ``"to"`` (``chart`` is the source of ``pt_map`` *to*
69+ ``PoincarePolar6D``) or ``"from"`` (``chart`` is the target of ``pt_map``
70+ *from* it); it only selects the error wording. Raises ``NotImplementedError``
71+ unless ``chart`` has exactly two ``Cart3D`` factors [position, velocity].
72+ """
73+ if len (chart .factors ) != 2 or not all (isinstance (f , Cart3D ) for f in chart .factors ):
74+ role = "source" if direction == "to" else "target"
75+ msg = (
76+ f"pt_map { direction } PoincarePolar6D requires a Cartesian phase-space "
77+ f"{ role } : a two-factor CartesianProductChart of (Cart3D, Cart3D) "
78+ f"[position, velocity]; got factors { chart .factors !r} ."
79+ )
80+ raise NotImplementedError (msg )
81+
82+
6583#####################################################################
6684# Point transformations
6785
@@ -1795,15 +1813,7 @@ def pt_map(
17951813 del usys
17961814 assert from_M == from_chart .M # noqa: S101
17971815 assert to_M == to_chart .M # noqa: S101
1798- if len (from_chart .factors ) != 2 or not all (
1799- isinstance (f , Cart3D ) for f in from_chart .factors
1800- ):
1801- msg = (
1802- "pt_map to PoincarePolar6D requires a Cartesian phase-space source: a "
1803- "two-factor CartesianProductChart of (Cart3D, Cart3D) [position, "
1804- f"velocity]; got factors { from_chart .factors !r} ."
1805- )
1806- raise NotImplementedError (msg )
1816+ _require_cart3d_phase_space (from_chart , direction = "to" )
18071817
18081818 pos , vel = from_chart .split_components (p )
18091819 x , y , z = pos ["x" ], pos ["y" ], pos ["z" ]
@@ -1869,20 +1879,13 @@ def pt_map(
18691879 del usys
18701880 assert from_M == from_chart .M # noqa: S101
18711881 assert to_M == to_chart .M # noqa: S101
1872- if len (to_chart .factors ) != 2 or not all (
1873- isinstance (f , Cart3D ) for f in to_chart .factors
1874- ):
1875- msg = (
1876- "pt_map from PoincarePolar6D requires a Cartesian phase-space target: a "
1877- "two-factor CartesianProductChart of (Cart3D, Cart3D) [position, "
1878- f"velocity]; got factors { to_chart .factors !r} ."
1879- )
1880- raise NotImplementedError (msg )
1882+ _require_cart3d_phase_space (to_chart , direction = "from" )
18811883
18821884 rho , z , dt_rho , dt_z = p ["rho" ], p ["z" ], p ["dt_rho" ], p ["dt_z" ]
1883- s = jnp .hypot (p ["pp_phi" ], p ["pp_phidot" ])
18841885 phi = jnp .atan2 (p ["pp_phidot" ], p ["pp_phi" ])
1885- lz = s ** 2 / 2 # sign(Lz) is not recoverable from the forward map; take Lz >= 0
1886+ # Lz = s²/2 with s = hypot(pp_phi, pp_phidot); compute directly to skip the
1887+ # sqrt (sign(Lz) is not recoverable from the forward map, so take Lz >= 0).
1888+ lz = (p ["pp_phi" ] ** 2 + p ["pp_phidot" ] ** 2 ) / 2
18861889 sinp , cosp = jnp .sin (phi ), jnp .cos (phi )
18871890
18881891 pos = {"x" : rho * sinp , "y" : rho * cosp , "z" : z }
0 commit comments