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,292 @@
1
+ r"""3D spherical harmonics and hydrogen-atom orbitals :math:`\lvert n,l,m\rangle`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+
7
+ import numpy as np
8
+ from scipy.special import genlaguerre
9
+
10
+ from .._compat import sph_harm_y, trapz
11
+
12
+ __all__ = [
13
+ "spherical_harmonic",
14
+ "radial_wavefunction",
15
+ "HydrogenOrbital",
16
+ "orbital_superposition_psi",
17
+ "orbital_superposition_density",
18
+ ]
19
+
20
+ A0 = 1.0
21
+ """float: Bohr radius, in atomic units (length measured in units of :math:`a_0`)."""
22
+
23
+
24
+ def spherical_harmonic(l: int, m: int, theta: np.ndarray, phi: np.ndarray) -> np.ndarray:
25
+ r"""The spherical harmonic :math:`Y_l^m(\theta,\phi)`.
26
+
27
+ Parameters
28
+ ----------
29
+ l : int
30
+ Orbital angular momentum quantum number.
31
+ m : int
32
+ Magnetic quantum number (:math:`\lvert m\rvert \le l`).
33
+ theta : numpy.ndarray
34
+ Polar angle, in :math:`[0, \pi]`.
35
+ phi : numpy.ndarray
36
+ Azimuthal angle, in :math:`[0, 2\pi)`.
37
+
38
+ Returns
39
+ -------
40
+ numpy.ndarray
41
+ Complex-valued :math:`Y_l^m(\theta,\phi)`.
42
+ """
43
+ return sph_harm_y(l, m, theta, phi)
44
+
45
+
46
+ def radial_wavefunction(n: int, l: int, r: np.ndarray, Z: int = 1, a0: float = A0) -> np.ndarray:
47
+ r"""The hydrogenic radial wavefunction :math:`R_{nl}(r)`.
48
+
49
+ Normalized so that :math:`\int_0^\infty \lvert R_{nl}(r)\rvert^2 r^2\,dr = 1`.
50
+
51
+ Parameters
52
+ ----------
53
+ n : int
54
+ Principal quantum number.
55
+ l : int
56
+ Orbital angular momentum quantum number (:math:`0 \le l < n`).
57
+ r : numpy.ndarray
58
+ Radii to evaluate at.
59
+ Z : int, default=1
60
+ Nuclear charge.
61
+ a0 : float, default=1.0
62
+ Bohr radius.
63
+
64
+ Returns
65
+ -------
66
+ numpy.ndarray
67
+
68
+ Raises
69
+ ------
70
+ ValueError
71
+ If ``l >= n``.
72
+ """
73
+ if l >= n:
74
+ raise ValueError("Require l < n.")
75
+ rho = 2 * Z * r / (n * a0)
76
+ L = genlaguerre(n - l - 1, 2 * l + 1)(rho)
77
+ from scipy.special import gammaln
78
+
79
+ log_norm = 1.5 * np.log(2 * Z / (n * a0)) + 0.5 * (gammaln(n - l) - np.log(2 * n) - gammaln(n + l + 1))
80
+ norm = np.exp(log_norm)
81
+ return norm * np.exp(-rho / 2) * rho**l * L
82
+
83
+
84
+ @dataclass
85
+ class HydrogenOrbital:
86
+ r"""The hydrogenic wavefunction
87
+ :math:`\psi_{nlm}(r,\theta,\phi) = R_{nl}(r)\, Y_l^m(\theta,\phi)`.
88
+
89
+ Parameters
90
+ ----------
91
+ n : int
92
+ Principal quantum number.
93
+ l : int
94
+ Orbital angular momentum quantum number (:math:`0 \le l < n`).
95
+ m : int
96
+ Magnetic quantum number (:math:`\lvert m\rvert \le l`).
97
+ Z : int, default=1
98
+ Nuclear charge.
99
+ a0 : float, default=1.0
100
+ Bohr radius.
101
+
102
+ Raises
103
+ ------
104
+ ValueError
105
+ If the quantum numbers violate :math:`0 \le l < n` or
106
+ :math:`\lvert m\rvert \le l`.
107
+ """
108
+
109
+ n: int
110
+ l: int
111
+ m: int
112
+ Z: int = 1
113
+ a0: float = A0
114
+
115
+ def __post_init__(self):
116
+ if not (0 <= self.l < self.n):
117
+ raise ValueError("Require 0 <= l < n.")
118
+ if abs(self.m) > self.l:
119
+ raise ValueError("Require |m| <= l.")
120
+
121
+ @property
122
+ def energy(self) -> float:
123
+ r"""float: Energy :math:`E_n = -Z^2/(2n^2)` Hartree (atomic units,
124
+ :math:`\hbar = m_e = e = 1`)."""
125
+ return -(self.Z**2) / (2 * self.n**2)
126
+
127
+ def radial(self, r: np.ndarray) -> np.ndarray:
128
+ """The radial part :math:`R_{nl}(r)`; see :func:`radial_wavefunction`.
129
+
130
+ Parameters
131
+ ----------
132
+ r : numpy.ndarray
133
+
134
+ Returns
135
+ -------
136
+ numpy.ndarray
137
+ """
138
+ return radial_wavefunction(self.n, self.l, r, self.Z, self.a0)
139
+
140
+ def angular(self, theta: np.ndarray, phi: np.ndarray) -> np.ndarray:
141
+ """The angular part :math:`Y_l^m(\\theta,\\phi)`; see :func:`spherical_harmonic`.
142
+
143
+ Parameters
144
+ ----------
145
+ theta, phi : numpy.ndarray
146
+
147
+ Returns
148
+ -------
149
+ numpy.ndarray
150
+ """
151
+ return spherical_harmonic(self.l, self.m, theta, phi)
152
+
153
+ def psi(self, r: np.ndarray, theta: np.ndarray, phi: np.ndarray) -> np.ndarray:
154
+ r"""The full wavefunction :math:`\psi_{nlm}(r,\theta,\phi)`.
155
+
156
+ Parameters
157
+ ----------
158
+ r, theta, phi : numpy.ndarray
159
+
160
+ Returns
161
+ -------
162
+ numpy.ndarray
163
+ Complex-valued.
164
+ """
165
+ return self.radial(r) * self.angular(theta, phi)
166
+
167
+ def density(self, r: np.ndarray, theta: np.ndarray, phi: np.ndarray) -> np.ndarray:
168
+ r"""The probability density :math:`\lvert\psi_{nlm}\rvert^2`.
169
+
170
+ Parameters
171
+ ----------
172
+ r, theta, phi : numpy.ndarray
173
+
174
+ Returns
175
+ -------
176
+ numpy.ndarray
177
+ """
178
+ return np.abs(self.psi(r, theta, phi)) ** 2
179
+
180
+ def radial_density(self, r: np.ndarray) -> np.ndarray:
181
+ r"""The radial probability density :math:`P(r) = r^2 \lvert R_{nl}(r)\rvert^2`.
182
+
183
+ The probability of finding the electron in a shell
184
+ :math:`[r, r+dr]`, already integrated over solid angle.
185
+
186
+ Parameters
187
+ ----------
188
+ r : numpy.ndarray
189
+
190
+ Returns
191
+ -------
192
+ numpy.ndarray
193
+ """
194
+ return r**2 * np.abs(self.radial(r)) ** 2
195
+
196
+ def most_probable_radius(self, r_max: float | None = None, n_points: int = 20000) -> float:
197
+ """The radius at which :meth:`radial_density` is maximal.
198
+
199
+ Parameters
200
+ ----------
201
+ r_max : float or None, optional
202
+ Upper bound of the search range; defaults to a value scaled to
203
+ the orbital's expected extent.
204
+ n_points : int, default=20000
205
+ Number of grid points used for the search.
206
+
207
+ Returns
208
+ -------
209
+ float
210
+ """
211
+ if r_max is None:
212
+ r_max = 4 * self.n**2 * self.a0 / self.Z + 10
213
+ r = np.linspace(1e-6, r_max, n_points)
214
+ P = self.radial_density(r)
215
+ return float(r[np.argmax(P)])
216
+
217
+ def check_normalization(self, r_max: float | None = None, n_points: int = 20000) -> float:
218
+ r"""Integrate :meth:`radial_density` over :math:`[0, r_\text{max}]` (should be 1).
219
+
220
+ Parameters
221
+ ----------
222
+ r_max : float or None, optional
223
+ Upper integration limit; defaults to a value scaled to the
224
+ orbital's expected extent.
225
+ n_points : int, default=20000
226
+ Number of quadrature points.
227
+
228
+ Returns
229
+ -------
230
+ float
231
+ """
232
+ if r_max is None:
233
+ r_max = 6 * self.n**2 * self.a0 / self.Z + 20
234
+ r = np.linspace(1e-8, r_max, n_points)
235
+ return float(trapz(self.radial_density(r), r))
236
+
237
+
238
+ def orbital_superposition_psi(
239
+ orb_a: HydrogenOrbital, orb_b: HydrogenOrbital, r: np.ndarray, theta: np.ndarray, phi: np.ndarray, t: float, ca: complex = 2**-0.5, cb: complex = 2**-0.5
240
+ ) -> np.ndarray:
241
+ r"""A coherent superposition of two hydrogen eigenstates at time :math:`t`.
242
+
243
+ .. math::
244
+
245
+ \psi(t) = c_a\,\psi_a\, e^{-iE_a t} + c_b\,\psi_b\, e^{-iE_b t},
246
+
247
+ beating at the Bohr frequency :math:`\omega_{ab}=E_a-E_b` between the two
248
+ stationary densities -- genuine dynamics, unlike either eigenstate alone
249
+ (whose density is static).
250
+
251
+ Parameters
252
+ ----------
253
+ orb_a, orb_b : HydrogenOrbital
254
+ The two eigenstates in the superposition (should differ in energy
255
+ for the beating to be visible).
256
+ r, theta, phi : numpy.ndarray
257
+ Coordinates to evaluate at (e.g. from a Cartesian grid, as in
258
+ :func:`~physicskit.quantum.visualizers.orbitals.orbital_density_grid`).
259
+ t : float
260
+ Time.
261
+ ca, cb : complex, default=1/sqrt(2) each
262
+ Superposition amplitudes (renormalized internally).
263
+
264
+ Returns
265
+ -------
266
+ numpy.ndarray
267
+ Complex-valued :math:`\psi(r,\theta,\phi,t)`.
268
+ """
269
+ norm = np.sqrt(np.abs(ca) ** 2 + np.abs(cb) ** 2)
270
+ ca, cb = ca / norm, cb / norm
271
+ phase_a = np.exp(-1j * orb_a.energy * t)
272
+ phase_b = np.exp(-1j * orb_b.energy * t)
273
+ return ca * phase_a * orb_a.psi(r, theta, phi) + cb * phase_b * orb_b.psi(r, theta, phi)
274
+
275
+
276
+ def orbital_superposition_density(
277
+ orb_a: HydrogenOrbital, orb_b: HydrogenOrbital, r: np.ndarray, theta: np.ndarray, phi: np.ndarray, t: float, ca: complex = 2**-0.5, cb: complex = 2**-0.5
278
+ ) -> np.ndarray:
279
+ r"""The probability density of :func:`orbital_superposition_psi`.
280
+
281
+ Parameters
282
+ ----------
283
+ orb_a, orb_b : HydrogenOrbital
284
+ r, theta, phi : numpy.ndarray
285
+ t : float
286
+ ca, cb : complex, default=1/sqrt(2) each
287
+
288
+ Returns
289
+ -------
290
+ numpy.ndarray
291
+ """
292
+ return np.abs(orbital_superposition_psi(orb_a, orb_b, r, theta, phi, t, ca, cb)) ** 2
@@ -0,0 +1,350 @@
1
+ r"""Stark and Zeeman splitting, and Floquet analysis of periodically driven
2
+ quantum boxes (multiphoton resonance, photon-assisted tunneling).
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from dataclasses import dataclass
8
+
9
+ import numpy as np
10
+
11
+ from .._compat import trapz
12
+ from ..core.solvers import SplitOperatorSolver1D
13
+
14
+ __all__ = ["zeeman_splitting", "zeeman_spectrum", "linear_stark_shift", "stark_n2_quartet", "FloquetDrivenBox"]
15
+
16
+
17
+ # --- Zeeman effect -----------------------------------------------------------
18
+
19
+
20
+ def zeeman_splitting(m_l: int, m_s: float, B: float, mu_B: float = 1.0, g_s: float = 2.0, hbar: float = 1.0) -> float:
21
+ r"""First-order (weak-field, no spin-orbit) Zeeman energy shift.
22
+
23
+ .. math::
24
+
25
+ \Delta E = \mu_B B\,(m_l + g_s m_s),
26
+
27
+ in the :math:`\lvert l, m_l; s, m_s\rangle` basis.
28
+
29
+ Parameters
30
+ ----------
31
+ m_l : int
32
+ Orbital magnetic quantum number.
33
+ m_s : float
34
+ Spin magnetic quantum number.
35
+ B : float
36
+ Magnetic field strength.
37
+ mu_B : float, default=1.0
38
+ Bohr magneton.
39
+ g_s : float, default=2.0
40
+ Electron spin g-factor.
41
+ hbar : float, default=1.0
42
+ Value of :math:`\hbar` (unused in this first-order formula; kept
43
+ for API symmetry with other perturbation functions).
44
+
45
+ Returns
46
+ -------
47
+ float
48
+ """
49
+ return mu_B * B * (m_l + g_s * m_s)
50
+
51
+
52
+ def zeeman_spectrum(l: int, B: float, mu_B: float = 1.0, g_s: float = 2.0) -> np.ndarray:
53
+ r"""All :math:`(m_l, m_s)` sublevel shifts for orbital number :math:`l`, spin-1/2.
54
+
55
+ Parameters
56
+ ----------
57
+ l : int
58
+ Orbital angular momentum quantum number.
59
+ B : float
60
+ Magnetic field strength.
61
+ mu_B : float, default=1.0
62
+ Bohr magneton.
63
+ g_s : float, default=2.0
64
+ Electron spin g-factor.
65
+
66
+ Returns
67
+ -------
68
+ numpy.ndarray
69
+ Sorted array of :math:`2(2l+1)` energy shifts.
70
+ """
71
+ m_l_values = np.arange(-l, l + 1)
72
+ m_s_values = np.array([-0.5, 0.5])
73
+ shifts = np.array([zeeman_splitting(ml, ms, B, mu_B, g_s) for ml in m_l_values for ms in m_s_values])
74
+ return np.sort(shifts)
75
+
76
+
77
+ # --- Linear Stark effect (hydrogen, degenerate perturbation theory) --------
78
+
79
+
80
+ def linear_stark_shift(n: int, n1: int, n2: int, m: int, F: float, a0: float = 1.0) -> float:
81
+ r"""First-order Stark shift of a hydrogenic parabolic state.
82
+
83
+ For :math:`\lvert n, n_1, n_2, m\rangle` under a uniform field :math:`F`
84
+ along :math:`z`,
85
+
86
+ .. math::
87
+
88
+ \Delta E = \frac{3}{2}\, n\, (n_1 - n_2)\, a_0 F,
89
+
90
+ valid when :math:`n_1 + n_2 + \lvert m\rvert + 1 = n`. This linear-in-
91
+ :math:`F` splitting is a hallmark of hydrogen's "accidental"
92
+ :math:`l`-degeneracy (removed by any core penetration).
93
+
94
+ Parameters
95
+ ----------
96
+ n : int
97
+ Principal quantum number.
98
+ n1, n2 : int
99
+ Parabolic quantum numbers.
100
+ m : int
101
+ Magnetic quantum number.
102
+ F : float
103
+ Electric field strength.
104
+ a0 : float, default=1.0
105
+ Bohr radius.
106
+
107
+ Returns
108
+ -------
109
+ float
110
+
111
+ Raises
112
+ ------
113
+ ValueError
114
+ If ``n1 + n2 + abs(m) + 1 != n``.
115
+ """
116
+ if n1 + n2 + abs(m) + 1 != n:
117
+ raise ValueError("Parabolic quantum numbers must satisfy n1+n2+|m|+1=n.")
118
+ return 1.5 * n * (n1 - n2) * a0 * F
119
+
120
+
121
+ @dataclass
122
+ class StarkLevel:
123
+ """One sublevel returned by :func:`stark_n2_quartet`."""
124
+
125
+ n1: int
126
+ """int: Parabolic quantum number."""
127
+
128
+ n2: int
129
+ """int: Parabolic quantum number."""
130
+
131
+ m: int
132
+ """int: Magnetic quantum number."""
133
+
134
+ shift: float
135
+ """float: The first-order Stark energy shift."""
136
+
137
+
138
+ def stark_n2_quartet(F: float, a0: float = 1.0) -> list:
139
+ r"""The linear Stark splitting of hydrogen's :math:`n=2` shell.
140
+
141
+ The 4-fold degenerate :math:`n=2` level (2s, 2p0, :math:`2p_{\pm1}`)
142
+ splits under a field :math:`F` into three levels with shifts
143
+ :math:`\{-3a_0F, 0, 0, +3a_0F\}` -- the classic linear Stark quartet,
144
+ since only the :math:`m=0` pair (2s/2p0) is coupled by the perturbation.
145
+
146
+ Parameters
147
+ ----------
148
+ F : float
149
+ Electric field strength.
150
+ a0 : float, default=1.0
151
+ Bohr radius.
152
+
153
+ Returns
154
+ -------
155
+ list of StarkLevel
156
+ Sorted by energy shift.
157
+ """
158
+ levels = []
159
+ for n1 in range(2):
160
+ for n2 in range(2):
161
+ for m in (-1, 0, 1):
162
+ if n1 + n2 + abs(m) + 1 == 2:
163
+ levels.append(StarkLevel(n1, n2, m, linear_stark_shift(2, n1, n2, m, F, a0)))
164
+ return sorted(levels, key=lambda lv: lv.shift)
165
+
166
+
167
+ # --- Floquet-driven infinite box --------------------------------------------
168
+
169
+
170
+ class FloquetDrivenBox:
171
+ r"""An infinite square well :math:`[0,L]` driven by an AC dipole field.
172
+
173
+ .. math::
174
+
175
+ V(x,t) = V_0 (x - L/2) \cos(\omega t),
176
+
177
+ simulated with the FFT split-operator propagator. The box walls are
178
+ emulated with a steep confining potential outside :math:`[0,L]` padded
179
+ into a larger FFT domain.
180
+
181
+ Provides both time-domain propagation (to see multiphoton Rabi
182
+ oscillations / photon-assisted tunneling between box eigenstates) and
183
+ the Floquet quasi-energy spectrum from the one-period propagator
184
+ :math:`\hat U(T)`.
185
+
186
+ Parameters
187
+ ----------
188
+ L : float, default=1.0
189
+ Well width.
190
+ V0 : float, default=5.0
191
+ Driving field amplitude.
192
+ omega : float, default=20.0
193
+ Driving angular frequency :math:`\omega`.
194
+ hbar : float, default=1.0
195
+ Value of :math:`\hbar` to use.
196
+ m : float, default=1.0
197
+ Particle mass.
198
+ wall_height : float, default=5000.0
199
+ Height of the confining walls outside :math:`[0,L]`.
200
+ pad : float, default=0.4
201
+ Fractional padding of the FFT domain beyond :math:`[0,L]`.
202
+ n_grid : int, default=2048
203
+ Number of FFT grid points.
204
+ """
205
+
206
+ def __init__(
207
+ self,
208
+ L: float = 1.0,
209
+ V0: float = 5.0,
210
+ omega: float = 20.0,
211
+ hbar: float = 1.0,
212
+ m: float = 1.0,
213
+ wall_height: float = 5000.0,
214
+ pad: float = 0.4,
215
+ n_grid: int = 2048,
216
+ ):
217
+ self.L, self.V0, self.omega, self.hbar, self.m = L, V0, omega, hbar, m
218
+ self.x = np.linspace(-pad * L, (1 + pad) * L, n_grid)
219
+
220
+ def wall(x):
221
+ return np.where((x >= 0) & (x <= L), 0.0, wall_height)
222
+
223
+ self._wall = wall(self.x)
224
+
225
+ def V(x, t):
226
+ return wall(x) + V0 * (x - L / 2) * np.cos(omega * t)
227
+
228
+ self.V = V
229
+
230
+ def box_eigenstate(self, n: int) -> np.ndarray:
231
+ """The :math:`n`-th unperturbed infinite-well eigenstate on the grid.
232
+
233
+ Parameters
234
+ ----------
235
+ n : int
236
+ Quantum number (:math:`n=1,2,\\dots`).
237
+
238
+ Returns
239
+ -------
240
+ numpy.ndarray
241
+ """
242
+ psi = np.zeros_like(self.x)
243
+ inside = (self.x >= 0) & (self.x <= self.L)
244
+ psi[inside] = np.sqrt(2 / self.L) * np.sin(n * np.pi * self.x[inside] / self.L)
245
+ norm = np.sqrt(trapz(psi**2, self.x))
246
+ return psi / norm
247
+
248
+ def box_energy(self, n: int) -> float:
249
+ r"""Unperturbed box eigenenergy :math:`E_n = n^2\pi^2\hbar^2/(2mL^2)`.
250
+
251
+ Parameters
252
+ ----------
253
+ n : int
254
+
255
+ Returns
256
+ -------
257
+ float
258
+ """
259
+ return (n**2 * np.pi**2 * self.hbar**2) / (2 * self.m * self.L**2)
260
+
261
+ def make_solver(self, dt: float = 1e-4) -> SplitOperatorSolver1D:
262
+ """Build a :class:`~physicskit.quantum.core.solvers.SplitOperatorSolver1D` for this drive.
263
+
264
+ Parameters
265
+ ----------
266
+ dt : float, default=1e-4
267
+ Time step.
268
+
269
+ Returns
270
+ -------
271
+ physicskit.quantum.core.solvers.SplitOperatorSolver1D
272
+ """
273
+ return SplitOperatorSolver1D(self.x, self.V, hbar=self.hbar, m=self.m, dt=dt)
274
+
275
+ def transition_probability(self, n_initial: int, n_final: int, t_max: float, dt: float = 1e-4) -> tuple[np.ndarray, np.ndarray]:
276
+ r"""Multiphoton transition probability :math:`P_{i\to f}(t)`.
277
+
278
+ Propagates the ``n_initial`` box eigenstate under the AC drive and
279
+ returns its overlap probability with the ``n_final`` unperturbed
280
+ box eigenstate -- shows resonant multiphoton transitions when
281
+ :math:`\hbar\omega` (or a multiple) bridges the level gap.
282
+
283
+ Parameters
284
+ ----------
285
+ n_initial : int
286
+ Initial box quantum number.
287
+ n_final : int
288
+ Final box quantum number to project onto.
289
+ t_max : float
290
+ Total propagation time.
291
+ dt : float, default=1e-4
292
+ Time step.
293
+
294
+ Returns
295
+ -------
296
+ times : numpy.ndarray
297
+ probs : numpy.ndarray
298
+ :math:`P_{n_\text{initial}\to n_\text{final}}(t)`.
299
+ """
300
+ solver = self.make_solver(dt)
301
+ psi0 = self.box_eigenstate(n_initial).astype(complex)
302
+ n_steps = int(t_max / dt)
303
+ save_every = max(n_steps // 400, 1)
304
+ frames, times = solver.propagate(psi0, n_steps, save_every=save_every)
305
+
306
+ target = self.box_eigenstate(n_final)
307
+ probs = np.array([np.abs(trapz(np.conj(target) * f, self.x)) ** 2 for f in frames])
308
+ return times, probs
309
+
310
+ def floquet_quasienergies(self, n_levels: int = 4, dt: float = 1e-4) -> np.ndarray:
311
+ r"""Floquet quasi-energy spectrum from the one-period propagator.
312
+
313
+ Diagonalizes :math:`\hat U(T)` (:math:`T=2\pi/\omega`), restricted
314
+ to the span of the lowest ``n_levels`` box eigenstates, to obtain
315
+ quasi-energies
316
+
317
+ .. math::
318
+
319
+ \epsilon_k = -\frac{\hbar}{T}\arg(\lambda_k),
320
+
321
+ where :math:`\lambda_k` are the eigenvalues of :math:`\hat U(T)`.
322
+
323
+ Parameters
324
+ ----------
325
+ n_levels : int, default=4
326
+ Size of the truncated box-eigenstate basis.
327
+ dt : float, default=1e-4
328
+ Time step used to build :math:`\hat U(T)`.
329
+
330
+ Returns
331
+ -------
332
+ numpy.ndarray
333
+ Sorted quasi-energies, shape ``(n_levels,)``.
334
+ """
335
+ T = 2 * np.pi / self.omega
336
+ solver = self.make_solver(dt)
337
+ n_steps = int(round(T / dt))
338
+
339
+ basis = [self.box_eigenstate(n) for n in range(1, n_levels + 1)]
340
+ U = np.zeros((n_levels, n_levels), dtype=complex)
341
+ for j, psi0 in enumerate(basis):
342
+ psi = psi0.astype(complex)
343
+ for _ in range(n_steps):
344
+ psi = solver.step(psi)
345
+ for i, target in enumerate(basis):
346
+ U[i, j] = trapz(np.conj(target) * psi, self.x)
347
+
348
+ eigvals = np.linalg.eigvals(U)
349
+ quasi_energies = -(self.hbar / T) * np.angle(eigvals)
350
+ return np.sort(quasi_energies)