GitHub

Built-in Dynamical Maps

Classic dynamical systems for testing, demonstration, and research with koopman-dmd.

Overview

The library includes several classic dynamical systems maps for testing, demonstration, and research. These maps serve as well-understood benchmark systems for validating DMD algorithms, exploring Koopman operator approximations, and studying the interplay between regular and chaotic dynamics.

All maps implement the MapFn trait in Rust. In Python and R, maps are selected by name string and passed to trajectory generation functions. Each map accepts configurable parameters that control the dynamical regime.

Standard Map (Chirikov)

The Chirikov standard map is a two-dimensional, area-preserving map that arises as a simplified model of the kicked rotor. It is one of the most widely studied systems in Hamiltonian dynamics and exhibits a rich mixture of regular and chaotic behavior depending on the perturbation strength.

y' = y + epsilon * sin(2 * pi * x)    (mod 1)
x' = x + y'    (mod 1)

Parameter: epsilon -- perturbation strength (default 0.12).

At small values of epsilon, the phase space is dominated by invariant curves (KAM tori) surrounding elliptic fixed points. As epsilon increases, these curves break up and chaotic regions grow, producing a characteristic pattern of islands of regularity embedded in a chaotic sea. This makes the standard map an ideal testbed for Koopman analysis methods that must distinguish between regular and chaotic dynamics.

Froeschle Map

The Froeschle map is a four-dimensional symplectic map that generalizes the standard map to coupled degrees of freedom. It consists of two coupled standard maps and is used to study Arnold diffusion and higher-dimensional Hamiltonian chaos.

Parameters:

When the coupling parameter epsilon3 is zero, the map reduces to two independent standard maps. Nonzero coupling introduces interactions between the two subsystems, enabling transport phenomena that are absent in two dimensions.

Extended Standard Map

The extended standard map augments the Chirikov standard map with an additional harmonic perturbation term. This extra degree of freedom provides finer control over the structure of phase space and is useful for studying how secondary resonances affect the breakdown of invariant tori.

Parameters:

Henon Map

The Henon map is a two-dimensional dissipative map that exhibits a well-known strange attractor. Unlike the area-preserving standard map, the Henon map contracts volumes in phase space, making it a prototype for studying chaotic attractors in low-dimensional systems.

x' = 1 - a * x^2 + y
y' = b * x

Parameters:

At the classic parameter values, the map produces a fractal strange attractor with a Hausdorff dimension of approximately 1.26. The Henon attractor is useful for testing DMD methods on systems with dissipative, chaotic dynamics.

Logistic Map

The logistic map is a one-dimensional map that, despite its simplicity, exhibits the full range of dynamical behavior from fixed points through period-doubling cascades to chaos.

x' = r * x * (1 - x)

Parameter: r -- growth rate (default 3.9, chaotic regime).

The map is bounded in the interval [0, 1] for values of r in [0, 4]. It undergoes a period-doubling route to chaos as r increases past approximately 3.57. The default value of 3.9 places the system deep in the chaotic regime, which is useful for testing Koopman decompositions on fully chaotic, low-dimensional data.

Generating Trajectories

The generate_trajectory function iterates a map from a given initial condition for a specified number of steps and returns a matrix of states. Each column of the returned matrix is a snapshot of the system state at a single time step.

use koopman_dmd::maps::{StandardMap, LogisticMap, generate_trajectory};

// Standard map with default epsilon = 0.12
let map = StandardMap::new(0.12);
let x0 = vec![0.1, 0.2];
let traj = generate_trajectory(&x0, &map, 1000);
println!("Trajectory shape: {:?}", traj.dim()); // (2, 1000)

// Logistic map in the chaotic regime
let logistic = LogisticMap::new(3.9);
let x0 = vec![0.4];
let traj = generate_trajectory(&x0, &logistic, 500);
println!("Trajectory shape: {:?}", traj.dim()); // (1, 500)
import koopman_dmd as kdmd
import numpy as np

# Standard map with default epsilon = 0.12
traj = kdmd.generate_trajectory(
    initial_condition=[0.1, 0.2],
    map_name="standard",
    n_steps=1000,
    epsilon=0.12,
)
print("Trajectory shape:", traj.shape)  # (2, 1000)

# Logistic map in the chaotic regime
traj = kdmd.generate_trajectory(
    initial_condition=[0.4],
    map_name="logistic",
    n_steps=500,
    r=3.9,
)
print("Trajectory shape:", traj.shape)  # (1, 500)
library(koopmandmd)

# Standard map with default epsilon = 0.12
traj <- generate_trajectory(
  initial_condition = c(0.1, 0.2),
  map_name = "standard",
  n_steps = 1000,
  epsilon = 0.12
)
print(dim(traj))  # 2 x 1000

# Logistic map in the chaotic regime
traj <- generate_trajectory(
  initial_condition = 0.4,
  map_name = "logistic",
  n_steps = 500,
  r = 3.9
)
print(dim(traj))  # 1 x 500

Phase Grid

The generate_phase_grid function creates a uniform grid of initial conditions for systematic phase space exploration. This is particularly useful for constructing phase portraits, mesochronic plots, or computing Koopman eigenfunctions over a region of phase space.

This function is available in the Rust API only.

use koopman_dmd::maps::generate_phase_grid;

// Create a 100x100 grid of initial conditions on [0, 1) x [0, 1)
let grid = generate_phase_grid(100, 100);
println!("Grid shape: {:?}", grid.dim()); // (2, 10000)

// Each column is an (x, y) initial condition.
// Use with generate_trajectory to build a phase portrait.

Custom Maps

In Rust, you can define custom dynamical maps using the ClosureMap wrapper. Any closure that takes a state slice and returns a new state vector can be wrapped into a type that implements the MapFn trait, making it compatible with generate_trajectory and all analysis functions.

This feature is available in the Rust API only.

use koopman_dmd::maps::{ClosureMap, generate_trajectory};

// Define a custom 2D rotation map
let theta = 0.1 * std::f64::consts::PI;
let rotation = ClosureMap::new(2, move |x: &[f64]| {
    vec![
        x[0] * theta.cos() - x[1] * theta.sin(),
        x[0] * theta.sin() + x[1] * theta.cos(),
    ]
});

let traj = generate_trajectory(&vec![1.0, 0.0], &rotation, 200);
println!("Trajectory shape: {:?}", traj.dim()); // (2, 200)

Map Properties

The following table summarizes the built-in maps, their dimensionality, dynamical type, configurable parameters, and typical behavior.

Map Dimension Type Parameters Typical Behavior
Standard (Chirikov) 2 Area-preserving epsilon Mixed regular/chaotic; islands in a chaotic sea
Froeschle 4 Symplectic (area-preserving) epsilon1, epsilon2, epsilon3 Higher-dimensional Hamiltonian chaos; Arnold diffusion
Extended Standard 2 Area-preserving epsilon, alpha Secondary resonances; controlled torus breakdown
Henon 2 Dissipative a, b Strange attractor; fractal structure
Logistic 1 Dissipative r Period-doubling cascade to chaos