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,142 @@
1
+ """Turbulent kinetic energy spectra and the Kolmogorov -5/3 law.
2
+
3
+ A turbulent velocity field is usefully summarized not by its detailed
4
+ pointwise structure but by how its kinetic energy is distributed across
5
+ length scales -- the energy spectrum :math:`E(k)`, defined so that
6
+ :math:`\\int E(k)\\,dk` is the total kinetic energy per unit mass.
7
+ Kolmogorov's 1941 theory predicts a universal power law,
8
+ :math:`E(k)\\propto k^{-5/3}`, in the "inertial range" of scales small
9
+ enough to have forgotten how the turbulence was forced but large enough not
10
+ to feel viscosity yet -- one of the most-tested predictions in all of
11
+ classical physics, and the standard first check that a simulated 2D or 3D
12
+ flow (e.g. the output of
13
+ :class:`physicskit.fluids.systems.navier_stokes.NavierStokes2D`) is
14
+ resolving a genuine turbulent cascade.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import numpy as np
20
+ from numpy.typing import NDArray
21
+
22
+ from physicskit.fluids.exceptions import InvalidParameterError
23
+
24
+ __all__ = ["energy_spectrum", "kolmogorov_reference_slope"]
25
+
26
+
27
+ def energy_spectrum(u: NDArray[np.float64], v: NDArray[np.float64], length: float) -> tuple[NDArray[np.float64], NDArray[np.float64]]:
28
+ """Isotropic (azimuthally averaged) kinetic energy spectrum of a 2D velocity field.
29
+
30
+ Computes :math:`\\hat{u}(\\mathbf{k})` and :math:`\\hat{v}(\\mathbf{k})`
31
+ by FFT, forms the kinetic energy density
32
+ :math:`\\tfrac{1}{2}(|\\hat{u}|^2+|\\hat{v}|^2)` at each wavevector, and
33
+ sums it over the discrete annulus of wavevectors with
34
+ :math:`k \\le |\\mathbf{k}| < k+1` (in grid-index units) to give
35
+ :math:`E(k)`, normalized so that :math:`\\sum_k E(k) \\approx` the
36
+ domain-averaged kinetic energy per unit mass (Parseval's theorem).
37
+
38
+ Parameters
39
+ ----------
40
+ u, v : ndarray of float, shape (n, n)
41
+ Velocity components on a doubly periodic grid, e.g. from
42
+ :meth:`physicskit.fluids.systems.navier_stokes.NavierStokes2D.velocity`.
43
+ length : float
44
+ Physical domain size.
45
+
46
+ Returns
47
+ -------
48
+ k : ndarray of float, shape (n // 2,)
49
+ Wavenumber bins (angular, :math:`2\\pi/\\lambda` convention).
50
+ E : ndarray of float, shape (n // 2,)
51
+ Kinetic energy spectral density at each wavenumber bin.
52
+
53
+ Raises
54
+ ------
55
+ InvalidParameterError
56
+ If `u` and `v` are not the same shape, or are not square.
57
+
58
+ See Also
59
+ --------
60
+ kolmogorov_reference_slope : The -5/3 reference line to compare `E` against.
61
+
62
+ Examples
63
+ --------
64
+ >>> import numpy as np
65
+ >>> n, length = 64, 2 * np.pi
66
+ >>> x = np.linspace(0, length, n, endpoint=False)
67
+ >>> X, Y = np.meshgrid(x, x, indexing="ij")
68
+ >>> u, v = np.sin(Y), np.sin(X) # a single-mode flow
69
+ >>> k, E = energy_spectrum(u, v, length)
70
+ >>> bool(np.argmax(E) == 1) # all the energy sits at the single k=1 mode
71
+ True
72
+ """
73
+ if u.shape != v.shape:
74
+ raise InvalidParameterError("u and v must have the same shape")
75
+ if u.shape[0] != u.shape[1]:
76
+ raise InvalidParameterError("u and v must be square (n, n) arrays")
77
+ n = u.shape[0]
78
+ u_hat = np.fft.fft2(u) / n**2
79
+ v_hat = np.fft.fft2(v) / n**2
80
+ energy_density = 0.5 * (np.abs(u_hat) ** 2 + np.abs(v_hat) ** 2) * n**2
81
+
82
+ kfreq = np.fft.fftfreq(n, d=length / n) * 2.0 * np.pi
83
+ KX, KY = np.meshgrid(kfreq, kfreq, indexing="ij")
84
+ kmag_index = np.round(np.sqrt(KX**2 + KY**2) / (2.0 * np.pi / length)).astype(int)
85
+
86
+ n_bins = n // 2
87
+ E = np.zeros(n_bins)
88
+ for shell in range(n_bins):
89
+ mask = kmag_index == shell
90
+ E[shell] = energy_density[mask].sum()
91
+ k = np.arange(n_bins) * (2.0 * np.pi / length)
92
+ return k, E
93
+
94
+
95
+ def kolmogorov_reference_slope(k: NDArray[np.float64], k0: float, E0: float) -> NDArray[np.float64]:
96
+ """A Kolmogorov :math:`k^{-5/3}` reference line, anchored at one point.
97
+
98
+ Kolmogorov's K41 theory predicts that, in the inertial range, the
99
+ energy spectrum depends only on the wavenumber `k` and the (scale-independent)
100
+ energy dissipation rate, and dimensional analysis alone then fixes the
101
+ power law:
102
+
103
+ .. math::
104
+
105
+ E(k) = E_0 \\left(\\frac{k}{k_0}\\right)^{-5/3}.
106
+
107
+ Plotting this line through one point ``(k0, E0)`` of a measured
108
+ spectrum (see :func:`energy_spectrum`) on log-log axes is the standard
109
+ visual check for an inertial range: a genuine turbulent cascade runs
110
+ parallel to this line over at least a decade of `k`.
111
+
112
+ Parameters
113
+ ----------
114
+ k : ndarray of float
115
+ Wavenumbers at which to evaluate the reference line.
116
+ k0 : float
117
+ Anchor wavenumber; must be positive.
118
+ E0 : float
119
+ Spectral energy density at `k0`.
120
+
121
+ Returns
122
+ -------
123
+ ndarray of float
124
+ Reference spectral density :math:`E_0(k/k_0)^{-5/3}` at each `k`.
125
+
126
+ Raises
127
+ ------
128
+ InvalidParameterError
129
+ If `k0` is not positive.
130
+
131
+ Examples
132
+ --------
133
+ >>> import numpy as np
134
+ >>> k = np.array([1.0, 2.0, 4.0])
135
+ >>> ref = kolmogorov_reference_slope(k, k0=1.0, E0=1.0)
136
+ >>> round(float(ref[1]), 4)
137
+ 0.315
138
+ """
139
+ if k0 <= 0:
140
+ raise InvalidParameterError(f"k0 must be positive, got {k0}")
141
+ k = np.asarray(k, dtype=np.float64)
142
+ return E0 * (k / k0) ** (-5.0 / 3.0)
@@ -0,0 +1,14 @@
1
+ from physicskit.fluids.visualizers import theme
2
+ from physicskit.fluids.visualizers.compressible import plot_shock_tube_profiles
3
+ from physicskit.fluids.visualizers.flow_fields import plot_streamlines, plot_vorticity_field
4
+ from physicskit.fluids.visualizers.potential_flow import plot_pressure_coefficient
5
+ from physicskit.fluids.visualizers.spectra import plot_energy_spectrum
6
+
7
+ __all__ = [
8
+ "plot_energy_spectrum",
9
+ "plot_pressure_coefficient",
10
+ "plot_shock_tube_profiles",
11
+ "plot_streamlines",
12
+ "plot_vorticity_field",
13
+ "theme",
14
+ ]
@@ -0,0 +1,39 @@
1
+ """Shock-tube profile plots."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import matplotlib.pyplot as plt
6
+ import numpy as np
7
+ from matplotlib.figure import Figure
8
+ from numpy.typing import NDArray
9
+
10
+ from physicskit.fluids.visualizers import theme
11
+
12
+ __all__ = ["plot_shock_tube_profiles"]
13
+
14
+
15
+ def plot_shock_tube_profiles(x: NDArray[np.float64], rho: NDArray[np.float64], u: NDArray[np.float64], p: NDArray[np.float64]) -> tuple[Figure, NDArray]:
16
+ """Plot density, velocity, and pressure profiles from a shock-tube solution.
17
+
18
+ Parameters
19
+ ----------
20
+ x : ndarray of float
21
+ Spatial grid.
22
+ rho, u, p : ndarray of float
23
+ Density, velocity, and pressure profiles, e.g. from
24
+ :func:`physicskit.fluids.systems.compressible_flow.sod_shock_tube`.
25
+
26
+ Returns
27
+ -------
28
+ fig : matplotlib.figure.Figure
29
+ axes : ndarray of matplotlib.axes.Axes, shape (3,)
30
+ """
31
+ fig, axes = plt.subplots(3, 1, figsize=(7, 8), sharex=True)
32
+ for ax, field, label in zip(axes, (rho, u, p), (r"$\rho$", "u", "p")):
33
+ ax.plot(x, field, color=theme.PRIMARY, lw=1.2)
34
+ ax.set_ylabel(label)
35
+ ax.grid(alpha=0.3)
36
+ axes[-1].set_xlabel("x")
37
+ fig.suptitle("Sod shock tube")
38
+ fig.tight_layout()
39
+ return fig, axes
@@ -0,0 +1,252 @@
1
+ """Streamline and vorticity-field plots, the workhorse visualizations of this package."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, cast
6
+
7
+ import matplotlib.pyplot as plt
8
+ import numpy as np
9
+ from matplotlib.animation import FuncAnimation
10
+ from matplotlib.axes import Axes
11
+ from matplotlib.figure import Figure
12
+ from numpy.typing import NDArray
13
+
14
+ from physicskit.fluids.systems.instabilities import simulate_kelvin_helmholtz, simulate_rayleigh_taylor
15
+ from physicskit.fluids.visualizers import theme
16
+
17
+ __all__ = ["plot_streamlines", "plot_vorticity_field", "animate_kelvin_helmholtz", "animate_rayleigh_taylor"]
18
+
19
+
20
+ def plot_streamlines(
21
+ X: NDArray[np.float64], Y: NDArray[np.float64], u: NDArray[np.float64], v: NDArray[np.float64], ax: Axes | None = None, **streamplot_kwargs: Any
22
+ ) -> tuple[Figure, Axes]:
23
+ """Plot velocity-field streamlines.
24
+
25
+ Parameters
26
+ ----------
27
+ X, Y : ndarray of float, shape (n, n)
28
+ Real-space coordinate grids.
29
+ u, v : ndarray of float, shape (n, n)
30
+ Velocity components.
31
+ ax : matplotlib.axes.Axes, optional
32
+ Axes to draw into; a new figure is created if omitted.
33
+ **streamplot_kwargs
34
+ Additional keyword arguments forwarded to ``ax.streamplot``.
35
+
36
+ Returns
37
+ -------
38
+ fig : matplotlib.figure.Figure
39
+ ax : matplotlib.axes.Axes
40
+ """
41
+ if ax is None:
42
+ fig, ax = plt.subplots(figsize=(6, 6))
43
+ else:
44
+ fig = cast(Figure, ax.figure)
45
+ kwargs: dict[str, Any] = {"color": theme.STRUCTURE, "linewidth": 0.8, "density": 1.2}
46
+ kwargs.update(streamplot_kwargs)
47
+ ax.streamplot(X.T, Y.T, u.T, v.T, **kwargs)
48
+ ax.set_xlabel("x")
49
+ ax.set_ylabel("y")
50
+ ax.set_aspect("equal")
51
+ return fig, ax
52
+
53
+
54
+ def plot_vorticity_field(
55
+ X: NDArray[np.float64],
56
+ Y: NDArray[np.float64],
57
+ omega: NDArray[np.float64],
58
+ u: NDArray[np.float64] | None = None,
59
+ v: NDArray[np.float64] | None = None,
60
+ ax: Axes | None = None,
61
+ **pcolormesh_kwargs: Any,
62
+ ) -> tuple[Figure, Axes]:
63
+ """Plot a vorticity field as a heatmap, optionally overlaid with velocity streamlines.
64
+
65
+ Parameters
66
+ ----------
67
+ X, Y : ndarray of float, shape (n, n)
68
+ Real-space coordinate grids.
69
+ omega : ndarray of float, shape (n, n)
70
+ Vorticity field.
71
+ u, v : ndarray of float, shape (n, n), optional
72
+ Velocity components; if given, streamlines are overlaid on the heatmap.
73
+ ax : matplotlib.axes.Axes, optional
74
+ Axes to draw into; a new figure is created if omitted.
75
+ **pcolormesh_kwargs
76
+ Additional keyword arguments forwarded to ``ax.pcolormesh``.
77
+
78
+ Returns
79
+ -------
80
+ fig : matplotlib.figure.Figure
81
+ ax : matplotlib.axes.Axes
82
+ """
83
+ if ax is None:
84
+ fig, ax = plt.subplots(figsize=(6, 6))
85
+ else:
86
+ fig = cast(Figure, ax.figure)
87
+ vmax = np.max(np.abs(omega)) or 1.0
88
+ kwargs: dict[str, Any] = {"cmap": theme.VORTICITY_CMAP, "shading": "auto", "vmin": -vmax, "vmax": vmax}
89
+ kwargs.update(pcolormesh_kwargs)
90
+ im = ax.pcolormesh(X, Y, omega, **kwargs)
91
+ fig.colorbar(im, ax=ax, label="vorticity")
92
+ if u is not None and v is not None:
93
+ ax.streamplot(X.T, Y.T, u.T, v.T, color=theme.STRUCTURE, linewidth=0.6, density=1.0)
94
+ ax.set_xlabel("x")
95
+ ax.set_ylabel("y")
96
+ ax.set_aspect("equal")
97
+ return fig, ax
98
+
99
+
100
+ def _animate_vorticity_snapshots(
101
+ X: NDArray[np.float64], Y: NDArray[np.float64], snapshots: list[NDArray[np.float64]], title: str, interval: int, label: str = "vorticity"
102
+ ) -> FuncAnimation:
103
+ """Shared heatmap animator: redraws a vorticity-like (signed, diverging) field over a sequence of snapshots."""
104
+ fig, ax = plt.subplots(figsize=(6, 6))
105
+ vmax = max(float(np.max(np.abs(s))) for s in snapshots) or 1.0
106
+ im = ax.pcolormesh(X, Y, snapshots[0], cmap=theme.VORTICITY_CMAP, shading="auto", vmin=-vmax, vmax=vmax)
107
+ fig.colorbar(im, ax=ax, label=label)
108
+ ax.set_xlabel("x")
109
+ ax.set_ylabel("y")
110
+ ax.set_aspect("equal")
111
+ ax.set_title(title)
112
+
113
+ def update(frame):
114
+ im.set_array(snapshots[frame].ravel())
115
+ return (im,)
116
+
117
+ return FuncAnimation(fig, update, frames=len(snapshots), interval=interval, blit=True)
118
+
119
+
120
+ def animate_kelvin_helmholtz(
121
+ omega0: NDArray[np.float64], nu: float, dt: float, steps_per_frame: int, n_frames: int, length: float, interval: int = 60
122
+ ) -> FuncAnimation:
123
+ """Animate a Kelvin-Helmholtz shear layer rolling up into its characteristic vortex row.
124
+
125
+ Repeatedly calls
126
+ :func:`physicskit.fluids.systems.instabilities.simulate_kelvin_helmholtz`
127
+ for ``steps_per_frame`` RK4 steps at a time, using each call's final
128
+ vorticity as the next call's initial condition, and animates the
129
+ resulting vorticity-field snapshots.
130
+
131
+ Parameters
132
+ ----------
133
+ omega0 : ndarray of float, shape (n, n)
134
+ Initial vorticity field, e.g. from
135
+ :func:`physicskit.fluids.systems.instabilities.kelvin_helmholtz_ic`.
136
+ nu : float
137
+ Kinematic viscosity; must be positive.
138
+ dt : float
139
+ Time step per sub-step.
140
+ steps_per_frame : int
141
+ Number of RK4 steps advanced between animation frames.
142
+ n_frames : int
143
+ Number of animation frames.
144
+ length : float
145
+ Physical domain size.
146
+ interval : int, default=60
147
+ Delay between frames in milliseconds.
148
+
149
+ Returns
150
+ -------
151
+ matplotlib.animation.FuncAnimation
152
+
153
+ See Also
154
+ --------
155
+ physicskit.fluids.systems.instabilities.simulate_kelvin_helmholtz : Supplies the vorticity snapshots animated here.
156
+ animate_rayleigh_taylor : The companion buoyancy-driven instability animator.
157
+
158
+ Examples
159
+ --------
160
+ >>> import numpy as np
161
+ >>> from physicskit.fluids.systems.instabilities import kelvin_helmholtz_ic
162
+ >>> n, length = 64, 2 * np.pi
163
+ >>> omega0 = kelvin_helmholtz_ic(n, length, shear_width=0.1, perturbation_amplitude=0.05)
164
+ >>> anim = animate_kelvin_helmholtz(omega0, nu=0.001, dt=0.0025, steps_per_frame=10, n_frames=4, length=length)
165
+ >>> len(list(anim.new_frame_seq()))
166
+ 4
167
+ """
168
+ n = omega0.shape[0]
169
+ x = np.linspace(0, length, n, endpoint=False)
170
+ X, Y = np.meshgrid(x, x, indexing="ij")
171
+ omega = np.asarray(omega0, dtype=float)
172
+ snapshots = [omega.copy()]
173
+ for _ in range(n_frames - 1):
174
+ result = simulate_kelvin_helmholtz(omega, nu, dt, steps_per_frame, length)
175
+ omega = result["omega"]
176
+ snapshots.append(omega.copy())
177
+ return _animate_vorticity_snapshots(X, Y, snapshots, title="Kelvin-Helmholtz instability", interval=interval)
178
+
179
+
180
+ def animate_rayleigh_taylor(
181
+ omega0: NDArray[np.float64],
182
+ buoyancy0: NDArray[np.float64],
183
+ nu: float,
184
+ kappa: float,
185
+ g: float,
186
+ dt: float,
187
+ steps_per_frame: int,
188
+ n_frames: int,
189
+ length: float,
190
+ interval: int = 60,
191
+ ) -> FuncAnimation:
192
+ """Animate the Rayleigh-Taylor instability's mushroom plumes growing from a rippled density interface.
193
+
194
+ Repeatedly calls
195
+ :func:`physicskit.fluids.systems.instabilities.simulate_rayleigh_taylor`
196
+ for ``steps_per_frame`` RK4 steps at a time, using each call's final
197
+ state as the next call's initial condition, and animates the resulting
198
+ buoyancy-field snapshots (the field in which the rising light plumes
199
+ and falling heavy fingers are most visually distinct).
200
+
201
+ Parameters
202
+ ----------
203
+ omega0, buoyancy0 : ndarray of float, shape (n, n)
204
+ Initial vorticity and buoyancy fields, e.g. from
205
+ :func:`physicskit.fluids.systems.instabilities.rayleigh_taylor_ic`.
206
+ nu : float
207
+ Kinematic viscosity; must be positive.
208
+ kappa : float
209
+ Buoyancy diffusivity; must be positive.
210
+ g : float
211
+ Gravitational acceleration; must be positive.
212
+ dt : float
213
+ Time step per sub-step.
214
+ steps_per_frame : int
215
+ Number of RK4 steps advanced between animation frames.
216
+ n_frames : int
217
+ Number of animation frames.
218
+ length : float
219
+ Physical domain size.
220
+ interval : int, default=60
221
+ Delay between frames in milliseconds.
222
+
223
+ Returns
224
+ -------
225
+ matplotlib.animation.FuncAnimation
226
+
227
+ See Also
228
+ --------
229
+ physicskit.fluids.systems.instabilities.simulate_rayleigh_taylor : Supplies the buoyancy snapshots animated here.
230
+ animate_kelvin_helmholtz : The companion shear-driven instability animator.
231
+
232
+ Examples
233
+ --------
234
+ >>> import numpy as np
235
+ >>> from physicskit.fluids.systems.instabilities import rayleigh_taylor_ic
236
+ >>> n, length = 64, 2 * np.pi
237
+ >>> omega0, buoyancy0 = rayleigh_taylor_ic(n, length, atwood_number=0.3, perturbation_amplitude=0.01)
238
+ >>> anim = animate_rayleigh_taylor(omega0, buoyancy0, nu=0.002, kappa=0.002, g=1.0, dt=0.01, steps_per_frame=10, n_frames=4, length=length)
239
+ >>> len(list(anim.new_frame_seq()))
240
+ 4
241
+ """
242
+ n = omega0.shape[0]
243
+ x = np.linspace(0, length, n, endpoint=False)
244
+ X, Y = np.meshgrid(x, x, indexing="ij")
245
+ omega = np.asarray(omega0, dtype=float)
246
+ buoyancy = np.asarray(buoyancy0, dtype=float)
247
+ snapshots = [buoyancy.copy()]
248
+ for _ in range(n_frames - 1):
249
+ result = simulate_rayleigh_taylor(omega, buoyancy, nu, kappa, g, dt, steps_per_frame, length)
250
+ omega, buoyancy = result["omega"], result["buoyancy"]
251
+ snapshots.append(buoyancy.copy())
252
+ return _animate_vorticity_snapshots(X, Y, snapshots, title="Rayleigh-Taylor instability (buoyancy)", interval=interval, label="buoyancy")
@@ -0,0 +1,51 @@
1
+ """Pressure-coefficient plots for potential flow."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, cast
6
+
7
+ import matplotlib.pyplot as plt
8
+ import numpy as np
9
+ from matplotlib.axes import Axes
10
+ from matplotlib.figure import Figure
11
+ from numpy.typing import NDArray
12
+
13
+ from physicskit.fluids.visualizers import theme
14
+
15
+ __all__ = ["plot_pressure_coefficient"]
16
+
17
+
18
+ def plot_pressure_coefficient(theta: NDArray[np.float64], Cp: NDArray[np.float64], ax: Axes | None = None, **plot_kwargs: Any) -> tuple[Figure, Axes]:
19
+ """Plot the surface pressure coefficient :math:`C_p(\\theta)` around a body.
20
+
21
+ Parameters
22
+ ----------
23
+ theta : ndarray of float
24
+ Angular position around the body (radians), typically ``[0, 2*pi]``.
25
+ Cp : ndarray of float
26
+ Pressure coefficient at each `theta`, e.g. from
27
+ :func:`physicskit.fluids.systems.potential_flow.pressure_coefficient`
28
+ evaluated on a circle.
29
+ ax : matplotlib.axes.Axes, optional
30
+ Axes to draw into; a new figure is created if omitted.
31
+ **plot_kwargs
32
+ Additional keyword arguments forwarded to ``ax.plot``.
33
+
34
+ Returns
35
+ -------
36
+ fig : matplotlib.figure.Figure
37
+ ax : matplotlib.axes.Axes
38
+ """
39
+ if ax is None:
40
+ fig, ax = plt.subplots(figsize=(6, 4))
41
+ else:
42
+ fig = cast(Figure, ax.figure)
43
+ kwargs: dict[str, Any] = {"color": theme.PRIMARY}
44
+ kwargs.update(plot_kwargs)
45
+ ax.plot(np.degrees(theta), Cp, **kwargs)
46
+ ax.axhline(0.0, color=theme.MUTED, lw=0.8, ls="--")
47
+ ax.invert_yaxis()
48
+ ax.set_xlabel(r"$\theta$ (degrees)")
49
+ ax.set_ylabel(r"$C_p$")
50
+ ax.set_title("Surface pressure coefficient")
51
+ return fig, ax
@@ -0,0 +1,62 @@
1
+ """Turbulent energy-spectrum plots."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, cast
6
+
7
+ import matplotlib.pyplot as plt
8
+ import numpy as np
9
+ from matplotlib.axes import Axes
10
+ from matplotlib.figure import Figure
11
+ from numpy.typing import NDArray
12
+
13
+ from physicskit.fluids.utils.spectral_analysis import kolmogorov_reference_slope
14
+ from physicskit.fluids.visualizers import theme
15
+
16
+ __all__ = ["plot_energy_spectrum"]
17
+
18
+
19
+ def plot_energy_spectrum(
20
+ k: NDArray[np.float64], E: NDArray[np.float64], ax: Axes | None = None, show_kolmogorov: bool = True, **plot_kwargs: Any
21
+ ) -> tuple[Figure, Axes]:
22
+ """Log-log plot of a kinetic energy spectrum, with an optional Kolmogorov -5/3 reference line.
23
+
24
+ Parameters
25
+ ----------
26
+ k : ndarray of float
27
+ Wavenumbers, e.g. from :func:`physicskit.fluids.utils.spectral_analysis.energy_spectrum`.
28
+ E : ndarray of float
29
+ Spectral energy density at each `k`.
30
+ ax : matplotlib.axes.Axes, optional
31
+ Axes to draw into; a new figure is created if omitted.
32
+ show_kolmogorov : bool, default True
33
+ If True, overlay a :math:`k^{-5/3}` reference line anchored at the
34
+ lowest plotted (nonzero-energy) wavenumber.
35
+ **plot_kwargs
36
+ Additional keyword arguments forwarded to ``ax.loglog`` for the
37
+ measured spectrum.
38
+
39
+ Returns
40
+ -------
41
+ fig : matplotlib.figure.Figure
42
+ ax : matplotlib.axes.Axes
43
+ """
44
+ if ax is None:
45
+ fig, ax = plt.subplots(figsize=(6, 5))
46
+ else:
47
+ fig = cast(Figure, ax.figure)
48
+ k = np.asarray(k, dtype=np.float64)
49
+ E = np.asarray(E, dtype=np.float64)
50
+ mask = (k > 0) & (E > 0)
51
+ kwargs: dict[str, Any] = {"color": theme.PRIMARY, "marker": "o", "markersize": 3, "label": "E(k)"}
52
+ kwargs.update(plot_kwargs)
53
+ ax.loglog(k[mask], E[mask], **kwargs)
54
+ if show_kolmogorov and np.any(mask):
55
+ k0 = k[mask][0]
56
+ E0 = E[mask][0]
57
+ ax.loglog(k[mask], kolmogorov_reference_slope(k[mask], k0, E0), color=theme.ACCENT, ls="--", label=r"$k^{-5/3}$")
58
+ ax.set_xlabel("k")
59
+ ax.set_ylabel("E(k)")
60
+ ax.set_title("Kinetic energy spectrum")
61
+ ax.legend()
62
+ return fig, ax
@@ -0,0 +1,38 @@
1
+ """Shared color constants for physicskit.fluids's Matplotlib visualizers.
2
+
3
+ Re-exports the same palette :mod:`physicskit.chaos.visualizers.theme` defines,
4
+ so a plot moving between the two packages (e.g. a von Karman street built
5
+ from :mod:`physicskit.fluids.systems.vortex_dynamics` next to a chaotic
6
+ trajectory) reads as one consistent visual language rather than two
7
+ accidentally different ones. Every visualizer still accepts its own
8
+ color/colormap keyword arguments to override these, so nothing here is
9
+ load-bearing.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from physicskit.chaos.visualizers.theme import (
15
+ ACCENT,
16
+ DIVERGING_CMAP,
17
+ MUTED,
18
+ PRIMARY,
19
+ QUALITATIVE_CMAP,
20
+ SEQUENTIAL_CMAP,
21
+ STRUCTURE,
22
+ )
23
+
24
+ __all__ = [
25
+ "PRIMARY",
26
+ "ACCENT",
27
+ "STRUCTURE",
28
+ "MUTED",
29
+ "QUALITATIVE_CMAP",
30
+ "SEQUENTIAL_CMAP",
31
+ "DIVERGING_CMAP",
32
+ "VORTICITY_CMAP",
33
+ ]
34
+
35
+ #: Diverging colormap for vorticity fields (signed, centered at zero): an
36
+ #: alias for :data:`DIVERGING_CMAP`, named for its most common use in this
37
+ #: package.
38
+ VORTICITY_CMAP: str = DIVERGING_CMAP
@@ -0,0 +1,52 @@
1
+ """Numba-accelerated ODE integrators shared across physicskit subpackages.
2
+
3
+ Right-hand-side / force callbacks use the ``f(state_or_pos, t, params) ->
4
+ ndarray`` convention throughout, so a single compiled callback can be reused
5
+ across systems with different parameter values without recompiling (see
6
+ :mod:`physicskit.integrators.fixed_step`).
7
+
8
+ * :func:`rk4_integrate` -- classical 4th-order Runge-Kutta (not
9
+ energy-preserving).
10
+ * :func:`leapfrog_integrate` (alias :func:`velocity_verlet_integrate`) --
11
+ 2nd-order symplectic Stormer-Verlet, for separable systems
12
+ ``pos'' = force(pos, t)``.
13
+ * :func:`yoshida4_integrate` -- 4th-order symplectic, built from three
14
+ leapfrog sub-steps.
15
+ * :func:`dopri5_integrate` -- adaptive-step-size embedded Dormand-Prince
16
+ RK5(4), for non-conservative or accuracy-sensitive systems (see
17
+ :mod:`physicskit.integrators.adaptive` for why this isn't offered for the
18
+ symplectic integrators).
19
+
20
+ :mod:`physicskit.classical.core.integrators` uses its own closure-based
21
+ calling convention (``force_func(q, t)`` plus a per-instance ``mass_inv``)
22
+ and :mod:`physicskit.statphys.core.md_engine` its own periodic-boundary,
23
+ force-caching variant; both are documented at their own definitions rather
24
+ than adapted to the convention here.
25
+ """
26
+
27
+ from physicskit.integrators.adaptive import dopri5_integrate, dopri5_step
28
+ from physicskit.integrators.fixed_step import (
29
+ RHSFunc,
30
+ leapfrog_integrate,
31
+ leapfrog_step,
32
+ rk4_integrate,
33
+ rk4_step,
34
+ velocity_verlet_integrate,
35
+ velocity_verlet_step,
36
+ yoshida4_integrate,
37
+ yoshida4_step,
38
+ )
39
+
40
+ __all__ = [
41
+ "RHSFunc",
42
+ "rk4_step",
43
+ "rk4_integrate",
44
+ "leapfrog_step",
45
+ "leapfrog_integrate",
46
+ "velocity_verlet_step",
47
+ "velocity_verlet_integrate",
48
+ "yoshida4_step",
49
+ "yoshida4_integrate",
50
+ "dopri5_step",
51
+ "dopri5_integrate",
52
+ ]