physicskit 0.1.0__py3-none-any.whl

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 (484) hide show
  1. physicskit/__init__.py +51 -0
  2. physicskit/astro/__init__.py +66 -0
  3. physicskit/astro/cosmic_web.py +395 -0
  4. physicskit/astro/galactic_dynamics.py +137 -0
  5. physicskit/astro/nbody.py +208 -0
  6. physicskit/astro/orbital_mechanics.py +220 -0
  7. physicskit/astro/stellar_dynamo.py +628 -0
  8. physicskit/astro/stellar_structure.py +198 -0
  9. physicskit/astro/tests/__init__.py +0 -0
  10. physicskit/astro/tests/conftest.py +7 -0
  11. physicskit/astro/tests/test_cosmic_web.py +159 -0
  12. physicskit/astro/tests/test_galactic_dynamics.py +46 -0
  13. physicskit/astro/tests/test_nbody.py +81 -0
  14. physicskit/astro/tests/test_orbital_mechanics.py +73 -0
  15. physicskit/astro/tests/test_stellar_dynamo.py +198 -0
  16. physicskit/astro/tests/test_stellar_structure.py +52 -0
  17. physicskit/astro/tests/test_visualizers.py +159 -0
  18. physicskit/astro/visualizers.py +628 -0
  19. physicskit/chaos/__init__.py +55 -0
  20. physicskit/chaos/core/__init__.py +3 -0
  21. physicskit/chaos/core/base_system.py +342 -0
  22. physicskit/chaos/core/integrators.py +40 -0
  23. physicskit/chaos/exceptions.py +24 -0
  24. physicskit/chaos/quantum/__init__.py +38 -0
  25. physicskit/chaos/quantum/billiards.py +274 -0
  26. physicskit/chaos/quantum/husimi.py +85 -0
  27. physicskit/chaos/quantum/maps.py +366 -0
  28. physicskit/chaos/systems/__init__.py +38 -0
  29. physicskit/chaos/systems/billiards.py +1131 -0
  30. physicskit/chaos/systems/continuous.py +1276 -0
  31. physicskit/chaos/systems/maps.py +557 -0
  32. physicskit/chaos/tests/__init__.py +0 -0
  33. physicskit/chaos/tests/test_basins.py +76 -0
  34. physicskit/chaos/tests/test_bifurcation.py +132 -0
  35. physicskit/chaos/tests/test_billiards.py +115 -0
  36. physicskit/chaos/tests/test_continuous.py +224 -0
  37. physicskit/chaos/tests/test_dimension.py +69 -0
  38. physicskit/chaos/tests/test_divergence.py +90 -0
  39. physicskit/chaos/tests/test_dynamic_plots.py +269 -0
  40. physicskit/chaos/tests/test_integrators.py +96 -0
  41. physicskit/chaos/tests/test_io.py +41 -0
  42. physicskit/chaos/tests/test_maps.py +110 -0
  43. physicskit/chaos/tests/test_metrics.py +115 -0
  44. physicskit/chaos/tests/test_phase_space.py +73 -0
  45. physicskit/chaos/tests/test_properties.py +116 -0
  46. physicskit/chaos/tests/test_quantum_billiards.py +94 -0
  47. physicskit/chaos/tests/test_quantum_maps.py +144 -0
  48. physicskit/chaos/tests/test_recurrence.py +51 -0
  49. physicskit/chaos/tests/test_repr_and_api_consistency.py +134 -0
  50. physicskit/chaos/tests/test_section.py +49 -0
  51. physicskit/chaos/tests/test_spectral.py +48 -0
  52. physicskit/chaos/tests/test_streamlit_app.py +45 -0
  53. physicskit/chaos/tests/test_timeseries.py +131 -0
  54. physicskit/chaos/tests/test_viewer3d.py +41 -0
  55. physicskit/chaos/utils/__init__.py +46 -0
  56. physicskit/chaos/utils/dimension.py +139 -0
  57. physicskit/chaos/utils/io.py +95 -0
  58. physicskit/chaos/utils/metrics.py +304 -0
  59. physicskit/chaos/utils/recurrence.py +122 -0
  60. physicskit/chaos/utils/spectral.py +69 -0
  61. physicskit/chaos/utils/timeseries.py +303 -0
  62. physicskit/chaos/visualizers/__init__.py +85 -0
  63. physicskit/chaos/visualizers/basins.py +185 -0
  64. physicskit/chaos/visualizers/bifurcation.py +273 -0
  65. physicskit/chaos/visualizers/divergence.py +374 -0
  66. physicskit/chaos/visualizers/dynamic_plots.py +1372 -0
  67. physicskit/chaos/visualizers/phase_space.py +133 -0
  68. physicskit/chaos/visualizers/quantum.py +299 -0
  69. physicskit/chaos/visualizers/recurrence.py +91 -0
  70. physicskit/chaos/visualizers/section.py +161 -0
  71. physicskit/chaos/visualizers/theme.py +31 -0
  72. physicskit/chaos/visualizers/viewer3d.py +82 -0
  73. physicskit/classical/__init__.py +55 -0
  74. physicskit/classical/core/__init__.py +17 -0
  75. physicskit/classical/core/base_system.py +510 -0
  76. physicskit/classical/core/integrators.py +397 -0
  77. physicskit/classical/systems/__init__.py +32 -0
  78. physicskit/classical/systems/chains.py +334 -0
  79. physicskit/classical/systems/hamiltonian.py +215 -0
  80. physicskit/classical/systems/lagrangian.py +308 -0
  81. physicskit/classical/systems/newtonian.py +536 -0
  82. physicskit/classical/systems/rotations.py +614 -0
  83. physicskit/classical/tests/__init__.py +0 -0
  84. physicskit/classical/tests/conftest.py +7 -0
  85. physicskit/classical/tests/test_base_system.py +113 -0
  86. physicskit/classical/tests/test_chains.py +84 -0
  87. physicskit/classical/tests/test_conservation.py +244 -0
  88. physicskit/classical/tests/test_conservation_utils.py +47 -0
  89. physicskit/classical/tests/test_hamiltonian.py +44 -0
  90. physicskit/classical/tests/test_integrators.py +123 -0
  91. physicskit/classical/tests/test_lagrangian.py +69 -0
  92. physicskit/classical/tests/test_newtonian.py +45 -0
  93. physicskit/classical/tests/test_rotations.py +160 -0
  94. physicskit/classical/tests/test_stepsize.py +149 -0
  95. physicskit/classical/tests/test_symbolic.py +125 -0
  96. physicskit/classical/tests/test_visualizers.py +172 -0
  97. physicskit/classical/utils/__init__.py +20 -0
  98. physicskit/classical/utils/conservation.py +126 -0
  99. physicskit/classical/utils/stepsize.py +187 -0
  100. physicskit/classical/utils/symbolic.py +235 -0
  101. physicskit/classical/visualizers/__init__.py +25 -0
  102. physicskit/classical/visualizers/animations.py +508 -0
  103. physicskit/classical/visualizers/interactive.py +113 -0
  104. physicskit/classical/visualizers/modal_analysis.py +97 -0
  105. physicskit/classical/visualizers/phase_space.py +214 -0
  106. physicskit/condensed/__init__.py +122 -0
  107. physicskit/condensed/anderson_localization.py +155 -0
  108. physicskit/condensed/correlated.py +284 -0
  109. physicskit/condensed/ginzburg_landau.py +220 -0
  110. physicskit/condensed/landau_levels.py +246 -0
  111. physicskit/condensed/laughlin.py +229 -0
  112. physicskit/condensed/models.py +627 -0
  113. physicskit/condensed/tests/__init__.py +0 -0
  114. physicskit/condensed/tests/test_condensed.py +518 -0
  115. physicskit/condensed/tests/test_visualizers.py +87 -0
  116. physicskit/condensed/tight_binding.py +445 -0
  117. physicskit/condensed/topological_insulator_3d.py +178 -0
  118. physicskit/condensed/topology.py +217 -0
  119. physicskit/condensed/visualizers.py +296 -0
  120. physicskit/condensed/weyl.py +180 -0
  121. physicskit/constants.py +184 -0
  122. physicskit/fields/__init__.py +111 -0
  123. physicskit/fields/electrodynamics.py +671 -0
  124. physicskit/fields/quantum_fields.py +510 -0
  125. physicskit/fields/solitons.py +527 -0
  126. physicskit/fields/tests/__init__.py +0 -0
  127. physicskit/fields/tests/conftest.py +7 -0
  128. physicskit/fields/tests/test_field_animations.py +154 -0
  129. physicskit/fields/tests/test_fields.py +439 -0
  130. physicskit/fields/tests/test_visualizers.py +101 -0
  131. physicskit/fields/visualizers.py +503 -0
  132. physicskit/fluids/__init__.py +134 -0
  133. physicskit/fluids/core/__init__.py +23 -0
  134. physicskit/fluids/core/grid.py +165 -0
  135. physicskit/fluids/core/timestepping.py +231 -0
  136. physicskit/fluids/exceptions.py +26 -0
  137. physicskit/fluids/systems/__init__.py +70 -0
  138. physicskit/fluids/systems/compressible_flow.py +281 -0
  139. physicskit/fluids/systems/instabilities.py +343 -0
  140. physicskit/fluids/systems/navier_stokes.py +221 -0
  141. physicskit/fluids/systems/potential_flow.py +440 -0
  142. physicskit/fluids/systems/viscous_flow.py +425 -0
  143. physicskit/fluids/systems/vortex_dynamics.py +304 -0
  144. physicskit/fluids/tests/__init__.py +0 -0
  145. physicskit/fluids/tests/conftest.py +7 -0
  146. physicskit/fluids/tests/test_compressible_flow.py +66 -0
  147. physicskit/fluids/tests/test_instabilities.py +115 -0
  148. physicskit/fluids/tests/test_navier_stokes.py +67 -0
  149. physicskit/fluids/tests/test_potential_flow.py +92 -0
  150. physicskit/fluids/tests/test_static_visualizers.py +91 -0
  151. physicskit/fluids/tests/test_utils.py +100 -0
  152. physicskit/fluids/tests/test_viscous_flow.py +110 -0
  153. physicskit/fluids/tests/test_visualizers.py +34 -0
  154. physicskit/fluids/tests/test_vortex_dynamics.py +88 -0
  155. physicskit/fluids/utils/__init__.py +18 -0
  156. physicskit/fluids/utils/dimensionless.py +239 -0
  157. physicskit/fluids/utils/spectral_analysis.py +142 -0
  158. physicskit/fluids/visualizers/__init__.py +14 -0
  159. physicskit/fluids/visualizers/compressible.py +39 -0
  160. physicskit/fluids/visualizers/flow_fields.py +252 -0
  161. physicskit/fluids/visualizers/potential_flow.py +51 -0
  162. physicskit/fluids/visualizers/spectra.py +62 -0
  163. physicskit/fluids/visualizers/theme.py +38 -0
  164. physicskit/integrators/__init__.py +52 -0
  165. physicskit/integrators/adaptive.py +199 -0
  166. physicskit/integrators/fixed_step.py +360 -0
  167. physicskit/integrators/tests/__init__.py +0 -0
  168. physicskit/integrators/tests/test_integrators.py +101 -0
  169. physicskit/optics/__init__.py +124 -0
  170. physicskit/optics/_compat.py +5 -0
  171. physicskit/optics/gaussian.py +382 -0
  172. physicskit/optics/quantum_optics.py +428 -0
  173. physicskit/optics/ray.py +469 -0
  174. physicskit/optics/tests/__init__.py +0 -0
  175. physicskit/optics/tests/test_diffraction_animation.py +38 -0
  176. physicskit/optics/tests/test_gaussian.py +170 -0
  177. physicskit/optics/tests/test_quantum_optics.py +147 -0
  178. physicskit/optics/tests/test_ray.py +177 -0
  179. physicskit/optics/tests/test_visualizers.py +58 -0
  180. physicskit/optics/tests/test_wave.py +146 -0
  181. physicskit/optics/visualizers.py +264 -0
  182. physicskit/optics/wave.py +365 -0
  183. physicskit/particle/__init__.py +152 -0
  184. physicskit/particle/collider.py +382 -0
  185. physicskit/particle/confinement.py +125 -0
  186. physicskit/particle/decays.py +357 -0
  187. physicskit/particle/electroweak.py +300 -0
  188. physicskit/particle/kinematics.py +271 -0
  189. physicskit/particle/neutrinos.py +84 -0
  190. physicskit/particle/nuclear.py +100 -0
  191. physicskit/particle/scattering.py +159 -0
  192. physicskit/particle/tests/__init__.py +0 -0
  193. physicskit/particle/tests/conftest.py +7 -0
  194. physicskit/particle/tests/test_collider.py +119 -0
  195. physicskit/particle/tests/test_confinement.py +42 -0
  196. physicskit/particle/tests/test_decays.py +112 -0
  197. physicskit/particle/tests/test_electroweak.py +97 -0
  198. physicskit/particle/tests/test_kinematics.py +138 -0
  199. physicskit/particle/tests/test_neutrinos.py +36 -0
  200. physicskit/particle/tests/test_nuclear.py +45 -0
  201. physicskit/particle/tests/test_scattering.py +64 -0
  202. physicskit/particle/tests/test_visualizers.py +214 -0
  203. physicskit/particle/visualizers/__init__.py +38 -0
  204. physicskit/particle/visualizers/animations.py +705 -0
  205. physicskit/particle/visualizers/static.py +101 -0
  206. physicskit/plasma/__init__.py +176 -0
  207. physicskit/plasma/acceleration.py +152 -0
  208. physicskit/plasma/instabilities.py +417 -0
  209. physicskit/plasma/kinetic.py +588 -0
  210. physicskit/plasma/mhd.py +463 -0
  211. physicskit/plasma/single_particle.py +562 -0
  212. physicskit/plasma/tests/__init__.py +0 -0
  213. physicskit/plasma/tests/conftest.py +7 -0
  214. physicskit/plasma/tests/test_new_time_domain_features.py +222 -0
  215. physicskit/plasma/tests/test_plasma.py +232 -0
  216. physicskit/plasma/tests/test_visualizers.py +79 -0
  217. physicskit/plasma/turbulence.py +219 -0
  218. physicskit/plasma/visualizers.py +868 -0
  219. physicskit/plasma/waves.py +549 -0
  220. physicskit/quantum/__init__.py +180 -0
  221. physicskit/quantum/_compat.py +20 -0
  222. physicskit/quantum/chapters/__init__.py +0 -0
  223. physicskit/quantum/chapters/entanglement.py +489 -0
  224. physicskit/quantum/chapters/harmonic_spin.py +517 -0
  225. physicskit/quantum/chapters/hydrogen_am.py +292 -0
  226. physicskit/quantum/chapters/perturbation.py +350 -0
  227. physicskit/quantum/chapters/potentials.py +997 -0
  228. physicskit/quantum/chapters/spin.py +306 -0
  229. physicskit/quantum/chapters/wave_packets.py +541 -0
  230. physicskit/quantum/core/__init__.py +0 -0
  231. physicskit/quantum/core/eigensolvers.py +311 -0
  232. physicskit/quantum/core/operators.py +296 -0
  233. physicskit/quantum/core/solvers.py +271 -0
  234. physicskit/quantum/tests/__init__.py +0 -0
  235. physicskit/quantum/tests/conftest.py +7 -0
  236. physicskit/quantum/tests/test_animations.py +225 -0
  237. physicskit/quantum/tests/test_compat.py +43 -0
  238. physicskit/quantum/tests/test_eigensolvers.py +24 -0
  239. physicskit/quantum/tests/test_entanglement.py +127 -0
  240. physicskit/quantum/tests/test_harmonic_spin.py +140 -0
  241. physicskit/quantum/tests/test_hydrogen_am.py +48 -0
  242. physicskit/quantum/tests/test_measure.py +110 -0
  243. physicskit/quantum/tests/test_operators.py +105 -0
  244. physicskit/quantum/tests/test_perturbation.py +112 -0
  245. physicskit/quantum/tests/test_physics_checks.py +131 -0
  246. physicskit/quantum/tests/test_potentials.py +191 -0
  247. physicskit/quantum/tests/test_solvers.py +70 -0
  248. physicskit/quantum/tests/test_spin.py +22 -0
  249. physicskit/quantum/tests/test_unitarity.py +84 -0
  250. physicskit/quantum/tests/test_wave_packets.py +53 -0
  251. physicskit/quantum/utils/__init__.py +0 -0
  252. physicskit/quantum/utils/measure.py +253 -0
  253. physicskit/quantum/visualizers/__init__.py +0 -0
  254. physicskit/quantum/visualizers/bloch_sphere.py +205 -0
  255. physicskit/quantum/visualizers/entanglement.py +58 -0
  256. physicskit/quantum/visualizers/orbitals.py +187 -0
  257. physicskit/quantum/visualizers/phase_space.py +179 -0
  258. physicskit/quantum/visualizers/wavefunctions.py +230 -0
  259. physicskit/relativity/__init__.py +61 -0
  260. physicskit/relativity/chapters/__init__.py +33 -0
  261. physicskit/relativity/chapters/cosmology.py +190 -0
  262. physicskit/relativity/chapters/gw_merger.py +399 -0
  263. physicskit/relativity/chapters/kerr.py +371 -0
  264. physicskit/relativity/chapters/lensing.py +196 -0
  265. physicskit/relativity/chapters/neutron_star.py +149 -0
  266. physicskit/relativity/chapters/schwarzschild.py +412 -0
  267. physicskit/relativity/chapters/timekeeping.py +133 -0
  268. physicskit/relativity/core/__init__.py +12 -0
  269. physicskit/relativity/core/geodesics.py +216 -0
  270. physicskit/relativity/core/kerr_raytracer.py +259 -0
  271. physicskit/relativity/core/raytracer.py +241 -0
  272. physicskit/relativity/core/tensors.py +468 -0
  273. physicskit/relativity/tests/__init__.py +0 -0
  274. physicskit/relativity/tests/test_conservations.py +54 -0
  275. physicskit/relativity/tests/test_constants.py +34 -0
  276. physicskit/relativity/tests/test_cosmology.py +61 -0
  277. physicskit/relativity/tests/test_gw_merger.py +117 -0
  278. physicskit/relativity/tests/test_kerr.py +116 -0
  279. physicskit/relativity/tests/test_kerr_raytracer.py +103 -0
  280. physicskit/relativity/tests/test_lensing.py +75 -0
  281. physicskit/relativity/tests/test_neutron_star.py +48 -0
  282. physicskit/relativity/tests/test_raytracer.py +67 -0
  283. physicskit/relativity/tests/test_schwarzschild.py +126 -0
  284. physicskit/relativity/tests/test_shadow_render.py +81 -0
  285. physicskit/relativity/tests/test_tensors.py +86 -0
  286. physicskit/relativity/tests/test_timekeeping.py +51 -0
  287. physicskit/relativity/tests/test_visualizers_misc.py +115 -0
  288. physicskit/relativity/utils/__init__.py +1 -0
  289. physicskit/relativity/utils/constants.py +232 -0
  290. physicskit/relativity/visualizers/__init__.py +46 -0
  291. physicskit/relativity/visualizers/interactive.py +127 -0
  292. physicskit/relativity/visualizers/shadow_render.py +367 -0
  293. physicskit/relativity/visualizers/spacetime_3d.py +92 -0
  294. physicskit/relativity/visualizers/spacetime_diagrams.py +198 -0
  295. physicskit/relativity/visualizers/wave_plots.py +185 -0
  296. physicskit/rmt/__init__.py +8 -0
  297. physicskit/rmt/ensembles/__init__.py +108 -0
  298. physicskit/rmt/ensembles/banded.py +114 -0
  299. physicskit/rmt/ensembles/base.py +135 -0
  300. physicskit/rmt/ensembles/bdg.py +218 -0
  301. physicskit/rmt/ensembles/chiral.py +308 -0
  302. physicskit/rmt/ensembles/circular.py +104 -0
  303. physicskit/rmt/ensembles/crossover.py +82 -0
  304. physicskit/rmt/ensembles/density_matrix.py +148 -0
  305. physicskit/rmt/ensembles/effective_hamiltonian.py +230 -0
  306. physicskit/rmt/ensembles/embedded.py +207 -0
  307. physicskit/rmt/ensembles/gaussian.py +153 -0
  308. physicskit/rmt/ensembles/ginibre.py +110 -0
  309. physicskit/rmt/ensembles/girko.py +190 -0
  310. physicskit/rmt/ensembles/graph_laplacian.py +92 -0
  311. physicskit/rmt/ensembles/haar.py +57 -0
  312. physicskit/rmt/ensembles/jacobi.py +182 -0
  313. physicskit/rmt/ensembles/poisson.py +77 -0
  314. physicskit/rmt/ensembles/polynomial.py +139 -0
  315. physicskit/rmt/ensembles/pt_symmetric.py +120 -0
  316. physicskit/rmt/ensembles/single_ring.py +170 -0
  317. physicskit/rmt/ensembles/sparse.py +95 -0
  318. physicskit/rmt/ensembles/syk.py +170 -0
  319. physicskit/rmt/ensembles/truncated_unitary.py +80 -0
  320. physicskit/rmt/ensembles/universality.py +92 -0
  321. physicskit/rmt/ensembles/wishart.py +88 -0
  322. physicskit/rmt/py.typed +0 -0
  323. physicskit/rmt/spectrum.py +82 -0
  324. physicskit/rmt/stats/__init__.py +160 -0
  325. physicskit/rmt/stats/characteristic_polynomial.py +77 -0
  326. physicskit/rmt/stats/circular_law.py +54 -0
  327. physicskit/rmt/stats/correlations.py +162 -0
  328. physicskit/rmt/stats/density.py +70 -0
  329. physicskit/rmt/stats/entanglement.py +36 -0
  330. physicskit/rmt/stats/free_probability.py +202 -0
  331. physicskit/rmt/stats/localization.py +338 -0
  332. physicskit/rmt/stats/marchenko_pastur.py +55 -0
  333. physicskit/rmt/stats/pt_symmetric.py +265 -0
  334. physicskit/rmt/stats/ratios.py +110 -0
  335. physicskit/rmt/stats/real_ginibre.py +134 -0
  336. physicskit/rmt/stats/rigidity.py +272 -0
  337. physicskit/rmt/stats/single_ring.py +95 -0
  338. physicskit/rmt/stats/spacing.py +150 -0
  339. physicskit/rmt/stats/tracy_widom.py +175 -0
  340. physicskit/rmt/stats/truncated_unitary.py +40 -0
  341. physicskit/rmt/stats/unfolding.py +37 -0
  342. physicskit/rmt/stats/wachter.py +67 -0
  343. physicskit/rmt/tests/__init__.py +0 -0
  344. physicskit/rmt/tests/cache_utils.py +107 -0
  345. physicskit/rmt/tests/conftest.py +8 -0
  346. physicskit/rmt/tests/test_banded.py +86 -0
  347. physicskit/rmt/tests/test_base.py +29 -0
  348. physicskit/rmt/tests/test_bdg.py +133 -0
  349. physicskit/rmt/tests/test_characteristic_polynomial.py +50 -0
  350. physicskit/rmt/tests/test_chiral.py +273 -0
  351. physicskit/rmt/tests/test_circular.py +225 -0
  352. physicskit/rmt/tests/test_crossover.py +72 -0
  353. physicskit/rmt/tests/test_density.py +23 -0
  354. physicskit/rmt/tests/test_density_matrix.py +181 -0
  355. physicskit/rmt/tests/test_effective_hamiltonian.py +140 -0
  356. physicskit/rmt/tests/test_embedded.py +169 -0
  357. physicskit/rmt/tests/test_free_probability.py +81 -0
  358. physicskit/rmt/tests/test_gaussian_ensembles.py +22 -0
  359. physicskit/rmt/tests/test_gaussian_semicircle.py +127 -0
  360. physicskit/rmt/tests/test_ginibre_circular_law.py +131 -0
  361. physicskit/rmt/tests/test_girko.py +178 -0
  362. physicskit/rmt/tests/test_graph_laplacian.py +102 -0
  363. physicskit/rmt/tests/test_haar.py +118 -0
  364. physicskit/rmt/tests/test_jacobi_wachter.py +136 -0
  365. physicskit/rmt/tests/test_localization.py +240 -0
  366. physicskit/rmt/tests/test_poisson.py +149 -0
  367. physicskit/rmt/tests/test_polynomial.py +107 -0
  368. physicskit/rmt/tests/test_pt_symmetric.py +178 -0
  369. physicskit/rmt/tests/test_random_state.py +19 -0
  370. physicskit/rmt/tests/test_real_ginibre.py +112 -0
  371. physicskit/rmt/tests/test_rigidity_universality.py +167 -0
  372. physicskit/rmt/tests/test_single_ring.py +132 -0
  373. physicskit/rmt/tests/test_spacing_and_ratios.py +122 -0
  374. physicskit/rmt/tests/test_sparse.py +71 -0
  375. physicskit/rmt/tests/test_spectrum.py +27 -0
  376. physicskit/rmt/tests/test_syk.py +136 -0
  377. physicskit/rmt/tests/test_tracy_widom.py +113 -0
  378. physicskit/rmt/tests/test_tridiagonal.py +41 -0
  379. physicskit/rmt/tests/test_truncated_unitary.py +80 -0
  380. physicskit/rmt/tests/test_validation_base.py +25 -0
  381. physicskit/rmt/tests/test_validation_misc.py +67 -0
  382. physicskit/rmt/tests/test_wishart_marchenko_pastur.py +120 -0
  383. physicskit/rmt/utils/__init__.py +0 -0
  384. physicskit/rmt/utils/haar.py +128 -0
  385. physicskit/rmt/utils/random_state.py +24 -0
  386. physicskit/rmt/utils/tridiagonal.py +167 -0
  387. physicskit/rmt/validation/__init__.py +36 -0
  388. physicskit/rmt/validation/base.py +126 -0
  389. physicskit/rmt/validation/circular_law.py +80 -0
  390. physicskit/rmt/validation/marchenko_pastur.py +53 -0
  391. physicskit/rmt/validation/ratio_distribution.py +53 -0
  392. physicskit/rmt/validation/real_ginibre.py +60 -0
  393. physicskit/rmt/validation/sine_kernel.py +57 -0
  394. physicskit/rmt/validation/single_ring.py +68 -0
  395. physicskit/rmt/validation/tracy_widom.py +89 -0
  396. physicskit/rmt/validation/universality.py +100 -0
  397. physicskit/rmt/validation/wachter.py +52 -0
  398. physicskit/rmt/validation/wigner_semicircle.py +40 -0
  399. physicskit/rmt/validation/wigner_surmise.py +58 -0
  400. physicskit/semiclassical/__init__.py +94 -0
  401. physicskit/semiclassical/_compat.py +5 -0
  402. physicskit/semiclassical/core/__init__.py +41 -0
  403. physicskit/semiclassical/core/gutzwiller.py +215 -0
  404. physicskit/semiclassical/core/path_integral.py +594 -0
  405. physicskit/semiclassical/core/propagators.py +579 -0
  406. physicskit/semiclassical/core/wkb.py +308 -0
  407. physicskit/semiclassical/systems/__init__.py +13 -0
  408. physicskit/semiclassical/systems/scarring.py +278 -0
  409. physicskit/semiclassical/tests/__init__.py +0 -0
  410. physicskit/semiclassical/tests/test_gutzwiller.py +35 -0
  411. physicskit/semiclassical/tests/test_path_integral.py +194 -0
  412. physicskit/semiclassical/tests/test_propagators.py +82 -0
  413. physicskit/semiclassical/tests/test_scarring.py +43 -0
  414. physicskit/semiclassical/tests/test_visualizers.py +89 -0
  415. physicskit/semiclassical/tests/test_wkb.py +30 -0
  416. physicskit/semiclassical/visualizers/__init__.py +17 -0
  417. physicskit/semiclassical/visualizers/gutzwiller.py +55 -0
  418. physicskit/semiclassical/visualizers/path_integral.py +195 -0
  419. physicskit/semiclassical/visualizers/propagators.py +89 -0
  420. physicskit/semiclassical/visualizers/scarring.py +146 -0
  421. physicskit/semiclassical/visualizers/wkb.py +55 -0
  422. physicskit/statphys/__init__.py +80 -0
  423. physicskit/statphys/chapters/__init__.py +43 -0
  424. physicskit/statphys/chapters/ehrenfest_urn.py +112 -0
  425. physicskit/statphys/chapters/ising_lattice.py +431 -0
  426. physicskit/statphys/chapters/kpz_growth.py +129 -0
  427. physicskit/statphys/chapters/molecular_dynamics.py +258 -0
  428. physicskit/statphys/chapters/nonequilibrium_work.py +146 -0
  429. physicskit/statphys/chapters/percolation.py +305 -0
  430. physicskit/statphys/chapters/random_walk.py +142 -0
  431. physicskit/statphys/chapters/renormalization.py +148 -0
  432. physicskit/statphys/chapters/sandpile.py +109 -0
  433. physicskit/statphys/chapters/spin_glass.py +275 -0
  434. physicskit/statphys/core/__init__.py +10 -0
  435. physicskit/statphys/core/kpz_engine.py +53 -0
  436. physicskit/statphys/core/md_engine.py +157 -0
  437. physicskit/statphys/core/monte_carlo.py +462 -0
  438. physicskit/statphys/core/random_walk_engine.py +68 -0
  439. physicskit/statphys/core/sandpile_engine.py +52 -0
  440. physicskit/statphys/tests/__init__.py +0 -0
  441. physicskit/statphys/tests/test_dynamics.py +66 -0
  442. physicskit/statphys/tests/test_ehrenfest_urn.py +44 -0
  443. physicskit/statphys/tests/test_finite_size_scaling.py +62 -0
  444. physicskit/statphys/tests/test_interactive.py +33 -0
  445. physicskit/statphys/tests/test_ising.py +68 -0
  446. physicskit/statphys/tests/test_kpz.py +55 -0
  447. physicskit/statphys/tests/test_landau_theory.py +49 -0
  448. physicskit/statphys/tests/test_md_engine.py +31 -0
  449. physicskit/statphys/tests/test_molecular_dynamics.py +72 -0
  450. physicskit/statphys/tests/test_nonequilibrium_work.py +33 -0
  451. physicskit/statphys/tests/test_partition_function.py +26 -0
  452. physicskit/statphys/tests/test_percolation.py +116 -0
  453. physicskit/statphys/tests/test_potts_model.py +46 -0
  454. physicskit/statphys/tests/test_random_walk.py +50 -0
  455. physicskit/statphys/tests/test_renormalization.py +44 -0
  456. physicskit/statphys/tests/test_sandpile.py +44 -0
  457. physicskit/statphys/tests/test_spin_glass.py +73 -0
  458. physicskit/statphys/tests/test_thermodynamics.py +121 -0
  459. physicskit/statphys/tests/test_xy_model.py +45 -0
  460. physicskit/statphys/utils/__init__.py +1 -0
  461. physicskit/statphys/utils/dynamics.py +100 -0
  462. physicskit/statphys/utils/finite_size_scaling.py +171 -0
  463. physicskit/statphys/utils/landau_theory.py +151 -0
  464. physicskit/statphys/utils/partition_function.py +109 -0
  465. physicskit/statphys/utils/thermodynamics.py +356 -0
  466. physicskit/statphys/visualizers/__init__.py +87 -0
  467. physicskit/statphys/visualizers/interactive.py +161 -0
  468. physicskit/statphys/visualizers/jarzynski_render.py +44 -0
  469. physicskit/statphys/visualizers/kpz_render.py +65 -0
  470. physicskit/statphys/visualizers/lattice_render.py +212 -0
  471. physicskit/statphys/visualizers/particle_render.py +121 -0
  472. physicskit/statphys/visualizers/random_walk_render.py +106 -0
  473. physicskit/statphys/visualizers/rg_render.py +45 -0
  474. physicskit/statphys/visualizers/sandpile_render.py +65 -0
  475. physicskit/statphys/visualizers/spin_glass_render.py +40 -0
  476. physicskit/statphys/visualizers/urn_render.py +38 -0
  477. physicskit/statphys/visualizers/vortex_render.py +84 -0
  478. physicskit/tests/__init__.py +0 -0
  479. physicskit/tests/test_constants.py +38 -0
  480. physicskit-0.1.0.dist-info/METADATA +196 -0
  481. physicskit-0.1.0.dist-info/RECORD +484 -0
  482. physicskit-0.1.0.dist-info/WHEEL +5 -0
  483. physicskit-0.1.0.dist-info/licenses/LICENSE +21 -0
  484. physicskit-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,628 @@
1
+ """Plotting helpers: N-body trajectories, Lane-Emden profiles, and rotation curves.
2
+
3
+ Matplotlib is used throughout. Every function returns its figure object
4
+ rather than calling ``show()``, so it composes cleanly into larger
5
+ figures or headless pipelines.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import matplotlib.colors as mcolors
11
+ import matplotlib.pyplot as plt
12
+ import numpy as np
13
+ from matplotlib.animation import FuncAnimation
14
+ from matplotlib.collections import LineCollection
15
+
16
+ from .cosmic_web import zeldovich_position
17
+
18
+ __all__ = [
19
+ "plot_nbody_trajectories",
20
+ "plot_lane_emden",
21
+ "plot_rotation_curve",
22
+ "animate_nbody_trajectories",
23
+ "animate_zeldovich_collapse",
24
+ "plot_zeldovich_snapshot",
25
+ "animate_stellar_convection",
26
+ "animate_dynamo_wave",
27
+ "plot_dynamo_butterfly_diagram",
28
+ ]
29
+
30
+
31
+ def plot_nbody_trajectories(history, ax=None):
32
+ """Plot the (x, y) trajectories of every body in an N-body simulation.
33
+
34
+ Parameters
35
+ ----------
36
+ history : ndarray of shape (n_steps + 1, N, 3)
37
+ Position history, e.g. from
38
+ :meth:`physicskit.astro.nbody.NBodySystem.simulate`.
39
+ ax : matplotlib.axes.Axes, optional
40
+ Axes to draw into; a new figure is created if omitted.
41
+
42
+ Returns
43
+ -------
44
+ fig : matplotlib.figure.Figure
45
+ ax : matplotlib.axes.Axes
46
+
47
+ Examples
48
+ --------
49
+ >>> import numpy as np
50
+ >>> from physicskit.astro.nbody import NBodySystem
51
+ >>> pos = np.array([[1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]])
52
+ >>> vel = np.array([[0.0, 0.5, 0.0], [0.0, -0.5, 0.0]])
53
+ >>> system = NBodySystem(pos, vel, np.array([1.0, 1.0]))
54
+ >>> history = system.simulate(dt=0.01, n_steps=50)
55
+ >>> fig, ax = plot_nbody_trajectories(history)
56
+ >>> isinstance(fig, plt.Figure)
57
+ True
58
+ """
59
+ if ax is None:
60
+ fig, ax = plt.subplots()
61
+ else:
62
+ fig = ax.figure
63
+ n_bodies = history.shape[1]
64
+ for b in range(n_bodies):
65
+ ax.plot(history[:, b, 0], history[:, b, 1], label=f"body {b + 1}")
66
+ ax.set_xlabel("x")
67
+ ax.set_ylabel("y")
68
+ ax.set_aspect("equal", adjustable="datalim")
69
+ ax.legend()
70
+ return fig, ax
71
+
72
+
73
+ def plot_lane_emden(xi, theta, ax=None):
74
+ r"""Plot the Lane-Emden function :math:`\theta(\xi)`.
75
+
76
+ Parameters
77
+ ----------
78
+ xi, theta : ndarray
79
+ From :func:`physicskit.astro.stellar_structure.lane_emden`.
80
+ ax : matplotlib.axes.Axes, optional
81
+ Axes to draw into; a new figure is created if omitted.
82
+
83
+ Returns
84
+ -------
85
+ fig : matplotlib.figure.Figure
86
+ ax : matplotlib.axes.Axes
87
+
88
+ Examples
89
+ --------
90
+ >>> from physicskit.astro.stellar_structure import lane_emden
91
+ >>> xi, theta = lane_emden(1.5)
92
+ >>> fig, ax = plot_lane_emden(xi, theta)
93
+ >>> isinstance(fig, plt.Figure)
94
+ True
95
+ """
96
+ if ax is None:
97
+ fig, ax = plt.subplots()
98
+ else:
99
+ fig = ax.figure
100
+ ax.plot(xi, theta)
101
+ ax.axhline(0.0, color="k", linewidth=0.5)
102
+ ax.scatter([xi[-1]], [theta[-1]], color="C1", zorder=3, label="surface")
103
+ ax.set_xlabel(r"$\xi$")
104
+ ax.set_ylabel(r"$\theta(\xi)$")
105
+ ax.legend()
106
+ return fig, ax
107
+
108
+
109
+ def plot_rotation_curve(r, v_model, ax=None, v_observed=None):
110
+ """Plot a galactic rotation curve, optionally overlaid with observed data.
111
+
112
+ Parameters
113
+ ----------
114
+ r : ndarray
115
+ Radii.
116
+ v_model : ndarray
117
+ Model circular velocity, e.g. from
118
+ :func:`physicskit.astro.galactic_dynamics.circular_velocity`.
119
+ ax : matplotlib.axes.Axes, optional
120
+ Axes to draw into; a new figure is created if omitted.
121
+ v_observed : ndarray, optional
122
+ Observed velocities to overlay as points.
123
+
124
+ Returns
125
+ -------
126
+ fig : matplotlib.figure.Figure
127
+ ax : matplotlib.axes.Axes
128
+
129
+ Examples
130
+ --------
131
+ >>> import numpy as np
132
+ >>> r = np.linspace(1, 20, 30)
133
+ >>> v = np.sqrt(1.0 / r)
134
+ >>> fig, ax = plot_rotation_curve(r, v)
135
+ >>> isinstance(fig, plt.Figure)
136
+ True
137
+ """
138
+ if ax is None:
139
+ fig, ax = plt.subplots()
140
+ else:
141
+ fig = ax.figure
142
+ ax.plot(r, v_model, label="model")
143
+ if v_observed is not None:
144
+ ax.scatter(r, v_observed, color="C1", s=15, label="observed")
145
+ ax.set_xlabel("r")
146
+ ax.set_ylabel(r"$v_c(r)$")
147
+ ax.legend()
148
+ return fig, ax
149
+
150
+
151
+ def animate_nbody_trajectories(history, interval: int = 30, trail: int = 200, skip: int = 1, colors=None, title: str | None = None):
152
+ """Animate an N-body simulation's real-space trajectories being traced out.
153
+
154
+ Draws each body's ``(x, y)`` path (the ``z`` component, if any, is
155
+ ignored) with a fading trail -- older trail segments are more
156
+ transparent -- and a bright marker at the body's current position, in
157
+ a distinct color per body.
158
+
159
+ Parameters
160
+ ----------
161
+ history : ndarray of shape (n_steps + 1, N, 3)
162
+ Position history, e.g. from :meth:`physicskit.astro.nbody.NBodySystem.simulate`.
163
+ interval : int, default 30
164
+ Delay between animation frames, in milliseconds.
165
+ trail : int, default 200
166
+ Number of most-recent steps kept visible as each body's trail.
167
+ skip : int, default 1
168
+ Number of simulation steps advanced per animation frame; increase
169
+ for long simulations so the animation covers them in a reasonable
170
+ number of frames.
171
+ colors : list, optional
172
+ Per-body colors; a `tab10` sweep is used if omitted.
173
+ title : str, optional
174
+ Axes title.
175
+
176
+ Returns
177
+ -------
178
+ matplotlib.animation.FuncAnimation
179
+ Assign it to a variable to keep it alive, and display it with
180
+ ``plt.show()`` or save it with ``anim.save(...)``.
181
+
182
+ Examples
183
+ --------
184
+ >>> from physicskit.astro.nbody import NBodySystem, figure_eight_initial_conditions
185
+ >>> pos, vel, masses = figure_eight_initial_conditions()
186
+ >>> system = NBodySystem(pos, vel, masses)
187
+ >>> history = system.simulate(dt=0.002, n_steps=200)
188
+ >>> anim = animate_nbody_trajectories(history)
189
+ >>> anim.__class__.__name__
190
+ 'FuncAnimation'
191
+ """
192
+ history = np.asarray(history, dtype=np.float64)
193
+ n_steps_plus1, n_bodies, _ = history.shape
194
+ xy = history[:, :, :2]
195
+
196
+ if colors is None:
197
+ cmap = plt.get_cmap("tab10")
198
+ colors = [cmap(i) for i in range(n_bodies)]
199
+ base_rgba = [np.array(mcolors.to_rgba(c)) for c in colors]
200
+
201
+ fig, ax = plt.subplots(figsize=(6.5, 6.5))
202
+ pad = 0.1 * (np.abs(xy).max() + 1e-12)
203
+ ax.set_xlim(xy[..., 0].min() - pad, xy[..., 0].max() + pad)
204
+ ax.set_ylim(xy[..., 1].min() - pad, xy[..., 1].max() + pad)
205
+ ax.set_aspect("equal")
206
+ if title:
207
+ ax.set_title(title)
208
+
209
+ trail_collections = []
210
+ markers = []
211
+ for b in range(n_bodies):
212
+ lc = LineCollection([], colors=[base_rgba[b]], linewidths=1.5)
213
+ ax.add_collection(lc)
214
+ trail_collections.append(lc)
215
+ (marker,) = ax.plot([], [], "o", color=colors[b], markersize=8, label=f"body {b + 1}")
216
+ markers.append(marker)
217
+ ax.legend(loc="upper right", fontsize=8)
218
+
219
+ frame_ends = np.arange(skip, n_steps_plus1 + skip, skip)
220
+ frame_ends[-1] = n_steps_plus1
221
+
222
+ def update(frame: int):
223
+ end = int(frame_ends[frame])
224
+ lo = max(0, end - trail)
225
+ artists = []
226
+ for b in range(n_bodies):
227
+ pts = xy[lo:end, b, :]
228
+ if pts.shape[0] >= 2:
229
+ segments = np.stack([pts[:-1], pts[1:]], axis=1)
230
+ n_seg = segments.shape[0]
231
+ seg_colors = np.tile(base_rgba[b], (n_seg, 1))
232
+ seg_colors[:, 3] = np.linspace(0.05, 1.0, n_seg)
233
+ trail_collections[b].set_segments(segments)
234
+ trail_collections[b].set_color(seg_colors)
235
+ else:
236
+ trail_collections[b].set_segments([])
237
+ markers[b].set_data([xy[end - 1, b, 0]], [xy[end - 1, b, 1]])
238
+ artists += [trail_collections[b], markers[b]]
239
+ return artists
240
+
241
+ anim = FuncAnimation(fig, update, frames=len(frame_ends), interval=interval, blit=False)
242
+ return anim
243
+
244
+
245
+ def _local_density_on_grid(xy, x_edges, y_edges):
246
+ """Local point-density proxy: the 2D-histogram bin count each point of
247
+ ``xy`` falls into, evaluated against a shared, precomputed set of bin
248
+ edges so densities are comparable across an animation's frames.
249
+
250
+ Chosen over a KD-tree nearest-neighbor density estimate (e.g.
251
+ ``scipy.spatial.cKDTree``, used elsewhere in this codebase) for
252
+ :func:`animate_zeldovich_collapse` and :func:`plot_zeldovich_snapshot`
253
+ because it needs no tree queries, no per-particle neighbor-count
254
+ hyperparameter, and directly reflects the same coarse-grained
255
+ overdensity -- particles piling up into the same small region of space
256
+ -- that the eye picks out in the scatter plot as filaments and nodes.
257
+ """
258
+ counts, _, _ = np.histogram2d(xy[:, 0], xy[:, 1], bins=[x_edges, y_edges])
259
+ n_bins_x = len(x_edges) - 1
260
+ n_bins_y = len(y_edges) - 1
261
+ ix = np.clip(np.digitize(xy[:, 0], x_edges) - 1, 0, n_bins_x - 1)
262
+ iy = np.clip(np.digitize(xy[:, 1], y_edges) - 1, 0, n_bins_y - 1)
263
+ return counts[ix, iy]
264
+
265
+
266
+ def animate_zeldovich_collapse(q, D_values, k_vectors, amplitudes, phases, interval=80, s=2):
267
+ r"""Animate the Zel'dovich approximation's collapse of a Lagrangian grid into the cosmic web.
268
+
269
+ Shows a scatter plot of :func:`physicskit.astro.cosmic_web.zeldovich_position`
270
+ evaluated at each growth factor in ``D_values``, frame by frame -- the
271
+ initially regular grid of tracer particles progressively streaming
272
+ together into filaments, sheets ("pancakes"), and dense nodes at
273
+ filament intersections. Points are colored by a local point-density
274
+ proxy (see :func:`_local_density_on_grid`): a fixed 2D histogram of the
275
+ particle positions, shared across all frames, so density colors are
276
+ directly comparable as structure grows in from D_values[0] to
277
+ D_values[-1].
278
+
279
+ Parameters
280
+ ----------
281
+ q : ndarray, shape (n_particles, 2)
282
+ Lagrangian tracer positions, e.g. from
283
+ :func:`physicskit.astro.cosmic_web.lagrangian_grid`.
284
+ D_values : array_like
285
+ Growth-factor values to animate through, one frame each.
286
+ k_vectors : ndarray, shape (n_modes, 2)
287
+ amplitudes : ndarray, shape (n_modes,)
288
+ phases : ndarray, shape (n_modes,)
289
+ Displacement-potential parameters, e.g. from
290
+ :func:`physicskit.astro.cosmic_web.random_displacement_potential`.
291
+ interval : int, default=80
292
+ Delay between animation frames, in milliseconds.
293
+ s : float, default=2
294
+ Marker size.
295
+
296
+ Returns
297
+ -------
298
+ matplotlib.animation.FuncAnimation
299
+ Assign it to a variable to keep it alive, and display it with
300
+ ``plt.show()`` or save it with ``anim.save(...)``.
301
+
302
+ See Also
303
+ --------
304
+ plot_zeldovich_snapshot : The single-frame, non-animated companion.
305
+
306
+ Examples
307
+ --------
308
+ >>> import numpy as np
309
+ >>> from physicskit.astro.cosmic_web import lagrangian_grid, random_displacement_potential, first_caustic_time
310
+ >>> q = lagrangian_grid(20, 1.0)
311
+ >>> k_vectors, amplitudes, phases = random_displacement_potential(6, k_min=2 * np.pi, k_max=6 * np.pi, amplitude_scale=0.02, seed=0)
312
+ >>> D_collapse = first_caustic_time(q, k_vectors, amplitudes, phases)
313
+ >>> D_values = np.linspace(0.0, 1.2 * D_collapse, 10)
314
+ >>> anim = animate_zeldovich_collapse(q, D_values, k_vectors, amplitudes, phases)
315
+ >>> anim.__class__.__name__
316
+ 'FuncAnimation'
317
+ """
318
+ q = np.atleast_2d(np.asarray(q, dtype=float))
319
+ D_values = np.asarray(D_values, dtype=float)
320
+ n_frames = D_values.shape[0]
321
+ n_particles = q.shape[0]
322
+
323
+ positions = np.empty((n_frames, n_particles, 2))
324
+ for i, D in enumerate(D_values):
325
+ positions[i] = zeldovich_position(q, D, k_vectors, amplitudes, phases)
326
+
327
+ x_min, x_max = positions[..., 0].min(), positions[..., 0].max()
328
+ y_min, y_max = positions[..., 1].min(), positions[..., 1].max()
329
+ pad_x = 0.03 * (x_max - x_min + 1e-12)
330
+ pad_y = 0.03 * (y_max - y_min + 1e-12)
331
+ x_min, x_max = x_min - pad_x, x_max + pad_x
332
+ y_min, y_max = y_min - pad_y, y_max + pad_y
333
+
334
+ n_bins = max(20, int(np.sqrt(n_particles)))
335
+ x_edges = np.linspace(x_min, x_max, n_bins + 1)
336
+ y_edges = np.linspace(y_min, y_max, n_bins + 1)
337
+
338
+ log_density = np.empty((n_frames, n_particles))
339
+ for i in range(n_frames):
340
+ log_density[i] = np.log10(_local_density_on_grid(positions[i], x_edges, y_edges) + 1.0)
341
+ vmax = max(float(log_density.max()), 1e-12)
342
+
343
+ fig, ax = plt.subplots(figsize=(6.5, 6.5))
344
+ ax.set_xlim(x_min, x_max)
345
+ ax.set_ylim(y_min, y_max)
346
+ ax.set_aspect("equal")
347
+ ax.set_xlabel("x")
348
+ ax.set_ylabel("y")
349
+
350
+ scatter = ax.scatter(positions[0, :, 0], positions[0, :, 1], c=log_density[0], cmap="inferno", s=s, vmin=0.0, vmax=vmax)
351
+ title = ax.set_title(f"D = {D_values[0]:.4f}")
352
+ fig.colorbar(scatter, ax=ax, label=r"local density (log$_{10}$ scale)")
353
+
354
+ def update(frame):
355
+ scatter.set_offsets(positions[frame])
356
+ scatter.set_array(log_density[frame])
357
+ title.set_text(f"D = {D_values[frame]:.4f}")
358
+ return scatter, title
359
+
360
+ anim = FuncAnimation(fig, update, frames=n_frames, interval=interval, blit=False)
361
+ return anim
362
+
363
+
364
+ def plot_zeldovich_snapshot(q, D, k_vectors, amplitudes, phases, ax=None, s=2):
365
+ r"""A single static snapshot of the Zel'dovich-evolved particle field at one growth factor.
366
+
367
+ The non-animated companion to :func:`animate_zeldovich_collapse`,
368
+ using the same 2D-histogram local-density coloring.
369
+
370
+ Parameters
371
+ ----------
372
+ q : ndarray, shape (n_particles, 2)
373
+ Lagrangian tracer positions, e.g. from
374
+ :func:`physicskit.astro.cosmic_web.lagrangian_grid`.
375
+ D : float
376
+ Growth factor at which to evaluate the Zel'dovich mapping.
377
+ k_vectors : ndarray, shape (n_modes, 2)
378
+ amplitudes : ndarray, shape (n_modes,)
379
+ phases : ndarray, shape (n_modes,)
380
+ Displacement-potential parameters, e.g. from
381
+ :func:`physicskit.astro.cosmic_web.random_displacement_potential`.
382
+ ax : matplotlib.axes.Axes, optional
383
+ Axes to draw into; a new figure is created if omitted.
384
+ s : float, default=2
385
+ Marker size.
386
+
387
+ Returns
388
+ -------
389
+ fig : matplotlib.figure.Figure
390
+ ax : matplotlib.axes.Axes
391
+
392
+ See Also
393
+ --------
394
+ animate_zeldovich_collapse : The animated version of this snapshot.
395
+
396
+ Examples
397
+ --------
398
+ >>> import numpy as np
399
+ >>> from physicskit.astro.cosmic_web import lagrangian_grid, random_displacement_potential, first_caustic_time
400
+ >>> q = lagrangian_grid(20, 1.0)
401
+ >>> k_vectors, amplitudes, phases = random_displacement_potential(6, k_min=2 * np.pi, k_max=6 * np.pi, amplitude_scale=0.02, seed=0)
402
+ >>> D_collapse = first_caustic_time(q, k_vectors, amplitudes, phases)
403
+ >>> fig, ax = plot_zeldovich_snapshot(q, D_collapse, k_vectors, amplitudes, phases)
404
+ >>> isinstance(fig, plt.Figure)
405
+ True
406
+ """
407
+ q = np.atleast_2d(np.asarray(q, dtype=float))
408
+ x = zeldovich_position(q, D, k_vectors, amplitudes, phases)
409
+ n_particles = x.shape[0]
410
+
411
+ x_min, x_max = x[:, 0].min(), x[:, 0].max()
412
+ y_min, y_max = x[:, 1].min(), x[:, 1].max()
413
+ pad_x = 0.03 * (x_max - x_min + 1e-12)
414
+ pad_y = 0.03 * (y_max - y_min + 1e-12)
415
+ x_edges = np.linspace(x_min - pad_x, x_max + pad_x, max(20, int(np.sqrt(n_particles))) + 1)
416
+ y_edges = np.linspace(y_min - pad_y, y_max + pad_y, max(20, int(np.sqrt(n_particles))) + 1)
417
+
418
+ log_density = np.log10(_local_density_on_grid(x, x_edges, y_edges) + 1.0)
419
+
420
+ if ax is None:
421
+ fig, ax = plt.subplots(figsize=(6.5, 6.5))
422
+ else:
423
+ fig = ax.figure
424
+ scatter = ax.scatter(x[:, 0], x[:, 1], c=log_density, cmap="inferno", s=s)
425
+ fig.colorbar(scatter, ax=ax, label=r"local density (log$_{10}$ scale)")
426
+ ax.set_xlabel("x")
427
+ ax.set_ylabel("y")
428
+ ax.set_aspect("equal", adjustable="datalim")
429
+ ax.set_title(f"D = {D:.4f}")
430
+ return fig, ax
431
+
432
+
433
+ def animate_stellar_convection(times, omega_snapshots, T_snapshots, interval=80):
434
+ """Animate 2D convective rolls: vorticity and temperature side by side.
435
+
436
+ Two panels sharing a time axis -- vorticity on the left, temperature
437
+ perturbation on the right -- each redrawn frame by frame from
438
+ :func:`physicskit.astro.stellar_dynamo.simulate_stellar_convection`'s
439
+ output, showing the small initial noise roll up into churning
440
+ convective plumes.
441
+
442
+ Parameters
443
+ ----------
444
+ times : ndarray, shape (n_saved,)
445
+ omega_snapshots : ndarray, shape (n_saved, ny, nx)
446
+ Vorticity field snapshots.
447
+ T_snapshots : ndarray, shape (n_saved, ny, nx)
448
+ Temperature-perturbation field snapshots.
449
+ interval : int, default=80
450
+ Delay between animation frames, in milliseconds.
451
+
452
+ Returns
453
+ -------
454
+ matplotlib.animation.FuncAnimation
455
+ Assign it to a variable to keep it alive, and display it with
456
+ ``plt.show()`` or save it with ``anim.save(...)``.
457
+
458
+ Examples
459
+ --------
460
+ >>> import numpy as np
461
+ >>> from physicskit.astro.stellar_dynamo import simulate_stellar_convection
462
+ >>> times, omega_snaps, T_snaps = simulate_stellar_convection(
463
+ ... 24, 24, 2 * np.pi, 2 * np.pi, n_steps=20, save_every=10, seed=0)
464
+ >>> anim = animate_stellar_convection(times, omega_snaps, T_snaps)
465
+ >>> anim.__class__.__name__
466
+ 'FuncAnimation'
467
+ """
468
+ omega_snapshots = np.asarray(omega_snapshots, dtype=np.float64)
469
+ T_snapshots = np.asarray(T_snapshots, dtype=np.float64)
470
+ times = np.asarray(times, dtype=np.float64)
471
+
472
+ omega_max = np.abs(omega_snapshots).max() + 1e-12
473
+ T_max = np.abs(T_snapshots).max() + 1e-12
474
+
475
+ fig, (ax_omega, ax_T) = plt.subplots(1, 2, figsize=(11, 5))
476
+ im_omega = ax_omega.imshow(omega_snapshots[0], origin="lower", cmap="RdBu_r", vmin=-omega_max, vmax=omega_max, aspect="auto")
477
+ im_T = ax_T.imshow(T_snapshots[0], origin="lower", cmap="inferno", vmin=-T_max, vmax=T_max, aspect="auto")
478
+ ax_omega.set_title("vorticity $\\omega$")
479
+ ax_T.set_title("temperature perturbation $T'$")
480
+ for ax in (ax_omega, ax_T):
481
+ ax.set_xlabel("x")
482
+ ax.set_ylabel("y")
483
+ fig.colorbar(im_omega, ax=ax_omega, fraction=0.046)
484
+ fig.colorbar(im_T, ax=ax_T, fraction=0.046)
485
+ suptitle = fig.suptitle(f"t = {times[0]:.3f}")
486
+ fig.tight_layout()
487
+
488
+ def update(frame):
489
+ im_omega.set_data(omega_snapshots[frame])
490
+ im_T.set_data(T_snapshots[frame])
491
+ suptitle.set_text(f"t = {times[frame]:.3f}")
492
+ return im_omega, im_T, suptitle
493
+
494
+ anim = FuncAnimation(fig, update, frames=omega_snapshots.shape[0], interval=interval, blit=False)
495
+ return anim
496
+
497
+
498
+ def animate_dynamo_wave(times, A_snapshots, B_snapshots, x, interval=80):
499
+ """Animate the alpha-omega dynamo's poloidal and toroidal fields as traveling, growing waves.
500
+
501
+ Draws :math:`A(x)` and :math:`B(x)` as two line plots sharing an
502
+ axis, redrawn frame by frame from
503
+ :func:`physicskit.astro.stellar_dynamo.simulate_alpha_omega_dynamo`'s
504
+ output. In the unstable/growing regime, both the growing amplitude
505
+ and the lateral migration of the wave pattern across `x` -- the
506
+ dynamo wave whose space-time trace is the solar butterfly diagram --
507
+ are visible as the animation runs; the y-axis is rescaled each frame
508
+ to the current amplitude so the growing wave doesn't run off scale.
509
+
510
+ Parameters
511
+ ----------
512
+ times : ndarray, shape (n_saved,)
513
+ A_snapshots, B_snapshots : ndarray, shape (n_saved, nx)
514
+ Poloidal-flux-proxy and toroidal-field snapshots.
515
+ x : ndarray, shape (nx,)
516
+ Spatial grid the snapshots live on.
517
+ interval : int, default=80
518
+ Delay between animation frames, in milliseconds.
519
+
520
+ Returns
521
+ -------
522
+ matplotlib.animation.FuncAnimation
523
+ Assign it to a variable to keep it alive, and display it with
524
+ ``plt.show()`` or save it with ``anim.save(...)``.
525
+
526
+ See Also
527
+ --------
528
+ plot_dynamo_butterfly_diagram : The static space-time summary of the same wave.
529
+
530
+ Examples
531
+ --------
532
+ >>> import numpy as np
533
+ >>> from physicskit.astro.stellar_dynamo import simulate_alpha_omega_dynamo
534
+ >>> Lx = 2 * np.pi
535
+ >>> x = np.linspace(0, Lx, 32, endpoint=False)
536
+ >>> A0 = 1e-3 * np.cos(x)
537
+ >>> B0 = np.zeros_like(A0)
538
+ >>> times, A_snaps, B_snaps = simulate_alpha_omega_dynamo(A0, B0, alpha=1.0, shear=5.0, eta=0.05, Lx=Lx, dt=0.01, n_steps=20, save_every=5)
539
+ >>> anim = animate_dynamo_wave(times, A_snaps, B_snaps, x)
540
+ >>> anim.__class__.__name__
541
+ 'FuncAnimation'
542
+ """
543
+ times = np.asarray(times, dtype=np.float64)
544
+ A_snapshots = np.asarray(A_snapshots, dtype=np.float64)
545
+ B_snapshots = np.asarray(B_snapshots, dtype=np.float64)
546
+ x = np.asarray(x, dtype=np.float64)
547
+
548
+ fig, ax = plt.subplots(figsize=(7, 4.5))
549
+ (line_A,) = ax.plot(x, A_snapshots[0], label="$A(x)$ (poloidal-flux proxy)")
550
+ (line_B,) = ax.plot(x, B_snapshots[0], label="$B(x)$ (toroidal field)")
551
+ ax.set_xlabel("x (latitude/radius proxy)")
552
+ ax.set_ylabel("field amplitude")
553
+ ax.set_xlim(x.min(), x.max())
554
+ ax.legend(loc="upper right")
555
+ title = ax.set_title(f"t = {times[0]:.3f}")
556
+
557
+ def update(frame):
558
+ a, b = A_snapshots[frame], B_snapshots[frame]
559
+ line_A.set_ydata(a)
560
+ line_B.set_ydata(b)
561
+ ymax = max(np.abs(a).max(), np.abs(b).max(), 1e-12) * 1.2
562
+ ax.set_ylim(-ymax, ymax)
563
+ title.set_text(f"t = {times[frame]:.3f}")
564
+ return line_A, line_B, title
565
+
566
+ anim = FuncAnimation(fig, update, frames=A_snapshots.shape[0], interval=interval, blit=False)
567
+ return anim
568
+
569
+
570
+ def plot_dynamo_butterfly_diagram(times, B_snapshots, x, ax=None):
571
+ """Static space-time (Hovmoller) plot of the alpha-omega dynamo wave: the "butterfly diagram".
572
+
573
+ Displays :math:`B(x,t)` as an image with time along the x-axis and
574
+ the spatial coordinate `x` (standing in for stellar latitude) along
575
+ the y-axis. In the unstable regime, the migrating dynamo wave shows
576
+ up as diagonal stripes of alternating sign drifting across the
577
+ plot -- the same characteristic pattern, and the same underlying
578
+ alpha-omega mechanism, behind the real Sun's sunspot-latitude
579
+ butterfly diagram.
580
+
581
+ Parameters
582
+ ----------
583
+ times : ndarray, shape (n_saved,)
584
+ B_snapshots : ndarray, shape (n_saved, nx)
585
+ Toroidal-field snapshots, e.g. from
586
+ :func:`physicskit.astro.stellar_dynamo.simulate_alpha_omega_dynamo`.
587
+ x : ndarray, shape (nx,)
588
+ Spatial grid the snapshots live on.
589
+ ax : matplotlib.axes.Axes, optional
590
+ Axes to draw into; a new figure is created if omitted.
591
+
592
+ Returns
593
+ -------
594
+ fig : matplotlib.figure.Figure
595
+ ax : matplotlib.axes.Axes
596
+
597
+ See Also
598
+ --------
599
+ animate_dynamo_wave : The animated, time-domain view of the same field.
600
+
601
+ Examples
602
+ --------
603
+ >>> import numpy as np
604
+ >>> from physicskit.astro.stellar_dynamo import simulate_alpha_omega_dynamo
605
+ >>> Lx = 2 * np.pi
606
+ >>> x = np.linspace(0, Lx, 32, endpoint=False)
607
+ >>> A0 = 1e-3 * np.cos(x)
608
+ >>> B0 = np.zeros_like(A0)
609
+ >>> times, A_snaps, B_snaps = simulate_alpha_omega_dynamo(A0, B0, alpha=1.0, shear=5.0, eta=0.05, Lx=Lx, dt=0.01, n_steps=200, save_every=5)
610
+ >>> fig, ax = plot_dynamo_butterfly_diagram(times, B_snaps, x)
611
+ >>> isinstance(fig, plt.Figure)
612
+ True
613
+ """
614
+ times = np.asarray(times, dtype=np.float64)
615
+ B_snapshots = np.asarray(B_snapshots, dtype=np.float64)
616
+ x = np.asarray(x, dtype=np.float64)
617
+
618
+ if ax is None:
619
+ fig, ax = plt.subplots(figsize=(7, 4.5))
620
+ else:
621
+ fig = ax.figure
622
+ vmax = np.abs(B_snapshots).max() + 1e-12
623
+ mesh = ax.pcolormesh(times, x, B_snapshots.T, cmap="RdBu_r", vmin=-vmax, vmax=vmax, shading="auto")
624
+ fig.colorbar(mesh, ax=ax, label="$B(x, t)$")
625
+ ax.set_xlabel("time")
626
+ ax.set_ylabel("x (latitude/radius proxy)")
627
+ ax.set_title("Dynamo wave butterfly diagram")
628
+ return fig, ax
@@ -0,0 +1,55 @@
1
+ """physicskit.chaos: visual analysis and simulation of chaotic dynamical systems and 2D billiards."""
2
+
3
+ from physicskit.chaos.core.base_system import BilliardSystem, DiscreteMap, DynamicalSystem
4
+ from physicskit.chaos.exceptions import ChaoskitError, InvalidParameterError
5
+ from physicskit.chaos.quantum.billiards import QuantumBilliard
6
+ from physicskit.chaos.quantum.maps import QuantumBakersMap, QuantumKickedRotor
7
+ from physicskit.chaos.systems.billiards import (
8
+ BunimovichStadium,
9
+ CircleBilliard,
10
+ EllipseBilliard,
11
+ RectangleBilliard,
12
+ SinaiBilliard,
13
+ TruncatedCircleBilliard,
14
+ )
15
+ from physicskit.chaos.systems.continuous import (
16
+ Chua,
17
+ DoublePendulum,
18
+ Duffing,
19
+ Lorenz,
20
+ MagneticPendulum,
21
+ RestrictedThreeBody,
22
+ Rossler,
23
+ )
24
+ from physicskit.chaos.systems.maps import BakersMap, HenonMap, LogisticMap, StandardMap
25
+
26
+ __version__ = "0.1.0"
27
+
28
+ __all__ = [
29
+ "BakersMap",
30
+ "BilliardSystem",
31
+ "BunimovichStadium",
32
+ "ChaoskitError",
33
+ "Chua",
34
+ "CircleBilliard",
35
+ "DiscreteMap",
36
+ "DoublePendulum",
37
+ "Duffing",
38
+ "DynamicalSystem",
39
+ "EllipseBilliard",
40
+ "HenonMap",
41
+ "InvalidParameterError",
42
+ "LogisticMap",
43
+ "Lorenz",
44
+ "MagneticPendulum",
45
+ "QuantumBakersMap",
46
+ "QuantumBilliard",
47
+ "QuantumKickedRotor",
48
+ "RectangleBilliard",
49
+ "RestrictedThreeBody",
50
+ "Rossler",
51
+ "SinaiBilliard",
52
+ "StandardMap",
53
+ "TruncatedCircleBilliard",
54
+ "__version__",
55
+ ]
@@ -0,0 +1,3 @@
1
+ from physicskit.chaos.core.base_system import BilliardSystem, DiscreteMap, DynamicalSystem
2
+
3
+ __all__ = ["BilliardSystem", "DiscreteMap", "DynamicalSystem"]