Topologie (pyna.topo)#

Le paquet pyna.topo fournit des algorithmes d’analyse de la structure topologique des cartes de Poincaré : îlots magnétiques, cycles X/O, variétés stables/instables et enchevetrements heterocliniques.

La conception centrale est une hierarchie a deux couches :

pyna.topo.core

géométrie de dimension finie independante du domaine : Trajectory, Orbit, PeriodicOrbit, Cycle, Island, IslandChain, Tube et TubeChain.

pyna.topo.toroidal

spécialisations pour le confinement magnétique qui ajoutent R/Z/phi, les nombres d’enroulement, les charges utiles de monodromie, les coupes de section appuyees par cyna et les diagnostics toroidaux.


Cartes de Poincaré#


Hierarchie des objets geometriques#

pyna.topo._base – Base classes for topology / geometry objects.

Extracted to a separate module to avoid circular imports between island_chain.py and invariant.py.

Hierarchy#

GeometricObject — root ABC for sampled or exact geometric objects
InvariantSet — root ABC for mathematically invariant objects

InvariantManifold — invariant set with a well-defined intrinsic dimension

Trajectory — sampled continuous curve (not assumed invariant) Orbit — periodic orbit of a discrete map (invariant)

SectionCuttable — mixin protocol for objects that can be sliced by a

Poincaré section

Design principle#

Finite sampled geometry should not automatically be promoted to an invariant object. In particular, a numerically traced open trajectory is useful geometry, but it is not an InvariantSet merely because it came from a flow integration. Established periodic objects such as Cycle and PeriodicOrbit remain in the invariant hierarchy.

InvariantObject remains available as a backward-compatible alias that points to InvariantSet so that existing subclass declarations keep working.

class pyna.topo._base.GeometricObject[source]

Bases: ABC

Abstract base for sampled or exact geometric/topological objects.

This is intentionally broader than InvariantSet: it covers both mathematically invariant objects and finite numerical representations such as sampled trajectories.

property ambient_dim: int | None[source]

Dimension of the ambient phase space (None if unknown).

diagnostics()[source]

Return a structured diagnostic / debug dict.

Return type:

Dict[str, Any]

property label: str | None[source]

Human-readable identifier. Override in subclasses.

class pyna.topo._base.InvariantManifold[source]

Bases: InvariantSet

An invariant set with a well-defined intrinsic dimension.

InvariantManifold sits between the abstract InvariantSet and the concrete geometry types (FixedPoint, PeriodicOrbit, InvariantTorus, StableManifold, …).

The key additional concept is intrinsic dimension:

  • FixedPoint → intrinsic_dim = 0

  • Orbit / PeriodicOrbit → intrinsic_dim = 0 (finite set of map points)

  • Trajectory / Cycle → intrinsic_dim = 1 (continuous curve)

  • InvariantTorus of order k → intrinsic_dim = k

  • StableManifold of a hyperbolic orbit → intrinsic_dim = dim(E^s)

The codimension is ambient_dim - intrinsic_dim when ambient_dim is known.

Subclasses must set intrinsic_dim (as a class attribute, __init__ argument, or @property). The default is None (unknown).

property codim: int | None[source]

Codimension = ambient_dim − intrinsic_dim (None if either is unknown).

property intrinsic_dim: int | None[source]

Intrinsic dimension of the invariant manifold (None if unknown).

pyna.topo._base.InvariantObject

Backward-compatible alias. Prefer InvariantSet in new code.

class pyna.topo._base.InvariantSet[source]

Bases: GeometricObject

Abstract base for any invariant geometric object of a dynamical system.

An invariant set S satisfies φ^t(S) ⊆ S for all t (continuous flow) or P(S) = S (discrete map).

Design: Pure interface — no __init__, no state fields. Concrete subclasses (including dataclasses) provide their own fields and satisfy the interface via @property overrides.

section_cut and diagnostics are no longer abstract. Not every invariant set can be meaningfully cut by a section (e.g. a KAM torus in a 6N-dim N-body phase space may have no natural Poincaré section). Use the SectionCuttable mixin to mark objects that can be sectioned.

Optional interface (all have sensible defaults):

.label @property -> str | None .ambient_dim @property -> int | None .poincare_map @property -> PoincareMap | None .phase_space @property -> PhaseSpace | None .diagnostics() -> dict .section_cut(s) -> list (raises NotImplementedError by default)

diagnostics()[source]

Return a structured diagnostic / debug dict.

The default implementation returns a minimal dict with just the class name. Subclasses are encouraged to override and add domain-specific information.

Return type:

Dict[str, Any]

property phase_space[source]

Phase space of the associated map (PhaseSpace | None).

property poincare_map[source]

The Poincaré map this object lives in (PoincareMap | None).

section_cut(section=None)[source]

Return the intersection of this invariant with a Poincaré section.

Raises NotImplementedError by default. Subclasses that support sectioning should override (and ideally also derive from SectionCuttable).

Return type:

list

class pyna.topo._base.Orbit[source]

Bases: InvariantManifold

A periodic orbit of a discrete map: a finite set of phase-space points.

Mathematically, an m-periodic orbit is a set {x₁, …, xₘ} satisfying P(xₖ) = xₖ₊₁ (indices mod m) and P^m(xₖ) = xₖ for the map P.

An Orbit is fundamentally different from a Trajectory:

  • Trajectory — solution of a continuous ODE (a curve, dim=1)

  • Orbit — fixed-point set of a discrete map (finite points, dim=0)

Concrete subtype#

  • PeriodicOrbit — Stores m FixedPoint objects, one per map iteration.

intrinsic_dim = 0 (a finite set of isolated points in the section).

property intrinsic_dim: int[source]

Intrinsic dimension of the invariant manifold (None if unknown).

class pyna.topo._base.SectionCuttable(*args, **kwargs)[source]

Bases: Protocol

Protocol / mixin marking objects that can be sliced by a Poincaré section.

Any class that implements section_cut(section) -> list satisfies this protocol. It is deliberately not a subclass of InvariantSet so that it can be mixed in freely (e.g. class Tube(InvariantSet, SectionCuttable)).

Usage:

if isinstance(obj, SectionCuttable):
    pts = obj.section_cut(my_section)
section_cut(section=None)[source]
Return type:

list

class pyna.topo._base.Trajectory[source]

Bases: GeometricObject

A finite sampled trajectory: a 1-D curve representation in phase space.

A Trajectory is numerical geometry, not a proof of invariance. It may be an open finite-time integration, an approximate trace, or a sampled representation of a genuinely invariant object. Established periodic flow orbits should be represented by Cycle, which may own a Trajectory as one representation.

property intrinsic_dim: int[source]

Geometric curve dimension of the sampled trajectory.

section_cut(section=None)[source]
Return type:

list

pyna.topo.core — Generic finite-dimensional topology objects.

This module is the canonical domain-agnostic core. Nothing here assumes toroidal geometry or uses hard-coded coordinate names such as R/Z/phi.

Class hierarchy#

SectionPoint(InvariantManifold, intrinsic_dim=0)

→ toroidal.FixedPoint

PeriodicOrbit(InvariantManifold, intrinsic_dim=0)

→ toroidal.PeriodicOrbit

Cycle(InvariantManifold, intrinsic_dim=1)

→ toroidal.Cycle

Island(InvariantSet)

→ toroidal.Island

IslandChain(InvariantSet)

→ toroidal.IslandChain

Tube(InvariantSet)

→ toroidal.Tube

TubeChain(InvariantSet)

→ toroidal.TubeChain

class pyna.topo.core.Cycle(trajectory=None, period_value=None, return_map_orbit=None, metadata=<factory>)[source]

Bases: InvariantManifold

Periodic orbit of a continuous-time flow in arbitrary finite dimension.

This is the generic root for toroidal.Cycle. The trajectory field is optional — toroidal subclasses may represent the cycle via a sections dict instead.

property ambient_dim: int | None[source]

Dimension of the ambient phase space (None if unknown).

diagnostics()[source]

Return a structured diagnostic / debug dict.

The default implementation returns a minimal dict with just the class name. Subclasses are encouraged to override and add domain-specific information.

Return type:

Dict[str, Any]

property intrinsic_dim: int[source]

Intrinsic dimension of the invariant manifold (None if unknown).

metadata: Dict[str, Any][source]
period_value: float | None = None[source]
return_map_orbit: PeriodicOrbit | None = None[source]
section_cut(section=None)[source]

Return the intersection of this invariant with a Poincaré section.

Raises NotImplementedError by default. Subclasses that support sectioning should override (and ideally also derive from SectionCuttable).

Return type:

PeriodicOrbit

section_points(section_value=None, section_label=None, tol=1e-09)[source]
Return type:

List[SectionPoint]

trajectory: Trajectory | None = None[source]
class pyna.topo.core.Island(O_orbit=<factory>, X_orbits=<factory>, child_chains=<factory>, parent_chain=None, label=None, metadata=<factory>)[source]

Bases: InvariantManifold

One island of a discrete Poincaré-map resonance structure.

This is the generic root for toroidal.Island.

Fields#

O_orbitPeriodicOrbit

Elliptic periodic orbit at the island centre.

X_orbitslist of PeriodicOrbit

Hyperbolic periodic orbit(s) bounding the island (may be empty).

child_chainslist of IslandChain

Sub-chains nested inside this island.

parent_chainIslandChain or None

The IslandChain that contains this island.

O_orbit: PeriodicOrbit[source]
property O_point: SectionPoint | None[source]
X_orbits: List[PeriodicOrbit][source]
property X_points: List[SectionPoint][source]
add_child_chain(chain)[source]
Return type:

None

child_chains: List[IslandChain][source]
diagnostics()[source]

Return a structured diagnostic / debug dict.

The default implementation returns a minimal dict with just the class name. Subclasses are encouraged to override and add domain-specific information.

Return type:

Dict[str, Any]

property intrinsic_dim: int[source]

Intrinsic dimension of the invariant manifold (None if unknown).

label: str | None = None[source]
metadata: Dict[str, Any][source]
parent_chain: IslandChain | None = None[source]
section_cut(section=None)[source]

Return the intersection of this invariant with a Poincaré section.

Raises NotImplementedError by default. Subclasses that support sectioning should override (and ideally also derive from SectionCuttable).

Return type:

list

step()[source]
Return type:

Island

step_back()[source]
Return type:

Island

class pyna.topo.core.IslandChain(islands=<factory>, period=None, label=None, parent_island=None, metadata=<factory>)[source]

Bases: InvariantManifold

Discrete island chain obtained on a section of a flow or map.

This is the generic root for toroidal.IslandChain.

property O_points: List[SectionPoint][source]
property X_points: List[SectionPoint][source]
add_island(island)[source]
Return type:

None

diagnostics()[source]

Return a structured diagnostic / debug dict.

The default implementation returns a minimal dict with just the class name. Subclasses are encouraged to override and add domain-specific information.

Return type:

Dict[str, Any]

property intrinsic_dim: int[source]

Intrinsic dimension of the invariant manifold (None if unknown).

islands: List[Island][source]
label: str | None = None[source]
metadata: Dict[str, Any][source]
property n_islands: int[source]
parent_island: Island | None = None[source]
period: int | None = None[source]
section_cut(section=None)[source]

Return the intersection of this invariant with a Poincaré section.

Raises NotImplementedError by default. Subclasses that support sectioning should override (and ideally also derive from SectionCuttable).

Return type:

list

property section_label: str | None[source]
property section_value: float | None[source]
class pyna.topo.core.LinearStabilityData(jacobian, eigenvalues=None, metadata=<factory>)[source]

Bases: GeometricObject

Linearised stability payload for a periodic object or section point.

property classification: Stability[source]
diagnostics()[source]

Return a structured diagnostic / debug dict.

Return type:

Dict[str, Any]

eigenvalues: ndarray | None = None[source]
jacobian: ndarray[source]
metadata: Dict[str, Any][source]
property stability_index: float[source]
property trace: float[source]
class pyna.topo.core.Orbit(states, steps=None, coordinate_names=None, metadata=<factory>)[source]

Bases: GeometricObject

Finite sampled orbit of a discrete-time map.

property ambient_dim: int[source]

Dimension of the ambient phase space (None if unknown).

coordinate_names: Tuple[str, ...] | None = None[source]
diagnostics()[source]

Return a structured diagnostic / debug dict.

Return type:

Dict[str, Any]

property final: ndarray[source]

Final sampled map state.

metadata: Dict[str, Any][source]
property n_samples: int[source]
property period_guess: int | None[source]

Return the smallest sampled return to the initial state.

states: ndarray[source]
steps: ndarray | None = None[source]
class pyna.topo.core.PeriodicOrbit(points=<factory>, period=None, stability_data=None, representative_state=None, orbit_trace=None, metadata=<factory>)[source]

Bases: InvariantManifold

Periodic orbit of a discrete map in arbitrary finite dimension.

This is the generic root for toroidal.PeriodicOrbit.

property ambient_dim: int | None[source]

Dimension of the ambient phase space (None if unknown).

diagnostics()[source]

Return a structured diagnostic / debug dict.

The default implementation returns a minimal dict with just the class name. Subclasses are encouraged to override and add domain-specific information.

Return type:

Dict[str, Any]

property intrinsic_dim: int[source]

Intrinsic dimension of the invariant manifold (None if unknown).

metadata: Dict[str, Any][source]
orbit_trace: Orbit | None = None[source]
period: int | None = None[source]
points: List[SectionPoint][source]
representative_state: ndarray | None = None[source]
section_cut(section=None)[source]

Return the intersection of this invariant with a Poincaré section.

Raises NotImplementedError by default. Subclasses that support sectioning should override (and ideally also derive from SectionCuttable).

Return type:

PeriodicOrbit

property section_label: str | None[source]
property section_value: float | None[source]
stability_data: LinearStabilityData | None = None[source]
class pyna.topo.core.SectionPoint(state=None, section_value=None, section_label=None, stability_data=None, metadata=<factory>)[source]

Bases: InvariantManifold

A point on a section of a finite-dimensional dynamical system.

This is the generic root for toroidal.FixedPoint. The state field may be None when constructed by a subclass that fills it in __post_init__ (e.g. FixedPoint from R,Z).

property ambient_dim: int | None[source]

Dimension of the ambient phase space (None if unknown).

property coordinate_names: Tuple[str, ...] | None[source]
diagnostics()[source]

Return a structured diagnostic / debug dict.

The default implementation returns a minimal dict with just the class name. Subclasses are encouraged to override and add domain-specific information.

Return type:

Dict[str, Any]

metadata: Dict[str, Any][source]
section_label: str | None = None[source]
section_value: float | None = None[source]
stability_data: LinearStabilityData | None = None[source]
state: ndarray | None = None[source]
class pyna.topo.core.Stability(*values)[source]

Bases: Enum

ELLIPTIC = 1[source]
HYPERBOLIC = 2[source]
PARABOLIC = 3[source]
UNKNOWN = 4[source]
class pyna.topo.core.Trajectory(states, times, time_name='t', coordinate_names=None, metadata=<factory>)[source]

Bases: GeometricObject

Finite sampled trajectory of a continuous-time system.

property ambient_dim: int[source]

Dimension of the ambient phase space (None if unknown).

component(i)[source]
Return type:

ndarray

coordinate_names: Tuple[str, ...] | None = None[source]
diagnostics()[source]

Return a structured diagnostic / debug dict.

Return type:

Dict[str, Any]

property final: ndarray[source]

Final sampled state.

interpolate_at(t)[source]
Return type:

ndarray

metadata: Dict[str, Any][source]
property n_samples: int[source]
section_cut(section, *, tol=1e-10)[source]
Return type:

List[SectionPoint]

states: ndarray[source]
property t: ndarray[source]

Alias for times used by ODE/SDE solution objects.

time_name: str = 't'[source]
times: ndarray[source]
property y: ndarray[source]

Alias for states with shape (n_samples, ambient_dim).

class pyna.topo.core.Tube(O_cycle, X_cycles=<factory>, label=None, debug_info=<factory>)[source]

Bases: InvariantManifold

A resonance zone surrounding an elliptic periodic orbit of a continuous flow.

A Tube is the continuous-time analogue of an Island: it consists of the nested family of invariant tori around an elliptic cycle (O_cycle), bounded by hyperbolic cycles (X_cycles).

For MCF field lines, this is a magnetic island tube. For Hamiltonian flows, it is a resonance zone bounded by separatrices.

This is the generic root for toroidal.Tube.

Fields#

O_cycleCycle

The elliptic periodic orbit at the core.

X_cycleslist of Cycle

Hyperbolic periodic orbit(s) bounding the resonance zone.

label : str or None

O_cycle: Cycle[source]
X_cycles: List[Cycle][source]
debug_info: Dict[str, Any][source]
diagnostics()[source]

Return a structured diagnostic / debug dict.

The default implementation returns a minimal dict with just the class name. Subclasses are encouraged to override and add domain-specific information.

Return type:

Dict[str, Any]

property intrinsic_dim: int[source]

Intrinsic dimension of the invariant manifold (None if unknown).

property is_skeleton_complete: bool[source]
label: str | None = None[source]
section_cut(section)[source]

Cut this Tube with a section → IslandChain.

Return type:

IslandChain

class pyna.topo.core.TubeChain(tubes=<factory>, label=None, debug_info=<factory>)[source]

Bases: InvariantManifold

All Tubes sharing the same resonance in a continuous flow.

This is the generic root for toroidal.TubeChain.

debug_info: Dict[str, Any][source]
diagnostics()[source]

Return a structured diagnostic / debug dict.

The default implementation returns a minimal dict with just the class name. Subclasses are encouraged to override and add domain-specific information.

Return type:

Dict[str, Any]

property intrinsic_dim: int[source]

Intrinsic dimension of the invariant manifold (None if unknown).

label: str | None = None[source]
property n_tubes: int[source]
section_cut(section)[source]

Cut all Tubes with a section → merged IslandChain.

Return type:

IslandChain

summary()[source]
Return type:

str

tubes: List[Tube][source]

Sections#


Accumulateurs de Poincaré#


Îlots magnétiques#


Calcul de variétés#


Orbites periodiques / cycles#


Cartes classiques et diagnostics du chaos#