pynamicalsys 1.5.2__tar.gz → 1.5.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/.gitignore +1 -0
- pynamicalsys-1.5.4/CHANGELOG.md +384 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/PKG-INFO +1 -1
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/__init__.py +2 -1
- pynamicalsys-1.5.4/src/pynamicalsys/__version__.py +24 -0
- pynamicalsys-1.5.4/src/pynamicalsys/common/__init__.py +16 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/common/basin_analysis.py +2 -2
- pynamicalsys-1.5.4/src/pynamicalsys/common/clv.py +97 -0
- pynamicalsys-1.5.4/src/pynamicalsys/common/differentiation.py +93 -0
- pynamicalsys-1.5.4/src/pynamicalsys/common/fitting.py +50 -0
- pynamicalsys-1.5.2/src/pynamicalsys/common/time_series_metrics.py → pynamicalsys-1.5.4/src/pynamicalsys/common/hurst.py +19 -2
- pynamicalsys-1.5.4/src/pynamicalsys/common/linalg.py +154 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/common/recurrence_quantification_analysis.py +1 -1
- pynamicalsys-1.5.4/src/pynamicalsys/common/types.py +87 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/common/validators.py +30 -29
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/__init__.py +16 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/adaptive_step.py +214 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/basins.py +150 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/clv.py +460 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/fixed_step.py +165 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/gali.py +215 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/hurst.py +164 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/ldi.py +178 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/lyapunov.py +310 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/maxima_map.py +229 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/continuous_time/models.py +1 -46
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/poincare.py +224 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/rte.py +213 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/sali.py +170 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/step.py +172 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/step_methods.py +234 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/stroboscopic.py +193 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/trajectory.py +196 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/validators.py +79 -0
- pynamicalsys-1.5.4/src/pynamicalsys/continuous_time/variational.py +109 -0
- pynamicalsys-1.5.4/src/pynamicalsys/core/__init__.py +16 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/core/basin_metrics.py +1 -1
- pynamicalsys-1.5.4/src/pynamicalsys/core/continuous_dynamical_systems.py +2276 -0
- pynamicalsys-1.5.4/src/pynamicalsys/core/discrete_dynamical_systems.py +3932 -0
- pynamicalsys-1.5.4/src/pynamicalsys/core/hamiltonian_systems.py +1847 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/core/plot_styler.py +1 -1
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/core/time_series_metrics.py +6 -5
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/__init__.py +16 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/averages.py +81 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/bifurcation.py +134 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/birkhoff.py +120 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/clv.py +457 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/escape.py +235 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/gali.py +198 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/hurst.py +167 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/ldi.py +142 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/lyapunov.py +637 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/manifolds.py +173 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/discrete_time/models.py +1 -1
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/periodic_orbits.py +568 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/rotation.py +76 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/rte.py +203 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/sali.py +141 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/stability.py +198 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/symmetry.py +73 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/trajectory.py +187 -0
- pynamicalsys-1.5.4/src/pynamicalsys/discrete_time/transport.py +366 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/discrete_time/validators.py +12 -13
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/clv.py +452 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/coefficients.py +22 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/fixed_step.py +118 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/gali.py +167 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/hurst.py +99 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/ldi.py +136 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/lyapunov.py +259 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/poincare.py +291 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/rte.py +155 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/sali.py +135 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/tangent.py +249 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/trajectory.py +141 -0
- pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems/validators.py +142 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys.egg-info/PKG-INFO +1 -1
- pynamicalsys-1.5.4/src/pynamicalsys.egg-info/SOURCES.txt +88 -0
- pynamicalsys-1.5.2/CHANGELOG.md +0 -200
- pynamicalsys-1.5.2/src/pynamicalsys/__version__.py +0 -34
- pynamicalsys-1.5.2/src/pynamicalsys/common/utils.py +0 -412
- pynamicalsys-1.5.2/src/pynamicalsys/continuous_time/__init__.py +0 -16
- pynamicalsys-1.5.2/src/pynamicalsys/continuous_time/chaotic_indicators.py +0 -1127
- pynamicalsys-1.5.2/src/pynamicalsys/continuous_time/numerical_integrators.py +0 -337
- pynamicalsys-1.5.2/src/pynamicalsys/continuous_time/trajectory_analysis.py +0 -646
- pynamicalsys-1.5.2/src/pynamicalsys/continuous_time/validators.py +0 -42
- pynamicalsys-1.5.2/src/pynamicalsys/core/__init__.py +0 -16
- pynamicalsys-1.5.2/src/pynamicalsys/core/continuous_dynamical_systems.py +0 -2277
- pynamicalsys-1.5.2/src/pynamicalsys/core/discrete_dynamical_systems.py +0 -4186
- pynamicalsys-1.5.2/src/pynamicalsys/core/hamiltonian_systems.py +0 -1674
- pynamicalsys-1.5.2/src/pynamicalsys/discrete_time/__init__.py +0 -16
- pynamicalsys-1.5.2/src/pynamicalsys/discrete_time/dynamical_indicators.py +0 -1692
- pynamicalsys-1.5.2/src/pynamicalsys/discrete_time/trajectory_analysis.py +0 -1460
- pynamicalsys-1.5.2/src/pynamicalsys/discrete_time/transport.py +0 -463
- pynamicalsys-1.5.2/src/pynamicalsys/hamiltonian_systems/__init__.py +0 -16
- pynamicalsys-1.5.2/src/pynamicalsys/hamiltonian_systems/chaotic_indicators.py +0 -867
- pynamicalsys-1.5.2/src/pynamicalsys/hamiltonian_systems/numerical_integrators.py +0 -320
- pynamicalsys-1.5.2/src/pynamicalsys/hamiltonian_systems/trajectory_analysis.py +0 -390
- pynamicalsys-1.5.2/src/pynamicalsys/hamiltonian_systems/validators.py +0 -114
- pynamicalsys-1.5.2/src/pynamicalsys.egg-info/SOURCES.txt +0 -46
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/CITATION.cff +0 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/CONTRIBUTING.md +0 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/LICENSE +0 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/MANIFEST.in +0 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/README.md +0 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/pyproject.toml +0 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/setup.cfg +0 -0
- {pynamicalsys-1.5.2/src/pynamicalsys/common → pynamicalsys-1.5.4/src/pynamicalsys/hamiltonian_systems}/__init__.py +0 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys/hamiltonian_systems/models.py +0 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys.egg-info/dependency_links.txt +0 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys.egg-info/requires.txt +0 -0
- {pynamicalsys-1.5.2 → pynamicalsys-1.5.4}/src/pynamicalsys.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [v1.5.4] - 2026-05-28
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `DiscreteDynamicalSystem` class:
|
|
13
|
+
- Added `return_last_state` to the `SALI`, `LDI`, and `GALI` methods.
|
|
14
|
+
- Added `method` option to `GALI` with the following implementations:
|
|
15
|
+
- `"DET"`: computes `GALI_k` from the Gram matrix determinant.
|
|
16
|
+
- `"QR"`: computes `GALI_k` from the diagonal of the triangular factor returned by the internal QR routine.
|
|
17
|
+
- `"QR_HH"`: computes `GALI_k` from the diagonal of the triangular factor returned by `numpy.linalg.qr`.
|
|
18
|
+
|
|
19
|
+
- `ContinuousDynamicalSystem` class:
|
|
20
|
+
- Added `method` option to `GALI` with the following implementations:
|
|
21
|
+
- `"DET"`: computes `GALI_k` from the Gram matrix determinant.
|
|
22
|
+
- `"QR"`: computes `GALI_k` from the diagonal of the triangular factor returned by the internal QR routine.
|
|
23
|
+
- `"QR_HH"`: computes `GALI_k` from the diagonal of the triangular factor returned by `numpy.linalg.qr`.
|
|
24
|
+
|
|
25
|
+
- `HamiltonianSystem` class:
|
|
26
|
+
- Added `method` option to `GALI` with the following implementations:
|
|
27
|
+
- `"DET"`: computes `GALI_k` from the Gram matrix determinant.
|
|
28
|
+
- `"QR"`: computes `GALI_k` from the diagonal of the triangular factor returned by the internal QR routine.
|
|
29
|
+
- `"QR_HH"`: computes `GALI_k` from the diagonal of the triangular factor returned by `numpy.linalg.qr`.
|
|
30
|
+
|
|
31
|
+
- `discrete_time` module:
|
|
32
|
+
- Added dedicated low-level modules:
|
|
33
|
+
- `trajectory.py`
|
|
34
|
+
- `bifurcation.py`
|
|
35
|
+
- `birkhoff.py`
|
|
36
|
+
- `hurst.py`
|
|
37
|
+
- `rte.py`
|
|
38
|
+
- `periodic_orbits.py`
|
|
39
|
+
- `stability.py`
|
|
40
|
+
- `manifolds.py`
|
|
41
|
+
- `rotation.py`
|
|
42
|
+
- `escape.py`
|
|
43
|
+
- `transport.py`
|
|
44
|
+
- `averages.py`
|
|
45
|
+
- `symmetry.py`
|
|
46
|
+
- `sali.py`
|
|
47
|
+
- `ldi.py`
|
|
48
|
+
- `gali.py`
|
|
49
|
+
- `clv.py`
|
|
50
|
+
|
|
51
|
+
- `continuous_time` module:
|
|
52
|
+
- Added dedicated low-level modules:
|
|
53
|
+
- `fixed_step.py`
|
|
54
|
+
- `adaptive_step.py`
|
|
55
|
+
- `step_methods.py`
|
|
56
|
+
- `variational.py`
|
|
57
|
+
- `step.py`
|
|
58
|
+
- `trajectory.py`
|
|
59
|
+
- `poincare.py`
|
|
60
|
+
- `stroboscopic.py`
|
|
61
|
+
- `maxima_map.py`
|
|
62
|
+
- `basins.py`
|
|
63
|
+
- `lyapunov.py`
|
|
64
|
+
- `sali.py`
|
|
65
|
+
- `ldi.py`
|
|
66
|
+
- `gali.py`
|
|
67
|
+
- `clv.py`
|
|
68
|
+
- `rte.py`
|
|
69
|
+
- `hurst.py`
|
|
70
|
+
|
|
71
|
+
- `hamiltonian_systems` module:
|
|
72
|
+
- Added dedicated low-level modules:
|
|
73
|
+
- `coefficients.py`
|
|
74
|
+
- `fixed_step.py`
|
|
75
|
+
- `tangent.py`
|
|
76
|
+
- `trajectory.py`
|
|
77
|
+
- `poincare.py`
|
|
78
|
+
- `lyapunov.py`
|
|
79
|
+
- `sali.py`
|
|
80
|
+
- `ldi.py`
|
|
81
|
+
- `gali.py`
|
|
82
|
+
- `clv.py`
|
|
83
|
+
- `rte.py`
|
|
84
|
+
- `hurst.py`
|
|
85
|
+
|
|
86
|
+
- `common.types`:
|
|
87
|
+
- Added `observable_t` type alias for weighted-Birkhoff observable functions.
|
|
88
|
+
- Added `flow_t` and `flow_jacobian_t` type aliases for continuous-time vector fields and their Jacobians.
|
|
89
|
+
- Added `grad_t` and `hess_t` type aliases for Hamiltonian gradients and Hessians.
|
|
90
|
+
- Added `symplectic_step_t` and `symplectic_tangent_step_t` type aliases for Hamiltonian fixed-step integrators and their tangent-map variants.
|
|
91
|
+
|
|
92
|
+
### Changed
|
|
93
|
+
|
|
94
|
+
- Refactored low-level discrete-time analysis routines by splitting the old monolithic modules into dedicated files for improved project organization, readability, and maintainability.
|
|
95
|
+
- Refactored low-level continuous-time analysis routines by splitting the old monolithic modules into dedicated files for improved project organization, readability, and maintainability.
|
|
96
|
+
- Refactored low-level Hamiltonian-system analysis and integration routines by splitting the old monolithic modules into dedicated files for improved project organization, readability, and maintainability.
|
|
97
|
+
|
|
98
|
+
- `DiscreteDynamicalSystem` class:
|
|
99
|
+
- Updated wrappers across the discrete-time analysis API with improved type annotations, return annotations, argument validation, and docstrings.
|
|
100
|
+
- Standardized handling of `sample_times` in wrappers that support sampled outputs by explicitly validating user input and constructing internal sampling arrays only when needed.
|
|
101
|
+
- Updated `dig` observable validation so the observable must be callable and return a 1D NumPy array with one value per input state.
|
|
102
|
+
- Improved validation and normalization of wrapper inputs for periodic-orbit, manifold, transport, escape, Hurst, and recurrence diagnostics.
|
|
103
|
+
- The Lyapunov exponent API now exposes the analytical QR procedure (after Eckmann-Ruelle) explicitly through the `method` argument:
|
|
104
|
+
- `method="ER"` now selects the analytical QR-based approach (available only for 2D systems).
|
|
105
|
+
- `method="QR"` now consistently uses the modifed Gram-Schmidt QR decomposition, independent of system dimension.
|
|
106
|
+
- `method=QR_HH` uses Householder QR decomposition via `np.linalg.qr`.
|
|
107
|
+
- The previous implicit behavior where method="QR" automatically switched to the Eckmann–Ruelle algorithm for 2D systems has been removed. Existing code relying on this optimization should now explicitly set `ds.lyapunov(..., method="ER")`.
|
|
108
|
+
|
|
109
|
+
- `ContinuousDynamicalSystem` class:
|
|
110
|
+
- Reorganized imports and internal plumbing to use the new continuous-time module layout.
|
|
111
|
+
- Updated constructor, integrator configuration, and wrapper methods with improved type annotations, return annotations, argument validation, and docstrings.
|
|
112
|
+
- Standardized validation of continuous-time arguments by using dedicated time validation helpers and more explicit normalization of parameters and wrapper inputs.
|
|
113
|
+
- Updated trajectory-related wrappers to reflect adaptive-step behavior more faithfully when ensemble trajectories do not all share the same stored length.
|
|
114
|
+
- Updated Lyapunov-related return annotations and docstrings so the scalar `num_exponents=1` case is documented and handled consistently.
|
|
115
|
+
|
|
116
|
+
- `HamiltonianSystem` class:
|
|
117
|
+
- Reorganized imports and internal plumbing to use the new Hamiltonian-system module layout.
|
|
118
|
+
- Updated constructor, integrator configuration, and wrapper methods with improved type annotations, return annotations, argument validation, and docstrings.
|
|
119
|
+
- Standardized validation of Hamiltonian wrapper inputs for coordinates, momenta, parameters, section arguments, CLV configuration, and time-like arguments.
|
|
120
|
+
- Updated Lyapunov-, CLV-, SALI-, LDI-, GALI-, RTE-, Hurst-, trajectory-, and Poincaré-related wrappers to use the refactored low-level modules and more explicit scalar/array return semantics.
|
|
121
|
+
|
|
122
|
+
- `continuous_time.validators`:
|
|
123
|
+
- Refactored `validate_times()` to return validated `np.float64` values and to enforce stricter type and range checks for continuous-time arguments.
|
|
124
|
+
|
|
125
|
+
- `hamiltonian_systems.validators`:
|
|
126
|
+
- Refactored `validate_times()` and `validate_initial_conditions()` with stricter typing, shape checks, and `np.float64` normalization for Hamiltonian-system inputs.
|
|
127
|
+
|
|
128
|
+
- `common.validators`:
|
|
129
|
+
- Refactored `validate_clv_subspaces()` and `validate_clv_pairs()` to validate indices against `num_clvs` instead of the full system dimension.
|
|
130
|
+
- Improved normalization of single subspace and single pair inputs into canonical tuple-based representations.
|
|
131
|
+
|
|
132
|
+
- `common.utils`:
|
|
133
|
+
- Refactored the internal QR routine to a simpler reduced modified Gram-Schmidt implementation with manual inner products for better Numba compatibility and lower overhead.
|
|
134
|
+
- Simplified `householder_qr()` implementation.
|
|
135
|
+
- Temporarily kept shared CLV helper routines in `utils.py` because they are still used by the continuous and Hamiltonian classes during the refactor.
|
|
136
|
+
- Added typed `qr_truncate()` helper documentation and return annotations for CLV-related truncation logic.
|
|
137
|
+
|
|
138
|
+
### Fixed
|
|
139
|
+
|
|
140
|
+
- `DiscreteDynamicalSystem` class:
|
|
141
|
+
- Fixed `SALI`, `LDI`, and `GALI` wrappers so that scalar outputs are returned consistently when `return_history=False`, while preserving the final state when `return_last_state=True`.
|
|
142
|
+
- Fixed `GALI` computation by using stable QR-based volume evaluation.
|
|
143
|
+
- Fixed `CLV_angles` validation so subspace and pair indices are checked against the number of computed CLVs rather than the ambient phase-space dimension.
|
|
144
|
+
- Removed a stray debug `print(iter_time)` from `manifold()`.
|
|
145
|
+
- Added validation to prevent the use of `method="ER"` for systems with dimension greater than 2, raising a clear error instead of silently falling back to another implementation.
|
|
146
|
+
|
|
147
|
+
- `ContinuousDynamicalSystem` class:
|
|
148
|
+
- Fixed wrapper regressions introduced during the continuous-time refactor in trajectory, reduced-map, Lyapunov, CLV, SALI, LDI, GALI, RTE, and Hurst-related methods.
|
|
149
|
+
- Fixed `trajectory()` return handling for ensembles evolved with adaptive integrators, where different initial conditions may produce trajectories with different numbers of stored time steps.
|
|
150
|
+
- Fixed `lyapunov()` so `method="QR_HH"` works correctly with the refactored low-level implementation.
|
|
151
|
+
- Fixed `lyapunov()` so `num_exponents=1` returns a scalar instead of a length-1 array when `return_history=False`.
|
|
152
|
+
- Fixed `GALI()` wrapper so the selected low-level computation method is validated and passed through correctly.
|
|
153
|
+
|
|
154
|
+
- `HamiltonianSystem` class:
|
|
155
|
+
- Fixed wrapper validation bugs in trajectory, Poincaré-section, Lyapunov, CLV, CLV-angle, SALI, LDI, GALI, RTE, and Hurst-related methods introduced during the Hamiltonian refactor.
|
|
156
|
+
- Fixed wrapper shape checks so coordinate and momentum arrays are validated by full shape compatibility rather than only by matching dimensionality.
|
|
157
|
+
- Fixed `lyapunov()` so `num_exponents=1` returns a scalar instead of a length-1 array when `return_history=False`.
|
|
158
|
+
- Fixed `GALI()` wrapper so the selected low-level computation method is validated and passed through correctly.
|
|
159
|
+
- Fixed section-index validation in Hamiltonian reduced-map wrappers so section coordinates are checked against the number of degrees of freedom rather than the full phase-space dimension where appropriate.
|
|
160
|
+
|
|
161
|
+
- `discrete_time` module:
|
|
162
|
+
- Fixed low-level `SALI`, `LDI`, and `GALI` implementations to return both the computed result and the final state consistently.
|
|
163
|
+
- Fixed history allocation and sampling logic in low-level `SALI`, `LDI`, and `GALI` implementations for `return_history=True`.
|
|
164
|
+
- Fixed the weighted-Birkhoff `dig` implementation to live in its own dedicated module while preserving wrapper behavior.
|
|
165
|
+
- Fixed dtype consistency in sampled transport routines to avoid Numba typing errors from mixing `int32` and `int64` sampling arrays.
|
|
166
|
+
|
|
167
|
+
- `continuous_time` module:
|
|
168
|
+
- Fixed QR-related low-level Lyapunov and GALI computations to handle Householder-based QR consistently under Numba.
|
|
169
|
+
- Fixed array contiguity issues in low-level QR-based continuous-time routines to avoid reshape/type failures after `numpy.linalg.qr`.
|
|
170
|
+
|
|
171
|
+
- `hamiltonian_systems` module:
|
|
172
|
+
- Fixed low-level Lyapunov and GALI computations to support both internal QR and Householder-based QR through method dispatch instead of passing unsupported callable QR objects into Numba-compiled routines.
|
|
173
|
+
- Fixed low-level trajectory and reduced-map helpers with clearer typing, stricter validation, and dedicated Poincaré-section extraction from stored trajectories.
|
|
174
|
+
- Fixed Hamiltonian recurrence-time-entropy returns by replacing dynamically assembled list-based returns with explicit tuple branches compatible with static typing.
|
|
175
|
+
|
|
176
|
+
- `common.validators`:
|
|
177
|
+
- Fixed `validate_positive()` so zero is rejected correctly.
|
|
178
|
+
|
|
179
|
+
[v1.5.4]: https://github.com/mrolims/pynamicalsys/compare/v1.5.3...v1.5.4
|
|
180
|
+
|
|
181
|
+
## [v1.5.3] - 2026-04-08
|
|
182
|
+
|
|
183
|
+
### Fixed
|
|
184
|
+
|
|
185
|
+
- Incorrect tangent drift update in symplectic (Verlet/Yoshida) integrators (used δq instead of δp in δq update)
|
|
186
|
+
- QR re-orthonormalization scheduling in Lyapunov spectrum (`(i + 1) % qr_interval`)
|
|
187
|
+
- History allocation using `round` instead of integer division
|
|
188
|
+
- Incorrect normalization of history array (time column was being scaled)
|
|
189
|
+
|
|
190
|
+
[v1.5.3]: https://github.com/mrolims/pynamicalsys/compare/v1.5.2...v1.5.3
|
|
191
|
+
|
|
192
|
+
## [v1.5.2] - 2026-03-23
|
|
193
|
+
|
|
194
|
+
### Fixed
|
|
195
|
+
|
|
196
|
+
- `DiscreteDynamicalSystem` class:
|
|
197
|
+
- Fixed parameter handling in `DiscreteDynamicalSystem.bifurcation_diagram()` when the system has no stored default parameters:
|
|
198
|
+
- user-provided parameters are now validated and the scanned parameter is inserted at `param_index`;
|
|
199
|
+
- if no parameters are provided, a default parameter array is initialized so the scanned parameter can be assigned correctly.
|
|
200
|
+
|
|
201
|
+
### Changed
|
|
202
|
+
|
|
203
|
+
- Minor formatting cleanup in `logistic_map()`.
|
|
204
|
+
|
|
205
|
+
[v1.5.2]: https://github.com/mrolims/pynamicalsys/compare/v1.5.1...v1.5.2
|
|
206
|
+
|
|
207
|
+
## [v1.5.1] - 2026-03-16
|
|
208
|
+
|
|
209
|
+
### Added
|
|
210
|
+
|
|
211
|
+
- Support for fixed recurrence rate threshold selection via `fixed_rr=True`. When enabled, the recurrence threshold is automatically chosen such that the recurrence matrix achieves the desired recurrence rate (`threshold` interpreted as the target RR).
|
|
212
|
+
|
|
213
|
+
- Support for callable distance metrics for recurrence matrix computation and recurrence-rate threshold estimation. Custom metrics must have signature `metric(x, y) -> float` and must be Numba-compatible (decorated with `@numba.njit`).
|
|
214
|
+
|
|
215
|
+
- New `return_eps` option in `TimeSeriesMetrics.recurrence_matrix()` to return the threshold value used to construct the recurrence matrix.
|
|
216
|
+
|
|
217
|
+
### Modifed
|
|
218
|
+
|
|
219
|
+
- Internal recurrence matrix computation has been refactored for improved performance and consistency between built-in metrics (supremum, euclidean, manhattan) and callable metrics.
|
|
220
|
+
|
|
221
|
+
- Threshold selection is now centralized in a new `calculate_threshold()` function, which handles
|
|
222
|
+
- direct thresholds.
|
|
223
|
+
- standard-deviation–scaled thresholds (`threshold_mode="std"`).
|
|
224
|
+
- fixed recurrence rate thresholds (`threshold_mode="rr"`).
|
|
225
|
+
|
|
226
|
+
[v1.5.1]: https://github.com/mrolims/pynamicalsys/compare/v1.5.0...v1.5.1
|
|
227
|
+
|
|
228
|
+
## [v1.5.0] - 2026-01-07
|
|
229
|
+
|
|
230
|
+
### Added
|
|
231
|
+
|
|
232
|
+
- Added two new methods, `set_parameters` and `get_parameters`, to each of the three main classes to improve parameter management. Parameters can now be set once via `set_parameters` and stored internally, allowing subsequent method calls to use the stored values without requiring parameters to be passed explicitly each time. Existing workflows remain fully backward compatible: methods that accept parameters directly continue to work as before.
|
|
233
|
+
|
|
234
|
+
- Added **Covariant Lyapunov Vector (CLV) angle diagnostics** to all three core system classes:
|
|
235
|
+
- The new methods `CLV` and `CLV_angles` allow computation of the **CLVs**, **angles between arbitrary CLV subspaces** and **pairwise CLV angles**, with full user control over:
|
|
236
|
+
- which subspaces are compared,
|
|
237
|
+
- which CLV pairs are measured.
|
|
238
|
+
- Support for **Poincaré-section–restricted CLV angles** in Hamiltonian systems, enabling angle analysis directly on the section.
|
|
239
|
+
- Angle diagnostics are based on **minimum principal angles between covariant subspaces**, providing a geometrically meaningful measure of hyperbolicity and near-tangencies in high-dimensional systems.
|
|
240
|
+
|
|
241
|
+
### Modified
|
|
242
|
+
|
|
243
|
+
- The parameter validator now accepts empty lists for systems that take no parameters.
|
|
244
|
+
|
|
245
|
+
[v1.5.0]: https://github.com/mrolims/pynamicalsys/compare/v1.4.9...v1.5.0
|
|
246
|
+
|
|
247
|
+
## [v1.4.9] - 2025-11-18
|
|
248
|
+
|
|
249
|
+
### Fixed
|
|
250
|
+
|
|
251
|
+
- Fix missing dependency:
|
|
252
|
+
- Added `ipython (>=8.13,<9.0.0)` to `pyproject.toml` dependencies, since it is required by the `ContinuousDynamicalSystem` class.
|
|
253
|
+
|
|
254
|
+
[v1.4.9]: https://github.com/mrolims/pynamicalsys/compare/v1.4.1...v1.4.9
|
|
255
|
+
|
|
256
|
+
## [v1.4.6] - 2025-10-09
|
|
257
|
+
|
|
258
|
+
### Modified
|
|
259
|
+
|
|
260
|
+
- `HamiltonianSystem` class:
|
|
261
|
+
- Fixed the integration of the tangent vectors that was leading to numerical instability for long integration times.
|
|
262
|
+
|
|
263
|
+
- Refactored `recurrence_time_entropy` methods and `white_vertline_distr` function to handle the minimum line length parameter more consistently.
|
|
264
|
+
|
|
265
|
+
[v1.4.6]: https://github.com/mrolims/pynamicalsys/compare/v1.4.1...v1.4.6
|
|
266
|
+
|
|
267
|
+
## [v1.4.5] - 2025-09-17
|
|
268
|
+
|
|
269
|
+
### Modified
|
|
270
|
+
|
|
271
|
+
- `DiscreteDynamicalSystem` class:
|
|
272
|
+
- Fixed problems in the `finite_hurst_exponent`
|
|
273
|
+
|
|
274
|
+
- `ContinuousDynamicalSystem` and `HamiltonianSystem` classes:
|
|
275
|
+
- Fixed the output of the `recurrence_time_entropy` method when `return_final_state=True`.
|
|
276
|
+
|
|
277
|
+
[v1.4.5]: https://github.com/mrolims/pynamicalsys/compare/v1.4.1...v1.4.5
|
|
278
|
+
|
|
279
|
+
## [v1.4.1] - 2025-09-15
|
|
280
|
+
|
|
281
|
+
### Added
|
|
282
|
+
|
|
283
|
+
- `HamiltonianSystem` class for simulating and analyzing continuous-time Hamiltonian systems.
|
|
284
|
+
- Support for symplectic integration:
|
|
285
|
+
- 2nd-order velocity–Verlet
|
|
286
|
+
- 4th-order Yoshida
|
|
287
|
+
- Trajectory computation and ensemble trajectories.
|
|
288
|
+
- Poincaré section generation (single and ensemble).
|
|
289
|
+
- Chaos indicators:
|
|
290
|
+
- Lyapunov spectrum and maximum Lyapunov exponent.
|
|
291
|
+
- Smaller Alignment Index (SALI).
|
|
292
|
+
- Generalized Alignment Index (GALI).
|
|
293
|
+
- Linear Dependence Index (LDI).
|
|
294
|
+
- Recurrence time entropy (RTE).
|
|
295
|
+
- Hurst exponent.
|
|
296
|
+
|
|
297
|
+
- `ContinuousDynamicalSystem` class:
|
|
298
|
+
- `poincare_section` method: return the Poincaré section of a given initial condition or of an ensemble of initial conditions.
|
|
299
|
+
- `stroboscopic_map` method: return the stroboscopic map of a given initial condition or of an ensemble of initial conditions.
|
|
300
|
+
- `maxima_map` method: return the maxima map of a given initial condition or of an ensemble of inital conditions.
|
|
301
|
+
- `basin_of_attraction` method: given an ensemble of initial conditions, detect and label the attractors in the system.
|
|
302
|
+
- `recurrence_time_entropy` method: calculates the recurrence time entropy for a given initial condition using the Poincaré section, stroboscopic map, or maxima map to construct the recurrence matrix.
|
|
303
|
+
- `hurst_exponent` method: calculates the Hurst exponent for a given initial condition using the Poincaré section, stroboscopic map, or maxima map.
|
|
304
|
+
|
|
305
|
+
- `TimeSeriesMetrics`:
|
|
306
|
+
- `hurst_exponent` method.
|
|
307
|
+
|
|
308
|
+
### Modified
|
|
309
|
+
|
|
310
|
+
- `DiscreteDynamicalSystem` class:
|
|
311
|
+
- Unified the Hurst exponent calculation into a single function.
|
|
312
|
+
|
|
313
|
+
- `ContinuousDynamicalSystem` class:
|
|
314
|
+
- `lyapunov` method now uses a specific function to compute only the maximum Lyapunov exponent when `num_exponents=1`.
|
|
315
|
+
|
|
316
|
+
[v1.4.1]: https://github.com/mrolims/pynamicalsys/compare/v1.3.1...v1.4.1
|
|
317
|
+
|
|
318
|
+
## [v1.3.1] - 2025-08-24
|
|
319
|
+
|
|
320
|
+
### Modified
|
|
321
|
+
|
|
322
|
+
- Removed `cache=True` from the low level methods that was leading to cache compilation errors.
|
|
323
|
+
|
|
324
|
+
[v1.3.1]: https://github.com/mrolims/pynamicalsys/compare/v1.3.0...v1.3.1
|
|
325
|
+
|
|
326
|
+
## [v1.3.0] - 2025-08-23
|
|
327
|
+
|
|
328
|
+
### Added
|
|
329
|
+
|
|
330
|
+
- `DiscreteDynamicalSystem` class:
|
|
331
|
+
- `step` method: returns the next state of the system.
|
|
332
|
+
- `GALI` method: computes the generalized alignment index (GALI).
|
|
333
|
+
|
|
334
|
+
- `ContinuousDynamicalSystem` class:
|
|
335
|
+
- `GALI` method that computes the generalized alignment index (GALI).
|
|
336
|
+
|
|
337
|
+
### Modified
|
|
338
|
+
|
|
339
|
+
- `DiscreteDynamicalSystem` class:
|
|
340
|
+
- Improved performance when checking sampling points by avoiding repeated searches in sample_times.
|
|
341
|
+
- Refactored the `lyapunov` method to allow computing only a subset of the Lyapunov spectrum.
|
|
342
|
+
|
|
343
|
+
- `ContinuousDynamicalSystem` class:
|
|
344
|
+
- Unified integration step logic (previously duplicated across methods like trajectory and lyapunov_exponents) into a single step function.
|
|
345
|
+
- Refactored the `lyapunov` method to allow computing only a subset of the Lyapunov spectrum.
|
|
346
|
+
|
|
347
|
+
[v1.3.0]: https://github.com/mrolims/pynamicalsys/compare/v1.2.2...v1.3.0
|
|
348
|
+
|
|
349
|
+
## [v1.2.2] - 2025-06-29
|
|
350
|
+
|
|
351
|
+
### Added
|
|
352
|
+
|
|
353
|
+
- `ContinuousDynamicalSystem` class for simulating and analyzing continuous nonlinear dynamical systems:
|
|
354
|
+
- Integration using the 4th order Runge-Kutta method with fixed time step.
|
|
355
|
+
- Integration using the adaptive 4th/5th order Runge-Kutta method with adaptive time step.
|
|
356
|
+
- Trajectory computation.
|
|
357
|
+
- Lyapunov exponents calculation.
|
|
358
|
+
- The smaller aligment index (SALI) and linear dependence index (LDI) for chaos detection.
|
|
359
|
+
|
|
360
|
+
[v1.2.2]: https://github.com/mrolims/pynamicalsys/compare/v1.0.0...v1.2.2
|
|
361
|
+
|
|
362
|
+
## v1.0.0 - 2025-06-16
|
|
363
|
+
|
|
364
|
+
### Added
|
|
365
|
+
|
|
366
|
+
- `DiscreteDynamicalSystem` class for simulating and analyzing discrete nonlinear dynamical systems:
|
|
367
|
+
- Trajectory computation.
|
|
368
|
+
- Chaotic indicators.
|
|
369
|
+
- Fixed points, periodic orbits, and manifolds.
|
|
370
|
+
- Statistical analysis of ensemble of trajetories.
|
|
371
|
+
- Escape basin quantification.
|
|
372
|
+
- Initial release of the package
|
|
373
|
+
- First version of documentation
|
|
374
|
+
- Basic tests
|
|
375
|
+
|
|
376
|
+
- `BasinMetrics` class to compute basin metris such as basin entropy and boundary dimension.
|
|
377
|
+
|
|
378
|
+
- `TimeSeriesMetrics` class to compute metrics related to time series analysis.
|
|
379
|
+
|
|
380
|
+
- `PlotStyler` utility class to globally configure and apply consistent styling for Matplotlib plots.
|
|
381
|
+
|
|
382
|
+
<!-- Dummy heading to avoid ending on a transition -->
|
|
383
|
+
|
|
384
|
+
##
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# __init__.py
|
|
2
2
|
|
|
3
|
-
# Copyright (C) 2025 Matheus Rolim Sales
|
|
3
|
+
# Copyright (C) 2025-2026 Matheus Rolim Sales
|
|
4
4
|
#
|
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
from pynamicalsys.core.discrete_dynamical_systems import DiscreteDynamicalSystem
|
|
19
|
+
|
|
19
20
|
from pynamicalsys.core.continuous_dynamical_systems import ContinuousDynamicalSystem
|
|
20
21
|
from pynamicalsys.core.hamiltonian_systems import HamiltonianSystem
|
|
21
22
|
from pynamicalsys.core.basin_metrics import BasinMetrics
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '1.5.4'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 5, 4)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = 'g83b2f0161'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# __init__.py
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2025-2026 Matheus Rolim Sales
|
|
4
|
+
#
|
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# basin_analysis.py
|
|
2
2
|
|
|
3
|
-
# Copyright (C) 2025 Matheus Rolim Sales
|
|
3
|
+
# Copyright (C) 2025-2026 Matheus Rolim Sales
|
|
4
4
|
#
|
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import numpy as np
|
|
19
19
|
from numba import njit, prange
|
|
20
|
-
from typing import
|
|
20
|
+
from typing import Tuple
|
|
21
21
|
from numpy.typing import NDArray
|
|
22
22
|
|
|
23
23
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# clv.py
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025-2026 Matheus Rolim Sales
|
|
4
|
+
#
|
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
from numpy.typing import NDArray
|
|
21
|
+
from numba import njit
|
|
22
|
+
from .types import numeric_t
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@njit
|
|
26
|
+
def clv_sanitize_inplace(M: NDArray[np.float64]) -> None:
|
|
27
|
+
nrows, ncols = M.shape
|
|
28
|
+
for i in range(nrows):
|
|
29
|
+
for j in range(ncols):
|
|
30
|
+
x = M[i, j]
|
|
31
|
+
if not np.isfinite(x):
|
|
32
|
+
M[i, j] = 0.0
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@njit
|
|
36
|
+
def clv_col_normalize_inplace(M: NDArray[np.float64], eps_norm: numeric_t) -> None:
|
|
37
|
+
nrows, ncols = M.shape
|
|
38
|
+
for j in range(ncols):
|
|
39
|
+
s = 0.0
|
|
40
|
+
for i in range(nrows):
|
|
41
|
+
v = M[i, j]
|
|
42
|
+
s += v * v
|
|
43
|
+
|
|
44
|
+
nrm = np.sqrt(s)
|
|
45
|
+
|
|
46
|
+
if (not np.isfinite(nrm)) or (nrm < eps_norm):
|
|
47
|
+
for i in range(nrows):
|
|
48
|
+
M[i, j] = 0.0
|
|
49
|
+
continue
|
|
50
|
+
|
|
51
|
+
inv = 1.0 / nrm
|
|
52
|
+
for i in range(nrows):
|
|
53
|
+
M[i, j] *= inv
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@njit
|
|
57
|
+
def clv_solve_upper_inplace(
|
|
58
|
+
R: NDArray[np.float64],
|
|
59
|
+
B: NDArray[np.float64],
|
|
60
|
+
rcond_guard: numeric_t,
|
|
61
|
+
) -> None:
|
|
62
|
+
"""
|
|
63
|
+
Solve the upper-triangular system ``R X = B`` in place.
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
R : NDArray[np.float64]
|
|
68
|
+
Upper-triangular matrix of shape `(p, p)`.
|
|
69
|
+
B : NDArray[np.float64]
|
|
70
|
+
Right-hand side matrix of shape `(p, m)`. Overwritten in place with
|
|
71
|
+
the solution `X`.
|
|
72
|
+
rcond_guard : numeric_t
|
|
73
|
+
Minimum absolute value allowed for diagonal entries of `R` during the
|
|
74
|
+
back-substitution step.
|
|
75
|
+
|
|
76
|
+
Notes
|
|
77
|
+
-----
|
|
78
|
+
This function modifies `B` in place and does not modify `R`.
|
|
79
|
+
"""
|
|
80
|
+
p = R.shape[0]
|
|
81
|
+
ncols = B.shape[1]
|
|
82
|
+
|
|
83
|
+
for col in range(ncols):
|
|
84
|
+
for i in range(p - 1, -1, -1):
|
|
85
|
+
s = B[i, col]
|
|
86
|
+
|
|
87
|
+
for k in range(i + 1, p):
|
|
88
|
+
s -= R[i, k] * B[k, col]
|
|
89
|
+
|
|
90
|
+
rii = R[i, i]
|
|
91
|
+
if (not np.isfinite(rii)) or (np.abs(rii) < rcond_guard):
|
|
92
|
+
rii = rcond_guard if rii >= 0.0 else -rcond_guard
|
|
93
|
+
|
|
94
|
+
if not np.isfinite(s):
|
|
95
|
+
B[i, col] = 0.0
|
|
96
|
+
else:
|
|
97
|
+
B[i, col] = s / rii
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# differentiation.py
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025-2026 Matheus Rolim Sales
|
|
4
|
+
#
|
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
from typing import Callable
|
|
19
|
+
import numpy as np
|
|
20
|
+
from numpy.typing import NDArray
|
|
21
|
+
from numba import njit
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@njit
|
|
25
|
+
def finite_difference_jacobian(
|
|
26
|
+
u: NDArray[np.float64],
|
|
27
|
+
parameters: NDArray[np.float64],
|
|
28
|
+
mapping: Callable[[NDArray[np.float64], NDArray[np.float64]], NDArray[np.float64]],
|
|
29
|
+
eps: float = -1.0,
|
|
30
|
+
) -> NDArray[np.float64]:
|
|
31
|
+
"""
|
|
32
|
+
Compute the Jacobian matrix using adaptive finite differences with error control.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
u : NDArray[np.float64]
|
|
37
|
+
State vector at which to compute Jacobian (shape: (n,))
|
|
38
|
+
parameters : NDArray[np.float64]
|
|
39
|
+
System parameters
|
|
40
|
+
mapping : Callable[[NDArray, NDArray], NDArray]
|
|
41
|
+
Vector-valued function to differentiate
|
|
42
|
+
eps : float, optional
|
|
43
|
+
Initial step size (automatically determined if -1.0)
|
|
44
|
+
|
|
45
|
+
Returns
|
|
46
|
+
-------
|
|
47
|
+
NDArray[np.float64]
|
|
48
|
+
Jacobian matrix (shape: (n, n)) where J[i,j] = ∂f_i/∂u_j
|
|
49
|
+
|
|
50
|
+
Raises
|
|
51
|
+
------
|
|
52
|
+
ValueError
|
|
53
|
+
If invalid method is specified
|
|
54
|
+
If eps is not positive when provided
|
|
55
|
+
|
|
56
|
+
Notes
|
|
57
|
+
-----
|
|
58
|
+
- For 'central' method (default), accuracy is O(eps²)
|
|
59
|
+
- For 'complex' method, accuracy is O(eps⁴) but requires complex arithmetic
|
|
60
|
+
- Automatic step size selection based on machine epsilon and input scale
|
|
61
|
+
- Includes Richardson extrapolation for higher accuracy
|
|
62
|
+
- Handles edge cases like zero components carefully
|
|
63
|
+
|
|
64
|
+
Examples
|
|
65
|
+
--------
|
|
66
|
+
>>> def lorenz(u, p):
|
|
67
|
+
... x, y, z = u
|
|
68
|
+
... sigma, rho, beta = p
|
|
69
|
+
... return np.array([sigma*(y-x), x*(rho-z)-y, x*y-beta*z])
|
|
70
|
+
>>> u = np.array([1.0, 1.0, 1.0])
|
|
71
|
+
>>> params = np.array([10.0, 28.0, 8/3])
|
|
72
|
+
>>> J = finite_difference_jacobian(u, params, lorenz, method='central')
|
|
73
|
+
"""
|
|
74
|
+
n = len(u)
|
|
75
|
+
J = np.zeros((n, n))
|
|
76
|
+
|
|
77
|
+
# Determine optimal step size if not provided
|
|
78
|
+
if eps <= 0:
|
|
79
|
+
eps = float(np.finfo(np.float64).eps) ** (1 / 3) * max(
|
|
80
|
+
1.0, float(np.linalg.norm(u))
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
for i in range(n):
|
|
84
|
+
# Central difference: O(eps²) accuracy
|
|
85
|
+
u_plus = u.copy()
|
|
86
|
+
u_minus = u.copy()
|
|
87
|
+
u_plus[i] += eps
|
|
88
|
+
u_minus[i] -= eps
|
|
89
|
+
J[:, i] = (mapping(u_plus, parameters) - mapping(u_minus, parameters)) / (
|
|
90
|
+
2 * eps
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
return J
|