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,517 @@
1
+ r"""The harmonic oscillator suite: Fock states, Glauber coherent states,
2
+ squeezed states, and thermal (mixed) states.
3
+
4
+ Wavefunctions are built from the numerically stable three-term recurrence
5
+ for normalized Hermite-Gaussian functions, which avoids the overflow of
6
+ evaluating raw Hermite polynomials :math:`H_n(x)` and :math:`n!` separately
7
+ at large :math:`n`.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from dataclasses import dataclass
13
+
14
+ import numpy as np
15
+ from scipy.special import gammaln
16
+
17
+ from .._compat import trapz
18
+
19
+ __all__ = ["HarmonicOscillator", "ThermalState"]
20
+
21
+
22
+ def _eigenfunctions_up_to(n_max: int, xi: np.ndarray) -> np.ndarray:
23
+ r"""Normalized :math:`\psi_n(\xi)` for :math:`n=0..n_\text{max}` on the
24
+ dimensionless coordinate :math:`\xi = \sqrt{m\omega/\hbar}\,x`, via the
25
+ stable recurrence
26
+
27
+ .. math::
28
+
29
+ \psi_n = \sqrt{2/n}\,\xi\,\psi_{n-1} - \sqrt{(n-1)/n}\,\psi_{n-2}.
30
+ """
31
+ psi = np.empty((n_max + 1, xi.shape[0]))
32
+ psi[0] = (1.0 / np.pi) ** 0.25 * np.exp(-(xi**2) / 2)
33
+ if n_max >= 1:
34
+ psi[1] = np.sqrt(2.0) * xi * psi[0]
35
+ for n in range(2, n_max + 1):
36
+ psi[n] = np.sqrt(2.0 / n) * xi * psi[n - 1] - np.sqrt((n - 1) / n) * psi[n - 2]
37
+ return psi
38
+
39
+
40
+ @dataclass
41
+ class HarmonicOscillator:
42
+ r"""The 1D quantum harmonic oscillator,
43
+
44
+ .. math::
45
+
46
+ \hat H = \frac{\hat p^2}{2m} + \frac{1}{2} m \omega^2 \hat x^2.
47
+
48
+ Parameters
49
+ ----------
50
+ m : float, default=1.0
51
+ Particle mass.
52
+ omega : float, default=1.0
53
+ Angular frequency :math:`\omega`.
54
+ hbar : float, default=1.0
55
+ Value of :math:`\hbar` to use.
56
+ """
57
+
58
+ m: float = 1.0
59
+ omega: float = 1.0
60
+ hbar: float = 1.0
61
+
62
+ @property
63
+ def x0(self) -> float:
64
+ r"""float: Natural length scale :math:`\sqrt{\hbar/(m\omega)}`."""
65
+ return np.sqrt(self.hbar / (self.m * self.omega))
66
+
67
+ def energy(self, n) -> np.ndarray:
68
+ r"""Eigenenergy :math:`E_n = \hbar\omega(n+1/2)`.
69
+
70
+ Parameters
71
+ ----------
72
+ n : int or array_like
73
+ Quantum number(s).
74
+
75
+ Returns
76
+ -------
77
+ numpy.ndarray
78
+ """
79
+ n = np.asarray(n)
80
+ return self.hbar * self.omega * (n + 0.5)
81
+
82
+ def _xi(self, x: np.ndarray) -> np.ndarray:
83
+ return np.asarray(x) / self.x0
84
+
85
+ def eigenfunction(self, n: int, x: np.ndarray) -> np.ndarray:
86
+ r"""The Fock (energy) eigenstate :math:`\phi_n(x)`.
87
+
88
+ Normalized so that :math:`\int \lvert\phi_n\rvert^2\,dx = 1`.
89
+
90
+ Parameters
91
+ ----------
92
+ n : int
93
+ Quantum number.
94
+ x : numpy.ndarray
95
+ Positions to evaluate at.
96
+
97
+ Returns
98
+ -------
99
+ numpy.ndarray
100
+ """
101
+ xi = self._xi(x)
102
+ psi = _eigenfunctions_up_to(n, xi)[n]
103
+ return psi / np.sqrt(self.x0)
104
+
105
+ def eigenfunctions(self, n_max: int, x: np.ndarray) -> np.ndarray:
106
+ r"""Stack of eigenstates :math:`\phi_0, \dots, \phi_{n_\text{max}}(x)`.
107
+
108
+ Parameters
109
+ ----------
110
+ n_max : int
111
+ Highest quantum number to include.
112
+ x : numpy.ndarray
113
+ Positions to evaluate at.
114
+
115
+ Returns
116
+ -------
117
+ numpy.ndarray
118
+ Shape ``(n_max+1, len(x))``.
119
+ """
120
+ xi = self._xi(x)
121
+ return _eigenfunctions_up_to(n_max, xi) / np.sqrt(self.x0)
122
+
123
+ def eigenfunction_t(self, n: int, x: np.ndarray, t: float) -> np.ndarray:
124
+ r"""The time-evolved stationary state
125
+ :math:`\psi_n(x,t) = \phi_n(x)\, e^{-i E_n t/\hbar}`.
126
+
127
+ A pure phase-rotating stationary state:
128
+ :math:`\lvert\psi_n(x,t)\rvert^2` is time-independent.
129
+
130
+ Parameters
131
+ ----------
132
+ n : int
133
+ Quantum number.
134
+ x : numpy.ndarray
135
+ Positions to evaluate at.
136
+ t : float
137
+ Time.
138
+
139
+ Returns
140
+ -------
141
+ numpy.ndarray
142
+ Complex-valued :math:`\psi_n(x,t)`.
143
+ """
144
+ phase = np.exp(-1j * self.energy(n) * t / self.hbar)
145
+ return self.eigenfunction(n, x).astype(complex) * phase
146
+
147
+ def superposition_wavefunction(self, n_values, coeffs, x: np.ndarray, t: float) -> np.ndarray:
148
+ r"""A general time-evolved superposition of Fock eigenstates.
149
+
150
+ .. math::
151
+
152
+ \psi(x,t) = \sum_k c_k\, \phi_{n_k}(x)\, e^{-i E_{n_k} t/\hbar},
153
+
154
+ with beats at every pairwise frequency :math:`(E_{n_k}-E_{n_j})/\hbar`
155
+ -- unlike a single stationary state (:meth:`eigenfunction_t`) or a
156
+ coherent state (:meth:`coherent_wavefunction`, a rigidly oscillating
157
+ Gaussian), a generic superposition's density genuinely reshapes over
158
+ time.
159
+
160
+ Parameters
161
+ ----------
162
+ n_values : array_like of int
163
+ Quantum numbers included in the superposition.
164
+ coeffs : array_like of complex
165
+ Amplitudes :math:`c_k` (renormalized internally so
166
+ :math:`\sum_k \lvert c_k\rvert^2=1`).
167
+ x : numpy.ndarray
168
+ Positions to evaluate at.
169
+ t : float
170
+ Time.
171
+
172
+ Returns
173
+ -------
174
+ numpy.ndarray
175
+ Complex-valued :math:`\psi(x,t)`.
176
+ """
177
+ n_values = np.asarray(n_values)
178
+ coeffs = np.asarray(coeffs, dtype=complex)
179
+ coeffs = coeffs / np.sqrt(np.sum(np.abs(coeffs) ** 2))
180
+ phis = self.eigenfunctions(int(n_values.max()), x)[n_values]
181
+ phases = np.exp(-1j * self.energy(n_values) * t / self.hbar)
182
+ return (coeffs * phases) @ phis
183
+
184
+ def superposition_trajectory(self, n_values, coeffs, x: np.ndarray, t_values: np.ndarray) -> np.ndarray:
185
+ """Stack of :meth:`superposition_wavefunction` snapshots over a time grid.
186
+
187
+ Shaped for :func:`~physicskit.quantum.visualizers.wavefunctions.animate_density`.
188
+
189
+ Parameters
190
+ ----------
191
+ n_values : array_like of int
192
+ Quantum numbers included in the superposition.
193
+ coeffs : array_like of complex
194
+ Amplitudes :math:`c_k`.
195
+ x : numpy.ndarray
196
+ Positions to evaluate at.
197
+ t_values : numpy.ndarray
198
+ Times to evaluate at.
199
+
200
+ Returns
201
+ -------
202
+ numpy.ndarray
203
+ Complex-valued, shape ``(len(t_values), len(x))``.
204
+ """
205
+ return np.array([self.superposition_wavefunction(n_values, coeffs, x, t) for t in t_values])
206
+
207
+ # --- Glauber coherent states -------------------------------------
208
+
209
+ def _coherent_coefficients(self, alpha: complex, n_max: int) -> np.ndarray:
210
+ n = np.arange(n_max + 1)
211
+ log_mag = -0.5 * abs(alpha) ** 2 + n * np.log(abs(alpha) + 1e-300) - 0.5 * gammaln(n + 1)
212
+ phase = n * np.angle(alpha)
213
+ return np.exp(log_mag) * np.exp(1j * phase)
214
+
215
+ def coherent_n_max(self, alpha: complex, margin: float = 8.0) -> int:
216
+ r"""Fock-basis truncation order for a coherent state :math:`\lvert\alpha\rangle`.
217
+
218
+ Captures the Poisson-distributed photon number
219
+ :math:`n \sim \lvert\alpha\rvert^2` out to several standard
220
+ deviations :math:`\sqrt{\lvert\alpha\rvert^2}`.
221
+
222
+ Parameters
223
+ ----------
224
+ alpha : complex
225
+ Coherent-state amplitude.
226
+ margin : float, default=8.0
227
+ Number of standard deviations of safety margin.
228
+
229
+ Returns
230
+ -------
231
+ int
232
+ """
233
+ nbar = abs(alpha) ** 2
234
+ return int(nbar + margin * np.sqrt(nbar + 1) + 20)
235
+
236
+ def coherent_wavefunction(self, alpha: complex, x: np.ndarray, t: float = 0.0, n_max: int | None = None) -> np.ndarray:
237
+ r"""The Glauber coherent state :math:`\lvert\alpha\rangle` in position space.
238
+
239
+ .. math::
240
+
241
+ \psi_\alpha(x,t) = \sum_n c_n\, \phi_n(x)\, e^{-i E_n t/\hbar},
242
+ \qquad c_n = e^{-\lvert\alpha\rvert^2/2}\frac{\alpha^n}{\sqrt{n!}},
243
+
244
+ the Poissonian Fock coefficients of :math:`\lvert\alpha\rangle`. The
245
+ packet is a Gaussian of fixed shape that oscillates rigidly,
246
+ matching the classical trajectory (see :meth:`coherent_trajectory`).
247
+
248
+ Parameters
249
+ ----------
250
+ alpha : complex
251
+ Coherent-state amplitude.
252
+ x : numpy.ndarray
253
+ Positions to evaluate at.
254
+ t : float, default=0.0
255
+ Time.
256
+ n_max : int or None, optional
257
+ Fock-basis truncation order; defaults to :meth:`coherent_n_max`.
258
+
259
+ Returns
260
+ -------
261
+ numpy.ndarray
262
+ Complex-valued :math:`\psi_\alpha(x,t)`.
263
+ """
264
+ if n_max is None:
265
+ n_max = self.coherent_n_max(alpha)
266
+ c = self._coherent_coefficients(alpha, n_max)
267
+ phis = self.eigenfunctions(n_max, x)
268
+ phases = np.exp(-1j * self.energy(np.arange(n_max + 1)) * t / self.hbar)
269
+ return (c * phases) @ phis
270
+
271
+ def coherent_trajectory(self, alpha: complex, t: np.ndarray):
272
+ r"""Classical mean position/momentum of a coherent state.
273
+
274
+ .. math::
275
+
276
+ \langle x\rangle(t) = x_0\sqrt2\,\mathrm{Re}\!\left[\alpha e^{-i\omega t}\right],
277
+ \qquad
278
+ \langle p\rangle(t) = \sqrt{2\hbar m \omega}\,\mathrm{Im}\!\left[\alpha e^{-i\omega t}\right].
279
+
280
+ Parameters
281
+ ----------
282
+ alpha : complex
283
+ Coherent-state amplitude.
284
+ t : numpy.ndarray
285
+ Times to evaluate at.
286
+
287
+ Returns
288
+ -------
289
+ x_t, p_t : numpy.ndarray
290
+ """
291
+ t = np.asarray(t)
292
+ a_t = alpha * np.exp(-1j * self.omega * t)
293
+ x_t = self.x0 * np.sqrt(2.0) * a_t.real
294
+ p_t = np.sqrt(2.0 * self.hbar * self.m * self.omega) * a_t.imag
295
+ return x_t, p_t
296
+
297
+ # --- Squeezed states -------------------------------------------------
298
+
299
+ def squeezed_vacuum_wavefunction(self, x: np.ndarray, r: float, phi: float = 0.0) -> np.ndarray:
300
+ r"""Position-space squeezed vacuum :math:`\lvert r,\phi\rangle`.
301
+
302
+ A Gaussian with quadrature variance
303
+
304
+ .. math::
305
+
306
+ \Delta x^2 = \frac{\hbar}{2 m \omega}\, e^{-2r}
307
+
308
+ (for :math:`\phi=0`, squeezed below the zero-point value when
309
+ :math:`r>0`), at the expense of
310
+ :math:`\Delta p^2 = (\hbar m \omega/2)\, e^{2r}`.
311
+
312
+ Parameters
313
+ ----------
314
+ x : numpy.ndarray
315
+ Positions to evaluate at.
316
+ r : float
317
+ Squeezing parameter.
318
+ phi : float, default=0.0
319
+ Squeezing angle (rotates the quadrature ellipse).
320
+
321
+ Returns
322
+ -------
323
+ numpy.ndarray
324
+ Complex-valued (real when ``phi=0``) squeezed-vacuum wavefunction.
325
+ """
326
+ x = np.asarray(x)
327
+ var_x = (self.hbar / (2 * self.m * self.omega)) * np.exp(-2 * r)
328
+ norm = (1.0 / (2 * np.pi * var_x)) ** 0.25
329
+ gaussian = norm * np.exp(-(x**2) / (4 * var_x))
330
+ # A squeezing-angle phi rotates the quadrature ellipse; encode it as
331
+ # a quadratic chirp phase, exact for the Gaussian squeezed state.
332
+ chirp = np.exp(1j * np.tan(phi) * x**2 / (4 * var_x)) if phi != 0.0 else 1.0
333
+ return gaussian * chirp
334
+
335
+ def squeezed_uncertainties(self, r: float):
336
+ r"""Position/momentum uncertainties of the :math:`r`-squeezed vacuum
337
+ (:math:`\phi=0` axis).
338
+
339
+ Parameters
340
+ ----------
341
+ r : float
342
+ Squeezing parameter.
343
+
344
+ Returns
345
+ -------
346
+ dx, dp : float
347
+ :math:`\Delta x`, :math:`\Delta p`; their product stays at the
348
+ minimum :math:`\hbar/2` for all :math:`r`.
349
+ """
350
+ dx = np.sqrt(self.hbar / (2 * self.m * self.omega) * np.exp(-2 * r))
351
+ dp = np.sqrt(self.hbar * self.m * self.omega / 2 * np.exp(2 * r))
352
+ return dx, dp
353
+
354
+ def zero_point_uncertainties(self):
355
+ """Position/momentum uncertainties of the ordinary ground state.
356
+
357
+ Equivalent to ``squeezed_uncertainties(r=0)``, provided for comparison.
358
+
359
+ Returns
360
+ -------
361
+ dx, dp : float
362
+ """
363
+ return self.squeezed_uncertainties(r=0.0)
364
+
365
+ # --- Thermal (mixed) states -------------------------------------------
366
+
367
+ def thermal_populations(self, T: float, n_max: int, k_B: float = 1.0) -> np.ndarray:
368
+ r"""Diagonal Boltzmann populations of the thermal density matrix.
369
+
370
+ .. math::
371
+
372
+ \rho_{nn} = (1-e^{-x})\, e^{-nx}, \qquad x = \frac{\hbar\omega}{k_B T},
373
+
374
+ for :math:`\hat\rho = e^{-\beta\hat H}/Z` (``T=0`` returns the pure
375
+ ground state).
376
+
377
+ Parameters
378
+ ----------
379
+ T : float
380
+ Temperature (``T<=0`` returns the ground state).
381
+ n_max : int
382
+ Highest Fock level to include.
383
+ k_B : float, default=1.0
384
+ Boltzmann constant.
385
+
386
+ Returns
387
+ -------
388
+ numpy.ndarray
389
+ Populations :math:`\rho_{nn}`, shape ``(n_max+1,)``, summing to 1.
390
+ """
391
+ n = np.arange(n_max + 1)
392
+ if T <= 0:
393
+ p = np.zeros(n_max + 1)
394
+ p[0] = 1.0
395
+ return p
396
+ x = self.hbar * self.omega / (k_B * T)
397
+ p = (1 - np.exp(-x)) * np.exp(-n * x)
398
+ return p / p.sum()
399
+
400
+ def thermal_position_distribution(self, x: np.ndarray, T: float, k_B: float = 1.0, n_max: int = 200) -> np.ndarray:
401
+ r"""The (temperature-broadened) position-space probability density.
402
+
403
+ .. math::
404
+
405
+ P(x) = \sum_n \rho_{nn}\, \lvert\phi_n(x)\rvert^2.
406
+
407
+ Parameters
408
+ ----------
409
+ x : numpy.ndarray
410
+ Positions to evaluate at.
411
+ T : float
412
+ Temperature.
413
+ k_B : float, default=1.0
414
+ Boltzmann constant.
415
+ n_max : int, default=200
416
+ Highest Fock level to include.
417
+
418
+ Returns
419
+ -------
420
+ numpy.ndarray
421
+ """
422
+ pops = self.thermal_populations(T, n_max, k_B)
423
+ phis = self.eigenfunctions(n_max, x)
424
+ return pops @ (phis**2)
425
+
426
+ def thermal_position_variance_analytic(self, T: float, k_B: float = 1.0) -> float:
427
+ r"""Closed-form position variance of the thermal state.
428
+
429
+ .. math::
430
+
431
+ \langle x^2\rangle = \frac{\hbar}{2m\omega}
432
+ \coth\!\left(\frac{\hbar\omega}{2 k_B T}\right),
433
+
434
+ reducing to the zero-point value :math:`\hbar/2m\omega` as
435
+ :math:`T\to 0`.
436
+
437
+ Parameters
438
+ ----------
439
+ T : float
440
+ Temperature.
441
+ k_B : float, default=1.0
442
+ Boltzmann constant.
443
+
444
+ Returns
445
+ -------
446
+ float
447
+ """
448
+ if T <= 0:
449
+ return self.hbar / (2 * self.m * self.omega)
450
+ x = self.hbar * self.omega / (2 * k_B * T)
451
+ return (self.hbar / (2 * self.m * self.omega)) / np.tanh(x)
452
+
453
+
454
+ @dataclass
455
+ class ThermalState:
456
+ """Convenience wrapper bundling an oscillator with a fixed temperature.
457
+
458
+ Parameters
459
+ ----------
460
+ oscillator : HarmonicOscillator
461
+ The underlying oscillator.
462
+ T : float
463
+ Temperature.
464
+ k_B : float, default=1.0
465
+ Boltzmann constant.
466
+ n_max : int, default=200
467
+ Fock-basis truncation order used for the thermal sum.
468
+ """
469
+
470
+ oscillator: HarmonicOscillator
471
+ T: float
472
+ k_B: float = 1.0
473
+ n_max: int = 200
474
+
475
+ def populations(self) -> np.ndarray:
476
+ """See :meth:`HarmonicOscillator.thermal_populations`.
477
+
478
+ Returns
479
+ -------
480
+ numpy.ndarray
481
+ """
482
+ return self.oscillator.thermal_populations(self.T, self.n_max, self.k_B)
483
+
484
+ def position_distribution(self, x: np.ndarray) -> np.ndarray:
485
+ """See :meth:`HarmonicOscillator.thermal_position_distribution`.
486
+
487
+ Parameters
488
+ ----------
489
+ x : numpy.ndarray
490
+
491
+ Returns
492
+ -------
493
+ numpy.ndarray
494
+ """
495
+ return self.oscillator.thermal_position_distribution(x, self.T, self.k_B, self.n_max)
496
+
497
+ def variance(self) -> float:
498
+ """See :meth:`HarmonicOscillator.thermal_position_variance_analytic`.
499
+
500
+ Returns
501
+ -------
502
+ float
503
+ """
504
+ return self.oscillator.thermal_position_variance_analytic(self.T, self.k_B)
505
+
506
+ def check_normalization(self, x: np.ndarray) -> float:
507
+ """Integrate :meth:`position_distribution` over ``x`` (should be 1).
508
+
509
+ Parameters
510
+ ----------
511
+ x : numpy.ndarray
512
+
513
+ Returns
514
+ -------
515
+ float
516
+ """
517
+ return float(trapz(self.position_distribution(x), x))