tsdynamics 3.0.0__tar.gz → 3.0.2__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.
Files changed (195) hide show
  1. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/PKG-INFO +1 -1
  2. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-core/src/bridge.rs +133 -3
  3. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-core/src/lib.rs +98 -0
  4. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/pyproject.toml +1 -1
  5. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/__init__.py +1 -1
  6. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/__init__.py +11 -0
  7. tsdynamics-3.0.2/src/tsdynamics/analysis/_result.py +692 -0
  8. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/__init__.py +5 -0
  9. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/_common.py +18 -19
  10. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/attractors.py +17 -13
  11. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/basins.py +67 -10
  12. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/continuation.py +5 -0
  13. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/basins/metrics.py +9 -4
  14. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/chaos/__init__.py +5 -0
  15. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/chaos/_common.py +14 -14
  16. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/chaos/expansion.py +10 -5
  17. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/chaos/gali.py +52 -8
  18. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/chaos/zero_one.py +7 -2
  19. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/__init__.py +5 -0
  20. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/_common.py +63 -7
  21. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/_scaling.py +5 -0
  22. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/correlation.py +11 -6
  23. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/fixedmass.py +8 -3
  24. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/dimensions/generalized.py +11 -6
  25. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/embedding/__init__.py +5 -0
  26. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/embedding/_common.py +13 -8
  27. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/embedding/delay.py +8 -3
  28. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/embedding/dimension.py +8 -3
  29. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/embedding/embed.py +9 -4
  30. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/__init__.py +5 -0
  31. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/core.py +27 -1
  32. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/dispersion.py +5 -0
  33. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/lz.py +5 -0
  34. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/multiscale.py +5 -0
  35. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/permutation.py +5 -0
  36. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/entropy/sample.py +5 -0
  37. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/fixedpoints/__init__.py +5 -0
  38. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/fixedpoints/fixed.py +5 -0
  39. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/fixedpoints/periodic.py +5 -0
  40. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/lyapunov/__init__.py +5 -0
  41. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/lyapunov/from_data.py +56 -0
  42. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/orbits/__init__.py +5 -0
  43. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/orbits/orbit_diagram.py +37 -0
  44. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/orbits/poincare.py +22 -2
  45. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/orbits/return_map.py +44 -0
  46. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/recurrence/__init__.py +5 -0
  47. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/recurrence/_common.py +16 -11
  48. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/recurrence/matrix.py +42 -4
  49. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/recurrence/rqa.py +40 -3
  50. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/recurrence/windowed.py +7 -2
  51. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/surrogate/__init__.py +5 -0
  52. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/surrogate/_common.py +12 -7
  53. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/surrogate/generators.py +13 -8
  54. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/surrogate/hypothesis.py +49 -3
  55. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/surrogate/statistics.py +5 -0
  56. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/data/__init__.py +5 -0
  57. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/data/sampling.py +5 -0
  58. tsdynamics-3.0.2/src/tsdynamics/data/trajectory.py +421 -0
  59. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/derived/__init__.py +5 -0
  60. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/derived/_base.py +25 -1
  61. tsdynamics-3.0.2/src/tsdynamics/derived/_crossings.py +194 -0
  62. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/derived/_variational.py +5 -0
  63. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/derived/ensemble.py +5 -0
  64. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/derived/poincare.py +89 -9
  65. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/derived/projected.py +5 -0
  66. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/derived/stroboscopic.py +5 -0
  67. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/derived/tangent.py +5 -0
  68. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/derived/wrapped.py +5 -0
  69. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/engine/__init__.py +10 -0
  70. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/engine/compile.py +5 -0
  71. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/engine/problem.py +5 -0
  72. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/engine/run.py +121 -0
  73. tsdynamics-3.0.2/src/tsdynamics/errors.py +172 -0
  74. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/families/__init__.py +5 -0
  75. tsdynamics-3.0.2/src/tsdynamics/families/_accessors.py +507 -0
  76. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/families/_dde_lyapunov.py +5 -0
  77. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/families/base.py +300 -2
  78. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/families/continuous.py +93 -17
  79. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/families/delay.py +5 -0
  80. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/families/discrete.py +43 -0
  81. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/families/protocol.py +27 -2
  82. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/families/stochastic.py +5 -0
  83. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/plugins.py +24 -0
  84. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/registry.py +30 -9
  85. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/solvers/__init__.py +5 -0
  86. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/solvers/select.py +5 -0
  87. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/__init__.py +9 -0
  88. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/__init__.py +5 -0
  89. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/__init__.py +5 -0
  90. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/transforms/__init__.py +5 -0
  91. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/transforms/features.py +5 -0
  92. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/transforms/preprocessing.py +5 -0
  93. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/transforms/spectral.py +5 -0
  94. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/utils/__init__.py +5 -0
  95. tsdynamics-3.0.2/src/tsdynamics/utils/grids.py +75 -0
  96. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/utils/sagitta_dt.py +5 -0
  97. tsdynamics-3.0.2/src/tsdynamics/viz/__init__.py +97 -0
  98. tsdynamics-3.0.2/src/tsdynamics/viz/spec.py +779 -0
  99. tsdynamics-3.0.0/src/tsdynamics/data/trajectory.py +0 -235
  100. tsdynamics-3.0.0/src/tsdynamics/utils/grids.py +0 -40
  101. tsdynamics-3.0.0/src/tsdynamics/viz/__init__.py +0 -10
  102. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/LICENSE +0 -0
  103. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/README.md +0 -0
  104. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/Cargo.toml +0 -0
  105. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-core/Cargo.lock +0 -0
  106. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-core/Cargo.toml +0 -0
  107. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/Cargo.toml +0 -0
  108. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/dde.rs +0 -0
  109. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/ensemble.rs +0 -0
  110. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/event.rs +0 -0
  111. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/integrate.rs +0 -0
  112. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/lib.rs +0 -0
  113. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/map.rs +0 -0
  114. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/problem.rs +0 -0
  115. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/rng.rs +0 -0
  116. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/sde.rs +0 -0
  117. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-engine/src/testkit.rs +0 -0
  118. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/Cargo.toml +0 -0
  119. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/builder.rs +0 -0
  120. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/eval.rs +0 -0
  121. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/lib.rs +0 -0
  122. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/op.rs +0 -0
  123. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/reference.rs +0 -0
  124. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/src/tape.rs +0 -0
  125. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/coverage_tape.rs +0 -0
  126. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/CircadianRhythm.txt +0 -0
  127. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/Lorenz.txt +0 -0
  128. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/SanUmSrisuchinwong.txt +0 -0
  129. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/SprottMore.txt +0 -0
  130. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/Torus.txt +0 -0
  131. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/fixtures/YuWang2.txt +0 -0
  132. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/gen_fixtures.py +0 -0
  133. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/golden_fixtures.rs +0 -0
  134. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-ir/tests/roundtrip.rs +0 -0
  135. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-jit/Cargo.toml +0 -0
  136. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-jit/src/codegen.rs +0 -0
  137. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-jit/src/error.rs +0 -0
  138. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-jit/src/evaluator.rs +0 -0
  139. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-jit/src/lib.rs +0 -0
  140. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-jit/src/shims.rs +0 -0
  141. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-jit/tests/compile_latency.rs +0 -0
  142. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-jit/tests/golden_fixtures.rs +0 -0
  143. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-jit/tests/interpreter_equivalence.rs +0 -0
  144. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/Cargo.toml +0 -0
  145. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/caps.rs +0 -0
  146. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/control.rs +0 -0
  147. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/dop853.rs +0 -0
  148. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/mod.rs +0 -0
  149. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/rk4.rs +0 -0
  150. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/rk45.rs +0 -0
  151. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/testkit.rs +0 -0
  152. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/explicit/tsit5.rs +0 -0
  153. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/bdf.rs +0 -0
  154. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/control.rs +0 -0
  155. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/linalg.rs +0 -0
  156. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/mod.rs +0 -0
  157. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/rosenbrock.rs +0 -0
  158. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/implicit/trbdf2.rs +0 -0
  159. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/lib.rs +0 -0
  160. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/registry.rs +0 -0
  161. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/sde/euler_maruyama.rs +0 -0
  162. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/sde/milstein.rs +0 -0
  163. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/sde/mod.rs +0 -0
  164. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/sde/testkit.rs +0 -0
  165. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/src/solver.rs +0 -0
  166. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/tests/explicit_accuracy.rs +0 -0
  167. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/tests/implicit_stiff.rs +0 -0
  168. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-solvers/tests/registry.rs +0 -0
  169. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-vm/Cargo.toml +0 -0
  170. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-vm/src/interp.rs +0 -0
  171. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-vm/src/lib.rs +0 -0
  172. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-vm/tests/golden_fixtures.rs +0 -0
  173. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/crates/tsdyn-vm/tests/oracle_equivalence.rs +0 -0
  174. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/analysis/fixedpoints/_common.py +0 -0
  175. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/engine/symbols.py +0 -0
  176. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/py.typed +0 -0
  177. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/solvers/explicit.py +0 -0
  178. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/solvers/implicit.py +0 -0
  179. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/solvers/stochastic.py +0 -0
  180. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/chaotic_attractors.py +0 -0
  181. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/chem_bio_systems.py +0 -0
  182. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/climate_geophysics.py +0 -0
  183. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/coupled_systems.py +0 -0
  184. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/delayed_systems.py +0 -0
  185. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/exotic_systems.py +0 -0
  186. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/oscillatory_systems.py +0 -0
  187. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/physical_systems.py +0 -0
  188. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/continuous/population_dynamics.py +0 -0
  189. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/chaotic_maps.py +0 -0
  190. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/exotic_maps.py +0 -0
  191. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/geometric_maps.py +0 -0
  192. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/polynomial_maps.py +0 -0
  193. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/systems/discrete/population_maps.py +0 -0
  194. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/transforms/_common.py +0 -0
  195. {tsdynamics-3.0.0 → tsdynamics-3.0.2}/src/tsdynamics/utils/general.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tsdynamics
3
- Version: 3.0.0
3
+ Version: 3.0.2
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Science/Research
6
6
  Classifier: Operating System :: OS Independent
@@ -28,9 +28,10 @@
28
28
 
29
29
  use tsdyn_engine::rng::SplitMix64;
30
30
  use tsdyn_engine::{
31
- ensemble_final as engine_ensemble, integrate_dde_grid, integrate_grid, iterate_dense,
32
- iterate_ensemble_final as engine_iterate_ensemble, sde_ensemble_final as engine_sde_ensemble,
33
- sde_integrate_grid, DelaySlot, IntegrateConfig, IntegrateError, MapError, SdeConfig, SdeError,
31
+ ensemble_final as engine_ensemble, integrate_dde_grid, integrate_events, integrate_grid,
32
+ iterate_dense, iterate_ensemble_final as engine_iterate_ensemble,
33
+ sde_ensemble_final as engine_sde_ensemble, sde_integrate_grid, DelaySlot, EventDirection,
34
+ EventSpec, IntegrateConfig, IntegrateError, MapError, SdeConfig, SdeError,
34
35
  };
35
36
  use tsdyn_ir::{Evaluator, Tape};
36
37
  use tsdyn_jit::JitEvaluator;
@@ -950,6 +951,135 @@ pub fn sde_ensemble_final(
950
951
  Ok(result.states)
951
952
  }
952
953
 
954
+ /// Map a Python-side direction code (`+1` / `-1` / `0`) to an [`EventDirection`].
955
+ fn event_direction(direction: i32) -> Result<EventDirection, EngineError> {
956
+ match direction {
957
+ 1 => Ok(EventDirection::Rising),
958
+ -1 => Ok(EventDirection::Falling),
959
+ 0 => Ok(EventDirection::Either),
960
+ other => Err(EngineError::BadShape(format!(
961
+ "event direction must be +1 (rising), -1 (falling) or 0 (either), got {other}"
962
+ ))),
963
+ }
964
+ }
965
+
966
+ /// Integrate `[t0, t1]` and return every crossing of the event function
967
+ /// `g(u, t) = 0` in `direction`, refined with the engine's O(h⁴) cubic-Hermite
968
+ /// dense output (stream WS-CROSSKERNEL — wiring the previously dead
969
+ /// [`tsdyn_engine::integrate_events`]).
970
+ ///
971
+ /// `rhs` is the system right-hand side; `g` a single-output tape evaluated over
972
+ /// the full state (`g.dim() == 1`, `g.n_param() <= rhs.n_param()`). `first_step`
973
+ /// seeds the solver; with the fixed-step `rk4` it *is* the march step, so a caller
974
+ /// that wants the Python `PoincareMap`'s dt-grid detection (no skipped crossings,
975
+ /// answer-identical refinement) passes `method = "rk4"`, `first_step = dt`.
976
+ ///
977
+ /// Returns `(times, states_flat, t_final, u_final, terminated)` — the `K` crossing
978
+ /// times, the row-major `(K, dim)` crossing states, the time/state the run stopped
979
+ /// at (so a caller can resume the next span exactly), and whether a terminal event
980
+ /// stopped it. Divergence raises ([`EngineError::Diverged`]), preserving the
981
+ /// "diverge loudly" contract of the per-`dt` Python path.
982
+ #[allow(clippy::too_many_arguments, clippy::type_complexity)]
983
+ pub fn integrate_events_dense(
984
+ rhs: Tape,
985
+ g: Tape,
986
+ ic: &[f64],
987
+ p: &[f64],
988
+ t0: f64,
989
+ t1: f64,
990
+ first_step: f64,
991
+ direction: i32,
992
+ terminal: bool,
993
+ method: &str,
994
+ rtol: f64,
995
+ atol: f64,
996
+ jit: bool,
997
+ ) -> Result<(Vec<f64>, Vec<f64>, f64, Vec<f64>, bool), EngineError> {
998
+ guard_continuous(&rhs)?;
999
+ check_inputs(&rhs, ic, p)?;
1000
+ if let Some(&bad) = ic.iter().find(|x| !x.is_finite()) {
1001
+ return Err(EngineError::BadShape(format!(
1002
+ "initial state must be finite, found {bad}"
1003
+ )));
1004
+ }
1005
+ let dim = rhs.dim();
1006
+ if dim == 0 {
1007
+ return Err(EngineError::BadShape(
1008
+ "system dimension is zero (the tape has no outputs)".to_string(),
1009
+ ));
1010
+ }
1011
+ // The event function is a single-output tape over the full state; it shares
1012
+ // the system parameter vector (it may declare fewer and read the leading
1013
+ // slice). `eval_event` in the engine asserts both, so reject violations here
1014
+ // as a clean `ValueError` rather than a release-build panic.
1015
+ if g.dim() != 1 {
1016
+ return Err(EngineError::BadShape(format!(
1017
+ "event function must have a single output, got {}",
1018
+ g.dim()
1019
+ )));
1020
+ }
1021
+ if g.n_state() > dim {
1022
+ return Err(EngineError::BadShape(format!(
1023
+ "event function reads {} state inputs but the system has dim = {dim}",
1024
+ g.n_state()
1025
+ )));
1026
+ }
1027
+ if g.n_param() > p.len() {
1028
+ return Err(EngineError::BadShape(format!(
1029
+ "event function declares {} parameters but the system has {}",
1030
+ g.n_param(),
1031
+ p.len()
1032
+ )));
1033
+ }
1034
+ if !(t0.is_finite() && t1.is_finite()) {
1035
+ return Err(EngineError::BadShape(format!(
1036
+ "event integration span must be finite, got t0 = {t0}, t1 = {t1}"
1037
+ )));
1038
+ }
1039
+ if t1 < t0 {
1040
+ return Err(EngineError::BadShape(format!(
1041
+ "integrate_events is forward only: need t1 >= t0, got t0 = {t0}, t1 = {t1}"
1042
+ )));
1043
+ }
1044
+ // The engine asserts a finite, positive first step (a hard `assert!`, not a
1045
+ // debug one) — turn a bad value into a clean error at the boundary.
1046
+ if !(first_step.is_finite() && first_step > 0.0) {
1047
+ return Err(EngineError::BadShape(format!(
1048
+ "first step (the detection dt) must be finite and positive, got {first_step}"
1049
+ )));
1050
+ }
1051
+ let dir = event_direction(direction)?;
1052
+ let name = resolve_solver(method)?;
1053
+ require_jacobian_if_needed(&rhs, name)?;
1054
+
1055
+ let rhs_ev = build_evaluator(rhs, jit)?;
1056
+ let g_ev = build_evaluator(g, jit)?;
1057
+ let mut solver = build_solver(name, rtol, atol);
1058
+ let cfg = IntegrateConfig::new(first_step);
1059
+
1060
+ let spec = if terminal {
1061
+ EventSpec::terminal(&*g_ev, dir)
1062
+ } else {
1063
+ EventSpec::new(&*g_ev, dir)
1064
+ };
1065
+ let outcome = integrate_events(&*rhs_ev, &mut *solver, &ic[..dim], p, t0, t1, &[spec], &cfg)
1066
+ .map_err(|e| EngineError::Diverged(diverge_msg(&e)))?;
1067
+
1068
+ let mut times = Vec::with_capacity(outcome.hits.len());
1069
+ let mut states = Vec::with_capacity(outcome.hits.len() * dim);
1070
+ for hit in &outcome.hits {
1071
+ times.push(hit.t);
1072
+ states.extend_from_slice(&hit.u);
1073
+ }
1074
+ Ok((
1075
+ times,
1076
+ states,
1077
+ outcome.t_final,
1078
+ outcome.u_final,
1079
+ outcome.terminated,
1080
+ ))
1081
+ }
1082
+
953
1083
  /// Prefix the engine's diverge message so the Python `RuntimeError` reads clearly.
954
1084
  fn diverge_msg(e: &IntegrateError) -> String {
955
1085
  format!("integration diverged before reaching the final time: {e}")
@@ -591,6 +591,103 @@ fn integrate_sde_ensemble_final<'py>(
591
591
  PyArray1::from_vec(py, flat).reshape([n_ic, dim])
592
592
  }
593
593
 
594
+ // ---------------------------------------------------------------------------
595
+ // Event detection (two tapes: right-hand side + event function g)
596
+ // ---------------------------------------------------------------------------
597
+
598
+ /// Integrate `[t0, t1]` and return the crossings of the event function
599
+ /// `g(u, t) = 0` in `direction` (`+1` rising / `-1` falling / `0` either),
600
+ /// refined with the engine's O(h⁴) cubic-Hermite dense output.
601
+ ///
602
+ /// The two tapes are passed back to back — first the right-hand side `f`, then the
603
+ /// single-output event function `g` (`g`'s `outputs.len() == 1`; it reads the full
604
+ /// state and may declare fewer parameters than the system, reading the leading
605
+ /// slice). `first_step` seeds the solver; with the fixed-step `rk4` it *is* the
606
+ /// detection step, so `method="rk4"`, `first_step=dt` reproduces the Python
607
+ /// `PoincareMap` dt-grid march and its refinement (answer-identical). `terminal`
608
+ /// stops the run at the first crossing. Divergence raises `RuntimeError`.
609
+ ///
610
+ /// Returns `(times, states, t_final, u_final, terminated)`: the `(K,)` crossing
611
+ /// times, the `(K, dim)` crossing states, the time and state the run stopped at
612
+ /// (to resume the next span exactly), and whether a terminal event stopped it.
613
+ #[pyfunction]
614
+ #[allow(clippy::too_many_arguments, clippy::type_complexity)]
615
+ fn integrate_events_dense<'py>(
616
+ py: Python<'py>,
617
+ ops: PyReadonlyArray1<i32>,
618
+ a: PyReadonlyArray1<i32>,
619
+ b: PyReadonlyArray1<i32>,
620
+ imm: PyReadonlyArray1<f64>,
621
+ outputs: PyReadonlyArray1<i32>,
622
+ jac_outputs: PyReadonlyArray1<i32>,
623
+ n_state: usize,
624
+ n_param: usize,
625
+ ops_g: PyReadonlyArray1<i32>,
626
+ a_g: PyReadonlyArray1<i32>,
627
+ b_g: PyReadonlyArray1<i32>,
628
+ imm_g: PyReadonlyArray1<f64>,
629
+ outputs_g: PyReadonlyArray1<i32>,
630
+ jac_outputs_g: PyReadonlyArray1<i32>,
631
+ n_state_g: usize,
632
+ n_param_g: usize,
633
+ ic: PyReadonlyArray1<f64>,
634
+ p: PyReadonlyArray1<f64>,
635
+ t0: f64,
636
+ t1: f64,
637
+ first_step: f64,
638
+ direction: i32,
639
+ terminal: bool,
640
+ method: String,
641
+ rtol: f64,
642
+ atol: f64,
643
+ jit: bool,
644
+ ) -> PyResult<(
645
+ Bound<'py, PyArray1<f64>>,
646
+ Bound<'py, PyArray2<f64>>,
647
+ f64,
648
+ Bound<'py, PyArray1<f64>>,
649
+ bool,
650
+ )> {
651
+ let rhs = OwnedTape::copy_in(&ops, &a, &b, &imm, &outputs, &jac_outputs, n_state, n_param)?;
652
+ let g = OwnedTape::copy_in(
653
+ &ops_g,
654
+ &a_g,
655
+ &b_g,
656
+ &imm_g,
657
+ &outputs_g,
658
+ &jac_outputs_g,
659
+ n_state_g,
660
+ n_param_g,
661
+ )?;
662
+ let dim = rhs.dim();
663
+ let ic = vec_f64("ic", &ic)?;
664
+ let p = vec_f64("p", &p)?;
665
+ let (times, states, t_final, u_final, terminated) = py
666
+ .detach(|| {
667
+ bridge::integrate_events_dense(
668
+ rhs.build()?,
669
+ g.build()?,
670
+ &ic,
671
+ &p,
672
+ t0,
673
+ t1,
674
+ first_step,
675
+ direction,
676
+ terminal,
677
+ &method,
678
+ rtol,
679
+ atol,
680
+ jit,
681
+ )
682
+ })
683
+ .map_err(to_py_err)?;
684
+ let n_hits = times.len();
685
+ let times = PyArray1::from_vec(py, times);
686
+ let states = PyArray1::from_vec(py, states).reshape([n_hits, dim])?;
687
+ let u_final = PyArray1::from_vec(py, u_final);
688
+ Ok((times, states, t_final, u_final, terminated))
689
+ }
690
+
594
691
  // ---------------------------------------------------------------------------
595
692
  // Introspection
596
693
  // ---------------------------------------------------------------------------
@@ -644,6 +741,7 @@ fn _rust(m: &Bound<'_, PyModule>) -> PyResult<()> {
644
741
  m.add_function(wrap_pyfunction!(integrate_ensemble_final, m)?)?;
645
742
  m.add_function(wrap_pyfunction!(integrate_sde_dense, m)?)?;
646
743
  m.add_function(wrap_pyfunction!(integrate_sde_ensemble_final, m)?)?;
744
+ m.add_function(wrap_pyfunction!(integrate_events_dense, m)?)?;
647
745
  m.add_function(wrap_pyfunction!(solvers, m)?)?;
648
746
  m.add_function(wrap_pyfunction!(_version, m)?)?;
649
747
  Ok(())
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "tsdynamics"
7
- version = "3.0.0"
7
+ version = "3.0.2"
8
8
  description = "Zero-warmup Rust-engine ODE/DDE/SDE integration, discrete maps, and chaos analysis for dynamical systems."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12,<4.0"
@@ -124,7 +124,7 @@ from .families import (
124
124
  )
125
125
 
126
126
  # Single source of truth for the package version; rewritten by python-semantic-release.
127
- __version__ = "3.0.0"
127
+ __version__ = "3.0.2"
128
128
 
129
129
  # Built-in system classes are NOT bound into this namespace — that would bury the
130
130
  # submodules (``analysis``, ``data``, ``systems``, …) under ~149 model names in
@@ -177,6 +177,7 @@ __all__ = [
177
177
  "correlation_dimension",
178
178
  "correlation_sum",
179
179
  "dimension_spectrum",
180
+ "discover_plugins",
180
181
  "dispersion_entropy",
181
182
  "embed",
182
183
  "embedding_dimension",
@@ -250,3 +251,13 @@ def discover_plugins(*, strict: bool = False) -> list[str]:
250
251
  # analyses register themselves from their own subpackages (the analysis streams);
251
252
  # plugin failures are isolated inside `register_entry_points`.
252
253
  discover_plugins()
254
+
255
+
256
+ def __dir__() -> list[str]:
257
+ """Expose only the curated public API (``__all__``) to ``dir()`` / autocomplete.
258
+
259
+ The capability subpackages (``basins``, ``chaos``, …) and plugin-wiring
260
+ helpers are re-exported flat or used internally; they stay importable but are
261
+ kept off the tab-completion surface so only the public quantifiers show.
262
+ """
263
+ return sorted(__all__)