kinamax.integration.core¶
Time-integration orbit-finding, clustering, and result post-processing utilities.
- class kinamax.integration.core.Container[source]¶
Bases:
objectBase container exposing NumPy/Polars export helpers for array-like fields.
- kinamax.integration.core.namedtuple_repr(name, values)[source]¶
Render a compact Polars-backed repr for NamedTuple-style containers.
- Parameters:
name (str)
values (Mapping[str, Any])
- Return type:
str
- class kinamax.integration.core.AttractorFinderConfig(init_time=Array(0., dtype=float32), init_time_step=Array(0.001, dtype=float32), convergence_tol=Array(1.e-06, dtype=float32), target_frequency=50.0, subharmonic_factor=10.0)[source]¶
Bases:
NamedTupleConfiguration values driving the shooting-based attractor search.
Examples
>>> config = AttractorFinderConfig( ... target_frequency=50.0, ... init_time=0.0, ... init_time_step=1.0e-3, ... convergence_tol=1.0e-10, ... subharmonic_factor=10.0, ... ) >>> print(config) AttractorFinderConfig ... │ init_time ┆ scalar ┆ float64 ┆ 0.0... │ init_time_step ┆ scalar ┆ float64 ┆ 0.001... │ convergence_tol ┆ scalar ┆ float64 ┆ 1e-10... │ target_frequency ┆ scalar ┆ float64 ┆ 50.0... │ subharmonic_factor ┆ scalar ┆ float64 ┆ 10.0... ...
- Parameters:
init_time (Array)
init_time_step (Array)
convergence_tol (Array)
target_frequency (float)
subharmonic_factor (float)
- init_time: Array¶
Alias for field number 0
- init_time_step: Array¶
Alias for field number 1
- convergence_tol: Array¶
Alias for field number 2
- target_frequency: float¶
Alias for field number 3
- subharmonic_factor: float¶
Alias for field number 4
- kinamax.integration.core.convert_subharmonics_flags(subharmonics_flags, final_flags, targetted_subharmonics)[source]¶
Collapse per-target boolean flags into detected subharmonic orders.
For rows flagged as converged (final_flags == 1), the first active entry in subharmonics_flags selects the matching order from targetted_subharmonics. Rows without convergence keep value 0.
- Parameters:
subharmonics_flags (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
final_flags (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
targetted_subharmonics (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
- Return type:
ndarray[tuple[Any, …], dtype[int32]]
- class kinamax.integration.core.AttractorFinderSolution(attractors, detected_subharmonic, subharmonic_residual, minimum_residual, simulated_periods, simulated_time, final_flag, simulated_iterations, converged)[source]¶
Bases:
ContainerStructured output produced by AttractorFinder.find_attractors.
- Parameters:
attractors (Array)
detected_subharmonic (Array)
subharmonic_residual (Array)
minimum_residual (Array)
simulated_periods (Array)
simulated_time (Array)
final_flag (Array)
simulated_iterations (Array)
converged (Array)
- attractors: Array¶
- detected_subharmonic: Array¶
- subharmonic_residual: Array¶
- minimum_residual: Array¶
- simulated_periods: Array¶
- simulated_time: Array¶
- final_flag: Array¶
- simulated_iterations: Array¶
- converged: Array¶
- as_dict(state_vector_labels=None)[source]¶
Flatten attractor-finder outputs to a tabular NumPy dictionary.
- Parameters:
state_vector_labels (Sequence[str] | None)
- Return type:
dict[str, ndarray]
- class kinamax.integration.core.AttractorFinder[source]¶
Bases:
objectNamespace holding attractor-finder data layouts and static helpers.
- class Params(residuals_per_period=10, targetted_subharmonics=array([1, 3, 5]), max_periods=1000, controller=PIDController(rtol=1e-07, atol=1e-09), solver=Tsit5())[source]¶
Bases:
NamedTupleStatic settings for the shooting-based attractor search.
Examples
>>> import jax.numpy as jnp >>> from diffrax import PIDController, Tsit5 >>> finder = AttractorFinder.Params( ... residuals_per_period=20, ... targetted_subharmonics=jnp.array([1, 2, 3, 5]), ... max_periods=2000, ... controller=PIDController(rtol=1e-8, atol=1e-9), ... solver=Tsit5(), ... ) >>> print(finder) AttractorFinder.Params ... │ residuals_per_period ┆ scalar ┆ int64 ┆ 20... │ targetted_subharmonics ┆ (4,) ┆ int32 ┆ [1, 2, 3, 5]... │ max_periods ┆ scalar ┆ int64 ┆ 2000... │ controller ┆ scalar ┆ PIDController ┆ PIDController(rtol=1e-08, atol... │ solver ┆ scalar ┆ Tsit5 ┆ Tsit5()... ...
- Parameters:
residuals_per_period (int)
targetted_subharmonics (ndarray[tuple[Any, ...], dtype[int64]])
max_periods (int)
controller (PIDController)
solver (Tsit5)
- residuals_per_period: int¶
Alias for field number 0
- targetted_subharmonics: ndarray[tuple[Any, ...], dtype[int64]]¶
Alias for field number 1
- max_periods: int¶
Alias for field number 2
- controller: PIDController¶
Alias for field number 3
- solver: Tsit5¶
Alias for field number 4
- static get_max_subharmonic(finder)[source]¶
Return the largest targeted subharmonic order.
- Parameters:
finder (Params)
- Return type:
int
- static get_time_steps_number(finder)[source]¶
Return the number of saved samples for one shooting window.
- Parameters:
finder (Params)
- Return type:
int
- static get_max_shooting_iterations(finder)[source]¶
Return the maximum number of shooting windows to integrate.
- Parameters:
finder (Params)
- Return type:
int
- static calculate_subharmonic_atomic_residual(pos, args)[source]¶
Accumulate one term of the weighted shooting residual.
- Parameters:
pos (int)
args (tuple[Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray, int, Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray, Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray])
- Return type:
tuple[Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray, int, Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray, Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray]
- static calculate_subharmonic_residual(subharmonic, X, residuals_per_period, state_weights)[source]¶
Calculate the weighted shooting residual for one candidate subharmonic.
- Parameters:
subharmonic (int)
X (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
residuals_per_period (int)
state_weights (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
- Return type:
Array
- static integrate_and_check_convergence(finder, init_conditions, start_time, end_time, steps_number, problem_definition, problem, init_time_step, targetted_subharmonics, residuals_per_period)[source]¶
Integrate one shooting window and evaluate residuals for each target.
- Parameters:
finder (Params)
init_conditions (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
start_time (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
end_time (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
steps_number (int)
problem_definition (Any | None)
problem (Any)
init_time_step (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
targetted_subharmonics (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
residuals_per_period (int)
- Return type:
tuple[Array, Array, Array, Array]
- static find_attractors(finder, problem_definition_or_problem, problem_or_init_conditions, init_conditions_or_finder_config, finder_config=None)[source]¶
Integrate until convergence and then sample the attractor over one orbit.
This function accepts either the legacy call shape
find_attractors(finder, problem, init_conditions, finder_config)or the data-oriented shapefind_attractors(finder, problem_definition, problem, init_conditions, finder_config).Examples
>>> import jax.numpy as jnp >>> from diffrax import PIDController, Tsit5 >>> from kinamax.integration.models import H46Problem >>> problem = H46Problem.Params(fd=jnp.array(50.0), Ad=jnp.array(2.5)) >>> x0 = jnp.array([0.0, 0.0, 0.0]) >>> finder = AttractorFinder.Params( ... residuals_per_period=20, ... targetted_subharmonics=jnp.array([1, 2, 3, 5]), ... max_periods=2000, ... controller=PIDController(rtol=1e-8, atol=1e-9), ... solver=Tsit5(), ... ) >>> config = AttractorFinderConfig( ... target_frequency=50.0, ... init_time=0.0, ... init_time_step=1.0e-3, ... convergence_tol=1.0e-10, ... subharmonic_factor=10.0, ... ) >>> problem, config, x0, solution = AttractorFinder.find_attractors( ... finder, H46Problem, problem, x0, config ... )
- Parameters:
finder (Params)
problem_definition_or_problem (Any | P)
problem_or_init_conditions (P | Array)
init_conditions_or_finder_config (Array | AttractorFinderConfig)
finder_config (AttractorFinderConfig | None)
- Return type:
tuple[P, AttractorFinderConfig, Array, AttractorFinderSolution]
- kinamax.integration.core.post_process_attractor_finder_results(problem_class, problems, finder_configs, init_conditions, solutions, target_subharmonics, solution_state_labels)[source]¶
Flatten batched attractor-finder outputs to one balanced result table.
The returned table contains one row per retained attractor sample. For a detected subharmonic Hk, only the first k attractor rows are kept per simulation so different simulations can be compared with a consistent layout.
Examples
>>> import jax.numpy as jnp >>> from diffrax import PIDController, Tsit5 >>> from kinamax.integration.models import H46Problem >>> problem = H46Problem.Params(fd=jnp.array(50.0), Ad=jnp.array(2.5)) >>> x0 = jnp.array([0.0, 0.0, 0.0]) >>> finder = AttractorFinder.Params( ... residuals_per_period=20, ... targetted_subharmonics=jnp.array([1, 2, 3, 5]), ... max_periods=2000, ... controller=PIDController(rtol=1e-8, atol=1e-9), ... solver=Tsit5(), ... ) >>> config = AttractorFinderConfig( ... target_frequency=50.0, ... init_time=0.0, ... init_time_step=1.0e-3, ... convergence_tol=1.0e-10, ... subharmonic_factor=10.0, ... ) >>> problem, config, x0, solution = AttractorFinder.find_attractors( ... finder, H46Problem, problem, x0, config ... ) >>> table = post_process_attractor_finder_results( ... problem_class=H46Problem, ... problems=problem, ... finder_configs=config, ... init_conditions=x0, ... solutions=solution, ... target_subharmonics=jnp.array([1, 2, 3, 5]), ... solution_state_labels=["xa", "dotxa", "Eha"], ... )
- Parameters:
problem_class (Any)
problems (Any)
finder_configs (Any)
init_conditions (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
solutions (AttractorFinderSolution)
target_subharmonics (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
solution_state_labels (Sequence[str])
- Return type:
DataFrame
- kinamax.integration.core.cluster_points(points, weights, distance_threshold=0.01, method='dbscan')[source]¶
Cluster weighted points and return labels with centroids in original space.
- Parameters:
points (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
weights (Array | ndarray | bool | number | bool | int | float | complex | TypedNdArray)
distance_threshold (float)
method (str)
- Return type:
tuple[int, ndarray, ndarray]
- kinamax.integration.core.detect_orbits(problem_class, simulations, ode_params_labels, attractor_state_vec_labels, state_vec_labels, distance_threshold=0.01, clustering_method='dbscan')[source]¶
Cluster attractor samples per configuration and map them to orbit IDs.
Workflow:
Group rows by ODE parameters, detected subharmonic, and target frequency so each configuration is processed independently.
Cluster the recorded attractor points in the weighted state space to estimate unique attractors for the group.
Assign globally unique attractor labels and record which simulations share the same attractor tuple (one orbit).
Return tidy Polars DataFrames for attractors and the simulation->orbit map.
- Parameters:
problem_class (Any)
simulations (DataFrame)
ode_params_labels (Sequence[str])
attractor_state_vec_labels (Sequence[str])
state_vec_labels (Sequence[str])
distance_threshold (float)
clustering_method (str)
- Return type:
tuple[DataFrame, DataFrame]