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,131 @@
1
+ """Spot-check each chapter against known analytic results, so regressions in
2
+ the underlying physics (not just raw unitarity) get caught."""
3
+
4
+ import numpy as np
5
+
6
+ from physicskit.quantum.chapters.entanglement import AharonovBohmRing, BellCorrelations
7
+ from physicskit.quantum.chapters.harmonic_spin import HarmonicOscillator, ThermalState
8
+ from physicskit.quantum.chapters.hydrogen_am import HydrogenOrbital
9
+ from physicskit.quantum.chapters.potentials import FiniteSquareWell, StadiumBilliard2D
10
+ from physicskit.quantum.chapters.wave_packets import QuantumRevival
11
+ from physicskit.quantum.core.eigensolvers import NumerovSolver, harmonic_well, infinite_well
12
+ from physicskit.quantum.visualizers.phase_space import wigner_transform
13
+
14
+
15
+ def test_numerov_matches_infinite_well_and_harmonic_oscillator():
16
+ x = np.linspace(0, 1, 400)
17
+ energies = NumerovSolver(x, infinite_well()).solve(5).energies
18
+ analytic = (np.arange(1, 6) ** 2 * np.pi**2) / 2
19
+ assert np.allclose(energies, analytic, rtol=1e-3)
20
+
21
+ x2 = np.linspace(-10, 10, 800)
22
+ energies2 = NumerovSolver(x2, harmonic_well()).solve(5).energies
23
+ assert np.allclose(energies2, np.arange(5) + 0.5, atol=1e-4)
24
+
25
+
26
+ def test_coherent_state_tracks_classical_trajectory():
27
+ ho = HarmonicOscillator()
28
+ x = np.linspace(-15, 15, 3000)
29
+ alpha = 3 + 1j
30
+ for t in (0.0, 1.3, 4.0):
31
+ psi_t = ho.coherent_wavefunction(alpha, x, t=t)
32
+ x_mean = np.real(np.trapezoid(x * np.abs(psi_t) ** 2, x))
33
+ x_classical, _ = ho.coherent_trajectory(alpha, np.array([t]))
34
+ assert abs(x_mean - x_classical[0]) < 1e-6
35
+
36
+
37
+ def test_thermal_state_broadens_with_temperature():
38
+ ho = HarmonicOscillator()
39
+ var_cold = ThermalState(ho, T=0.1).variance()
40
+ var_hot = ThermalState(ho, T=5.0).variance()
41
+ assert var_hot > var_cold
42
+
43
+
44
+ def test_hydrogen_orbitals_normalized_with_correct_energy():
45
+ for n, l, m in [(1, 0, 0), (2, 1, 0), (3, 2, 1)]:
46
+ orb = HydrogenOrbital(n, l, m)
47
+ assert abs(orb.check_normalization() - 1.0) < 1e-6
48
+ assert abs(orb.energy - (-1 / (2 * n**2))) < 1e-12
49
+
50
+
51
+ def test_quantum_revival_reassembles_at_revival_time():
52
+ qr = QuantumRevival(L=1.0, n_max=250)
53
+ x = np.linspace(0, qr.L, 1500)
54
+ psi0_func = qr.gaussian_initial_state(x0=0.3, sigma=0.03)
55
+ psi0 = psi0_func(x)
56
+ c = qr.eigenbasis_coefficients(psi0_func)
57
+
58
+ fidelity_scrambled = qr.fidelity_to_initial(x, 0.1 * qr.revival_time, c, psi0)
59
+ fidelity_revived = qr.fidelity_to_initial(x, qr.revival_time, c, psi0)
60
+
61
+ assert fidelity_revived > 0.999
62
+ assert fidelity_scrambled < 0.5
63
+
64
+
65
+ def test_wigner_transform_matches_ground_state_analytic_form():
66
+ ho = HarmonicOscillator()
67
+ x = np.linspace(-8, 8, 250)
68
+ psi0 = ho.eigenfunction(0, x)
69
+ xg, p, W = wigner_transform(x, psi0, hbar=1.0, n_p=120)
70
+ X, P = np.meshgrid(x, p, indexing="ij")
71
+ analytic = (1 / np.pi) * np.exp(-(X**2) - P**2)
72
+ assert np.max(np.abs(W - analytic)) < 1e-10
73
+
74
+
75
+ def test_bell_singlet_violates_chsh_bound():
76
+ bc = BellCorrelations()
77
+ assert abs(bc.chsh_optimal() - 2 * np.sqrt(2)) < 1e-10
78
+ assert bc.chsh_optimal() > 2.0 # violates the classical (local hidden-variable) bound
79
+
80
+
81
+ def test_aharonov_bohm_energy_periodic_in_flux_quantum():
82
+ ring = AharonovBohmRing(R=1.0)
83
+ Phi0 = ring.flux_quantum
84
+ n = np.arange(-3, 4)
85
+ e0 = ring.energy(n, 0.0)
86
+ e_shifted = ring.energy(n + 1, Phi0) # shifting both n and Phi by one quantum is a relabeling
87
+ assert np.allclose(e0, e_shifted)
88
+ assert abs(ring.aharonov_bohm_phase(Phi0) - 2 * np.pi) < 1e-12
89
+
90
+
91
+ def test_barrier_scattering_matches_sub_barrier_tunneling_formula():
92
+ # A "well" with negative V0 is a barrier of height |V0|; below the
93
+ # barrier (E < |V0|) this is the classically forbidden, sub-barrier
94
+ # tunneling regime, where k2 is purely imaginary.
95
+ E, Vb, a = 4.5, 6.0, 1.0
96
+ barrier = FiniteSquareWell(V0=-Vb, width=a)
97
+ result = barrier.scattering(E)
98
+
99
+ kappa = np.sqrt(2 * (Vb - E))
100
+ T_expected = 1 / (1 + Vb**2 * np.sinh(kappa * a) ** 2 / (4 * E * (Vb - E)))
101
+ assert abs(result.T - T_expected) < 1e-12
102
+ assert abs(result.k2.real) < 1e-12 # purely imaginary in the forbidden region
103
+ assert 0 < result.T < 1
104
+
105
+ # Above the barrier (E > |V0|), T should match the ordinary real-k2 formula.
106
+ E_above = 10.0
107
+ result_above = barrier.scattering(E_above)
108
+ k2_expected = np.sqrt(2 * (E_above - Vb))
109
+ T_expected_above = 1 / (1 + Vb**2 * np.sin(k2_expected * a) ** 2 / (4 * E_above * (E_above - Vb)))
110
+ assert abs(result_above.T - T_expected_above) < 1e-10
111
+ assert abs(result_above.k2.imag) < 1e-12
112
+
113
+
114
+ def test_stadium_billiard_grid_is_isotropic_and_states_are_normalized():
115
+ # A mismatched dx/dy staircases the semicircular caps as ellipses
116
+ # rather than circles, giving resolution-dependent, non-monotonically
117
+ # converging eigenvalues -- grid() must keep dx == dy.
118
+ sb = StadiumBilliard2D(L=1.0, R=0.5)
119
+ for n_points in (50, 90, 150):
120
+ (X, Y), x, y = sb.grid(n_points)
121
+ dx, dy = x[1] - x[0], y[1] - y[0]
122
+ # dy matches dx up to the rounding of n_y to an integer point count
123
+ assert abs(dx - dy) / dx < 0.02
124
+
125
+ energies, wavefunctions, X, Y, mask = sb.solve(n_points=90, n_states=4)
126
+ assert np.all(np.diff(energies) > 0)
127
+ assert np.all(energies > 0)
128
+ dx, dy = X[1, 0] - X[0, 0], Y[0, 1] - Y[0, 0]
129
+ for psi in wavefunctions:
130
+ assert abs(np.sum(psi**2) * dx * dy - 1.0) < 1e-6
131
+ assert np.all(psi[~mask] == 0.0)
@@ -0,0 +1,191 @@
1
+ """Tests for physicskit.quantum.chapters.potentials: the parts
2
+ test_physics_checks.py and test_animations.py don't already exercise --
3
+ the asymmetric step well, the gravitational bouncer (both the Numerov
4
+ solver and its closed-form Airy-function check), DoubleWellSimulator's
5
+ localized_state, FiniteSquareWell's bound_states/transmission_spectrum/
6
+ evanescent_wavefunction, and the 2D rectangular/circular boxes.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import numpy as np
12
+ import pytest
13
+
14
+ from physicskit.quantum._compat import trapz
15
+ from physicskit.quantum.chapters.potentials import (
16
+ Box2DEigenstate,
17
+ CircularBox2D,
18
+ DoubleWellSimulator,
19
+ FiniteSquareWell,
20
+ RectangularBox2D,
21
+ airy_bouncer_energies,
22
+ airy_wavefunction,
23
+ asymmetric_well_states,
24
+ gravitational_bouncer_states,
25
+ )
26
+
27
+
28
+ # --- Asymmetric step well -----------------------------------------------------
29
+
30
+
31
+ def test_asymmetric_well_states_are_bound_below_the_lower_wall():
32
+ res = asymmetric_well_states(width=2.0, V_left=40.0, V_right=15.0, n_points=800, n_states=3)
33
+ assert np.all(np.diff(res.energies) > 0) # ascending
34
+ assert np.all(res.energies < 15.0) # below the lower (right) wall
35
+ for psi in res.wavefunctions:
36
+ assert trapz(psi**2, res.x) == pytest.approx(1.0, abs=1e-2)
37
+
38
+
39
+ # --- Gravitational bouncer -----------------------------------------------------
40
+
41
+
42
+ def test_gravitational_bouncer_numerov_matches_airy_analytic_energies():
43
+ n_states = 4
44
+ numeric = gravitational_bouncer_states(alpha=1.0, x_extent=12.0, n_points=1500, n_states=n_states)
45
+ analytic = airy_bouncer_energies(alpha=1.0, n_states=n_states)
46
+ np.testing.assert_allclose(numeric.energies, analytic, rtol=2e-2)
47
+
48
+
49
+ def test_airy_bouncer_energies_are_ascending_and_positive():
50
+ energies = airy_bouncer_energies(alpha=2.0, n_states=5)
51
+ assert np.all(energies > 0)
52
+ assert np.all(np.diff(energies) > 0)
53
+
54
+
55
+ def test_airy_wavefunction_is_normalized_and_vanishes_below_floor():
56
+ x = np.linspace(-2, 30, 4000)
57
+ psi = airy_wavefunction(x, alpha=1.0, n=0)
58
+ assert trapz(psi**2, x) == pytest.approx(1.0, abs=1e-3)
59
+ np.testing.assert_allclose(psi[x < 0], 0.0)
60
+
61
+
62
+ def test_airy_wavefunction_overlaps_numerov_ground_state():
63
+ numeric = gravitational_bouncer_states(alpha=1.0, x_extent=12.0, n_points=1500, n_states=1)
64
+ analytic_psi = airy_wavefunction(numeric.x, alpha=1.0, n=0)
65
+ overlap = abs(trapz(analytic_psi * numeric.wavefunctions[0], numeric.x))
66
+ assert overlap == pytest.approx(1.0, abs=1e-2)
67
+
68
+
69
+ # --- Double well: localized_state ---------------------------------------------
70
+
71
+
72
+ def test_double_well_localized_state_is_normalized_and_side_asymmetric():
73
+ dw = DoubleWellSimulator(lam=0.3, a=2.0, n_points=800)
74
+ result = dw.solve(n_states=2)
75
+ left = dw.localized_state(result, side="left")
76
+ right = dw.localized_state(result, side="right")
77
+ assert trapz(left**2, result.x) == pytest.approx(1.0, abs=1e-2)
78
+ assert trapz(right**2, result.x) == pytest.approx(1.0, abs=1e-2)
79
+ left_mask = result.x < 0
80
+ # a state built to localize on the left should weight the left lobe more
81
+ assert trapz(left[left_mask] ** 2, result.x[left_mask]) > trapz(right[left_mask] ** 2, result.x[left_mask])
82
+
83
+
84
+ # --- Finite square well: bound_states / transmission_spectrum / evanescent ----
85
+
86
+
87
+ def test_finite_square_well_bound_states_are_all_negative_energy():
88
+ well = FiniteSquareWell(V0=20.0, width=2.0)
89
+ res = well.bound_states(n_points=800, n_states=6)
90
+ assert res.energies.size > 0
91
+ assert np.all(res.energies < 0)
92
+ assert np.all(np.diff(res.energies) > 0)
93
+
94
+
95
+ def test_finite_square_well_evanescent_wavefunction_matches_bound_states_entry():
96
+ well = FiniteSquareWell(V0=20.0, width=2.0)
97
+ res = well.bound_states(n_points=800, n_states=3)
98
+ np.testing.assert_allclose(well.evanescent_wavefunction(res, n=1), res.wavefunctions[1])
99
+
100
+
101
+ def test_transmission_spectrum_matches_pointwise_scattering():
102
+ well = FiniteSquareWell(V0=10.0, width=1.0)
103
+ E_values = np.array([1.0, 5.0, 12.0])
104
+ spectrum = well.transmission_spectrum(E_values)
105
+ expected = np.array([well.scattering(E).T for E in E_values])
106
+ np.testing.assert_allclose(spectrum, expected)
107
+ assert np.all((spectrum >= 0) & (spectrum <= 1))
108
+
109
+
110
+ # --- 2D rectangular box ---------------------------------------------------------
111
+
112
+
113
+ def test_rectangular_box_energy_matches_formula():
114
+ box = RectangularBox2D(Lx=2.0, Ly=3.0, hbar=1.0, m=1.0)
115
+ nx, ny = 2, 3
116
+ expected = (np.pi**2 * box.hbar**2 / (2 * box.m)) * ((nx / box.Lx) ** 2 + (ny / box.Ly) ** 2)
117
+ assert box.energy(nx, ny) == pytest.approx(expected)
118
+
119
+
120
+ def test_rectangular_box_spectrum_is_sorted_by_energy():
121
+ box = RectangularBox2D(Lx=1.0, Ly=1.7)
122
+ states = box.spectrum(n_max=4)
123
+ energies = [s.energy for s in states]
124
+ assert energies == sorted(energies)
125
+ assert len(states) == 16
126
+
127
+
128
+ def test_rectangular_box_square_has_degeneracies():
129
+ box = RectangularBox2D(Lx=1.0, Ly=1.0)
130
+ degeneracies = box.degeneracies(n_max=4)
131
+ # (1,2) and (2,1) are exactly degenerate for a square box (E ~ nx^2+ny^2)
132
+ assert any({(1, 2), (2, 1)} <= set(pairs) for pairs in degeneracies.values())
133
+ for pairs in degeneracies.values():
134
+ assert len(pairs) >= 2
135
+
136
+
137
+ def test_rectangular_box_grid_has_expected_shape_and_bounds():
138
+ box = RectangularBox2D(Lx=2.0, Ly=3.0)
139
+ X, Y = box.grid(n_points=10)
140
+ assert X.shape == (10, 10)
141
+ assert X.min() == pytest.approx(0.0)
142
+ assert X.max() == pytest.approx(2.0)
143
+ assert Y.max() == pytest.approx(3.0)
144
+
145
+
146
+ def test_box2d_eigenstate_psi_is_normalized_over_the_box():
147
+ box = RectangularBox2D(Lx=1.0, Ly=1.0)
148
+ state = Box2DEigenstate(nx=2, ny=1, energy=box.energy(2, 1))
149
+ X, Y = box.grid(n_points=200)
150
+ psi = state.psi(X, Y, box.Lx, box.Ly)
151
+ integral = trapz(trapz(psi**2, Y[0], axis=1), X[:, 0])
152
+ assert integral == pytest.approx(1.0, abs=1e-2)
153
+
154
+
155
+ # --- 2D circular quantum dot ------------------------------------------------------
156
+
157
+
158
+ def test_circular_box_eigenstate_energy_matches_bessel_zero_formula():
159
+ from scipy.special import jn_zeros
160
+
161
+ dot = CircularBox2D(R=1.5, hbar=1.0, m_mass=1.0)
162
+ state = dot.eigenstate(m=1, n=2)
163
+ expected_k = jn_zeros(1, 2)[-1] / dot.R
164
+ assert state.k == pytest.approx(expected_k)
165
+ assert state.energy == pytest.approx(dot.hbar**2 * state.k**2 / (2 * dot.m_mass))
166
+
167
+
168
+ def test_circular_box_spectrum_is_sorted_and_ground_state_is_m_zero_n_one():
169
+ dot = CircularBox2D(R=1.0)
170
+ states = dot.spectrum(m_max=3, n_max=3)
171
+ energies = [s.energy for s in states]
172
+ assert energies == sorted(energies)
173
+ assert states[0].m == 0
174
+ assert states[0].n == 1
175
+
176
+
177
+ def test_circular_box_polar_grid_spans_radius_and_full_turn():
178
+ dot = CircularBox2D(R=2.0)
179
+ r, phi = dot.polar_grid(n_r=20, n_phi=30)
180
+ assert r.shape == (20, 30)
181
+ assert r.max() == pytest.approx(2.0)
182
+ assert phi.max() == pytest.approx(2 * np.pi)
183
+
184
+
185
+ def test_circular_eigenstate_psi_vanishes_at_the_boundary():
186
+ dot = CircularBox2D(R=1.0)
187
+ state = dot.eigenstate(m=0, n=1)
188
+ phi = np.linspace(0, 2 * np.pi, 16)
189
+ r_boundary = np.full_like(phi, dot.R)
190
+ psi_boundary = state.psi(r_boundary, phi, dot.R)
191
+ np.testing.assert_allclose(psi_boundary, 0.0, atol=1e-8)
@@ -0,0 +1,70 @@
1
+ """Tests for physicskit.quantum.core.solvers: the time-dependent-potential
2
+ branch of SplitOperatorSolver2D (test_unitarity.py only exercises the
3
+ static-potential path) and _accepts_time's non-introspectable-callable
4
+ fallback.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import numpy as np
10
+ import pytest
11
+
12
+ from physicskit.quantum.core.solvers import SplitOperatorSolver2D, _accepts_time
13
+
14
+
15
+ def _gaussian_2d(X, Y, x0=0.0, y0=0.0, sigma=1.0):
16
+ norm = (2 * np.pi * sigma**2) ** (-0.5)
17
+ return norm * np.exp(-((X - x0) ** 2 + (Y - y0) ** 2) / (2 * sigma**2))
18
+
19
+
20
+ def test_accepts_time_detects_three_argument_signature():
21
+ def V_static(x, y):
22
+ return x + y
23
+
24
+ def V_time_dependent(x, y, t):
25
+ return x + y + t
26
+
27
+ assert _accepts_time(V_static, n_spatial_args=2) is False
28
+ assert _accepts_time(V_time_dependent, n_spatial_args=2) is True
29
+
30
+
31
+ def test_accepts_time_falls_back_to_false_for_non_introspectable_callable():
32
+ # inspect.signature(min) raises ValueError (no signature metadata for
33
+ # this builtin), and _accepts_time should fall back to False rather
34
+ # than propagating the exception.
35
+ assert _accepts_time(min, n_spatial_args=2) is False
36
+
37
+
38
+ def test_split_operator_2d_with_time_dependent_potential_conserves_norm():
39
+ x = np.linspace(-8, 8, 64)
40
+ y = np.linspace(-8, 8, 64)
41
+
42
+ def V(X, Y, t):
43
+ return 0.5 * (X**2 + Y**2) * (1.0 + 0.1 * np.sin(t))
44
+
45
+ solver = SplitOperatorSolver2D(x, y, V, dt=1e-3)
46
+ assert solver._time_dependent is True
47
+
48
+ X, Y = np.meshgrid(x, y, indexing="ij")
49
+ psi = _gaussian_2d(X, Y).astype(complex)
50
+ psi /= np.sqrt(solver.norm(psi))
51
+
52
+ t = 0.0
53
+ for _ in range(50):
54
+ psi = solver.step(psi, t)
55
+ t += solver.dt
56
+
57
+ assert solver.norm(psi) == pytest.approx(1.0, abs=1e-6)
58
+
59
+
60
+ def test_split_operator_2d_time_dependent_potential_actually_varies_with_time():
61
+ x = np.linspace(-8, 8, 32)
62
+ y = np.linspace(-8, 8, 32)
63
+
64
+ def V(X, Y, t):
65
+ return t * (X**2 + Y**2)
66
+
67
+ solver = SplitOperatorSolver2D(x, y, V, dt=1e-3)
68
+ phase_t0 = solver._half_potential_phase(0.0)
69
+ phase_t1 = solver._half_potential_phase(1.0)
70
+ assert not np.allclose(phase_t0, phase_t1)
@@ -0,0 +1,22 @@
1
+ """Tests for physicskit.quantum.chapters.spin: RabiProblem's Omega_R=0
2
+ edge case (no drive, no detuning), not exercised by test_animations.py.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import numpy as np
8
+
9
+ from physicskit.quantum.chapters.spin import RabiProblem
10
+ from physicskit.quantum.core.operators import identity2
11
+
12
+
13
+ def test_rabi_propagator_is_identity_when_undriven_and_on_resonance():
14
+ rabi = RabiProblem(omega0=1.0, omega_d=1.0, Omega=0.0)
15
+ assert rabi.generalized_rabi_frequency == 0.0
16
+ np.testing.assert_allclose(rabi.propagator(t=2.5), identity2)
17
+
18
+
19
+ def test_rabi_excited_state_population_stays_zero_when_undriven():
20
+ rabi = RabiProblem(omega0=1.0, omega_d=1.0, Omega=0.0)
21
+ t = np.linspace(0, 10, 20)
22
+ np.testing.assert_allclose(rabi.excited_state_population(t), np.zeros_like(t))
@@ -0,0 +1,84 @@
1
+ """Verify probability conservation integral |psi(x,t)|^2 dx = 1 +/- 1e-6 over
2
+ 10^4 timesteps of the split-operator FFT propagator, across a variety of
3
+ potential shapes (harmonic, double well, finite well, asymmetric well,
4
+ gravitational bouncer, soft infinite box, and a 2D rectangular box).
5
+ """
6
+
7
+ import numpy as np
8
+ import pytest
9
+
10
+ from physicskit.quantum.core.eigensolvers import (
11
+ asymmetric_step_well,
12
+ double_well,
13
+ finite_well,
14
+ harmonic_well,
15
+ linear_gravitational_well,
16
+ )
17
+ from physicskit.quantum.core.solvers import SplitOperatorSolver1D, SplitOperatorSolver2D
18
+
19
+ N_STEPS = 10_000
20
+ TOL = 1e-6
21
+
22
+
23
+ def _gaussian(x, x0=0.0, sigma=1.0, k0=0.0):
24
+ norm = (2 * np.pi * sigma**2) ** (-0.25)
25
+ return norm * np.exp(-((x - x0) ** 2) / (4 * sigma**2)) * np.exp(1j * k0 * x)
26
+
27
+
28
+ def _run_1d(V, x, psi0, dt):
29
+ solver = SplitOperatorSolver1D(x, V, dt=dt)
30
+ psi = psi0.astype(complex)
31
+ psi /= np.sqrt(solver.norm(psi))
32
+ for _ in range(N_STEPS):
33
+ psi = solver.step(psi)
34
+ return solver.norm(psi)
35
+
36
+
37
+ @pytest.mark.parametrize(
38
+ "name,V,x_range,x0,sigma,dt",
39
+ [
40
+ ("harmonic", harmonic_well(), (-15, 15), 2.0, 1.0, 1e-3),
41
+ ("double_well", double_well(lam=0.5, a=2.5), (-8, 8), 2.5, 0.5, 5e-4),
42
+ ("finite_well", finite_well(V0=30.0, width=3.0), (-10, 10), 0.0, 0.5, 5e-4),
43
+ ("asymmetric_well", asymmetric_step_well(width=3.0, V_left=40.0, V_right=15.0), (-8, 8), 0.0, 0.5, 5e-4),
44
+ ("gravitational_bouncer", linear_gravitational_well(alpha=2.0), (-12, 12), 3.0, 0.5, 2e-4),
45
+ ],
46
+ )
47
+ def test_1d_unitarity(name, V, x_range, x0, sigma, dt):
48
+ x = np.linspace(*x_range, 2048)
49
+ psi0 = _gaussian(x, x0=x0, sigma=sigma)
50
+ final_norm = _run_1d(V, x, psi0, dt)
51
+ assert abs(final_norm - 1.0) < TOL, f"{name}: norm drifted to {final_norm}"
52
+
53
+
54
+ def test_1d_unitarity_soft_infinite_box():
55
+ L, wall = 1.0, 4000.0
56
+
57
+ def V(x):
58
+ return np.where((x >= 0) & (x <= L), 0.0, wall)
59
+
60
+ x = np.linspace(-0.3, 1.3, 2048)
61
+ psi0 = _gaussian(x, x0=0.5, sigma=0.08)
62
+ final_norm = _run_1d(V, x, psi0, dt=2e-5)
63
+ assert abs(final_norm - 1.0) < TOL
64
+
65
+
66
+ def test_2d_unitarity_rectangular_box():
67
+ Lx, Ly, wall = 1.0, 1.0, 3000.0
68
+
69
+ def V(x, y):
70
+ return np.where((x >= 0) & (x <= Lx) & (y >= 0) & (y <= Ly), 0.0, wall)
71
+
72
+ x = np.linspace(-0.3, 1.3, 160)
73
+ y = np.linspace(-0.3, 1.3, 160)
74
+ solver = SplitOperatorSolver2D(x, y, V, dt=5e-5)
75
+
76
+ X, Y = solver.X, solver.Y
77
+ psi0 = np.exp(-((X - 0.5) ** 2 + (Y - 0.5) ** 2) / (4 * 0.05**2)).astype(complex)
78
+ psi0 /= np.sqrt(solver.norm(psi0))
79
+
80
+ psi = psi0
81
+ for _ in range(2000):
82
+ psi = solver.step(psi)
83
+
84
+ assert abs(solver.norm(psi) - 1.0) < TOL
@@ -0,0 +1,53 @@
1
+ """Tests for physicskit.quantum.chapters.wave_packets: the parts of
2
+ GaussianDispersion (center, density) and TwinSlit not already exercised
3
+ by test_physics_checks.py/test_animations.py.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import numpy as np
9
+ import pytest
10
+
11
+ from physicskit.quantum._compat import trapz
12
+ from physicskit.quantum.chapters.wave_packets import GaussianDispersion, TwinSlit
13
+
14
+
15
+ def test_gaussian_dispersion_center_moves_ballistically():
16
+ gd = GaussianDispersion(x0=1.0, k0=3.0, hbar=1.0, m=2.0)
17
+ t = np.array([0.0, 1.0, 2.5])
18
+ np.testing.assert_allclose(gd.center(t), gd.x0 + (gd.hbar * gd.k0 / gd.m) * t)
19
+
20
+
21
+ def test_gaussian_dispersion_density_matches_abs_psi_squared():
22
+ gd = GaussianDispersion()
23
+ x = np.linspace(-10, 10, 200)
24
+ np.testing.assert_allclose(gd.density(x, t=0.7), np.abs(gd.psi(x, 0.7)) ** 2)
25
+
26
+
27
+ def test_gaussian_dispersion_density_stays_normalized_over_time():
28
+ gd = GaussianDispersion(sigma0=1.0, k0=0.0) # k0=0 keeps the packet centered at x0
29
+ x = np.linspace(-40, 40, 4000)
30
+ for t in (0.0, 5.0, 20.0):
31
+ assert trapz(gd.density(x, t), x) == pytest.approx(1.0, abs=1e-3)
32
+
33
+
34
+ def test_twin_slit_intensity_is_normalized():
35
+ ts = TwinSlit(slit_separation=4.0, slit_width=0.4, k0=10.0)
36
+ x = np.linspace(-20, 20, 4000)
37
+ I = ts.intensity(x, screen_distance=50.0)
38
+ assert trapz(I, x) == pytest.approx(1.0, abs=1e-6)
39
+
40
+
41
+ def test_twin_slit_intensity_is_symmetric_about_the_axis():
42
+ ts = TwinSlit(slit_separation=4.0, slit_width=0.4, k0=10.0)
43
+ x = np.linspace(-20, 20, 501) # ascending and symmetric, so trapz normalization matches
44
+ I = ts.intensity(x, screen_distance=50.0)
45
+ np.testing.assert_allclose(I, I[::-1], rtol=1e-10)
46
+
47
+
48
+ def test_twin_slit_amplitude_is_complex_and_finite():
49
+ ts = TwinSlit()
50
+ x = np.linspace(-10, 10, 50)
51
+ amp = ts.amplitude(x, screen_distance=30.0)
52
+ assert np.iscomplexobj(amp)
53
+ assert np.all(np.isfinite(amp))
File without changes