Source code for hiten.algorithms.poincare.centermanifold.base

"""
Center manifold Poincare map interface for the CR3BP.

This module provides the main user-facing interface for computing and
analyzing Poincare maps restricted to center manifolds of collinear
libration points in the Circular Restricted Three-Body Problem (CR3BP).

The :class:`~hiten.algorithms.poincare.centermanifold.base.CenterManifoldMap` 
class extends the base return map functionality with center manifold-specific seeding 
strategies and visualization capabilities.
"""

from __future__ import annotations

from typing import Generic, Literal, Optional

from hiten.algorithms.poincare.centermanifold.backend import \
    _CenterManifoldBackend
from hiten.algorithms.poincare.centermanifold.config import \
    _CenterManifoldMapConfig
from hiten.algorithms.poincare.centermanifold.engine import \
    _CenterManifoldEngine
from hiten.algorithms.poincare.centermanifold.interfaces import \
    _CenterManifoldInterface
from hiten.algorithms.poincare.centermanifold.seeding import \
    _CenterManifoldSeedingBase
from hiten.algorithms.poincare.centermanifold.strategies import _make_strategy
from hiten.algorithms.poincare.centermanifold.types import \
    CenterManifoldMapResults
from hiten.algorithms.types.core import (ConfigT, DomainT, InterfaceT, ResultT,
                                         _HitenBaseFacade)


[docs] class CenterManifoldMapPipeline(_HitenBaseFacade, Generic[DomainT, InterfaceT, ConfigT, ResultT]): """Poincare return map restricted to the center manifold of a collinear libration point. This class provides the main interface for computing and analyzing Poincare maps on center manifolds in the CR3BP. It supports various seeding strategies and provides visualization capabilities for understanding the local dynamics. Notes ----- State vectors are ordered as [q1, q2, q3, p1, p2, p3] where q1=0 for center manifold trajectories. All coordinates are in nondimensional units with the primary-secondary separation as the length unit. Examples -------- >>> from hiten.system.center import CenterManifold >>> from hiten.algorithms.poincare.centermanifold.base import CenterManifoldMap >>> >>> # Create center manifold for L1 point >>> cm = CenterManifold("L1") >>> >>> # Create Poincare map at specific energy >>> energy = -1.5 >>> poincare_map = CenterManifoldMap(cm, energy) >>> >>> # Compute the map >>> poincare_map.compute() >>> >>> # Plot the results >>> poincare_map.plot() """ def __init__(self, config: _CenterManifoldMapConfig, engine: _CenterManifoldEngine, interface: _CenterManifoldInterface = None, backend: _CenterManifoldBackend = None) -> None: super().__init__(config, engine, interface, backend)
[docs] @classmethod def with_default_engine( cls, config: _CenterManifoldMapConfig, interface: Optional[_CenterManifoldInterface] = None,\ backend: Optional[_CenterManifoldBackend] = None, ) -> "CenterManifoldMapPipeline": """Construct a map with a default-wired engine injected. This mirrors the DI-friendly facades (e.g., ConnectionPipeline) by creating a default engine using the current configuration and injecting it. The engine is wired for the default section coordinate in the config. Parameters ---------- config : :class:`~hiten.algorithms.poincare.centermanifold.config._CenterManifoldMapConfig` Configuration object for the center manifold map. interface : :class:`~hiten.algorithms.poincare.centermanifold.interfaces._CenterManifoldInterface`, optional Interface object for the center manifold map. If None, uses the default _CenterManifoldInterface. backend : :class:`~hiten.algorithms.poincare.centermanifold.backend._CenterManifoldBackend`, optional Backend instance for the center manifold map. If None, uses the default _CenterManifoldBackend. Returns ------- :class:`~hiten.algorithms.poincare.centermanifold.base.CenterManifoldMapPipeline` A center manifold map facade instance with a default engine injected. """ from hiten.algorithms.poincare.centermanifold.backend import \ _CenterManifoldBackend from hiten.algorithms.poincare.centermanifold.engine import \ _CenterManifoldEngine from hiten.algorithms.poincare.centermanifold.interfaces import \ _CenterManifoldInterface backend = backend or _CenterManifoldBackend() map_intf = interface or _CenterManifoldInterface() strategy = cls._build_strategy(config) engine = _CenterManifoldEngine(backend=backend, seed_strategy=strategy, map_config=config, interface=map_intf) return cls(config, engine, map_intf, backend)
[docs] def generate( self, domain_obj: DomainT, override: bool = False, *, section_coord: str | None = None, dt: float | None = None, n_iter: int | None = None, n_workers: int | None = None, method: Literal["fixed", "adaptive", "symplectic"] | None = None, order: int | None = None, c_omega_heuristic: float | None = None, ) -> CenterManifoldMapResults: """Compute the section, supporting runtime overrides without mutating config. If no overrides are provided, this defers to the cached, default setup and persists the result. If any overrides are provided, a temporary engine is assembled for this call and the result is returned without polluting the persistent cache. In all cases, this method returns the 2-D points of the section. """ kwargs = { "section_coord": section_coord, "dt": dt, "n_iter": n_iter, "n_workers": n_workers, "method": method, "order": order, "c_omega_heuristic": c_omega_heuristic, } problem = self._create_problem(domain_obj=domain_obj, override=override, **kwargs) engine = self._get_engine() self._results = engine.solve(problem) return self._results
@staticmethod def _build_strategy(config: _CenterManifoldMapConfig) -> _CenterManifoldSeedingBase: strategy_kwargs: dict[str, object] = {} if config.seed_strategy == "single": strategy_kwargs["seed_axis"] = config.seed_axis return _make_strategy(config, **strategy_kwargs)