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,510 @@
1
+ """Gross-Pitaevskii mean-field theory for trapped, rotating Bose-Einstein condensates.
2
+
3
+ Solves the time-dependent Gross-Pitaevskii equation (GPE)
4
+
5
+ .. math::
6
+
7
+ i\\partial_t\\psi = \\Big[-\\tfrac{1}{2}\\nabla^2 + V(\\mathbf{r}) + g|\\psi|^2 - \\Omega L_z\\Big]\\psi
8
+
9
+ in the rotating frame (units :math:`\\hbar=m=1`) by imaginary-time
10
+ propagation (:math:`\\tau=it`), which turns the Schrodinger-like evolution
11
+ into a gradient flow that relaxes any initial state toward a stationary
12
+ point of the rotating-frame energy. The kinetic and potential/interaction
13
+ terms are each handled exactly in their natural representation (spectral
14
+ and real-space respectively, split-step); the angular-momentum term
15
+ :math:`\\Omega L_z` is advanced explicitly via centered finite differences,
16
+ which is non-stiff at the small imaginary-time steps used here.
17
+
18
+ A single quantized vortex, imprinted by multiplying the wavefunction by
19
+ :math:`(x-x_0)+i(y-y_0)`, is used throughout as the worked example of a
20
+ "vortex lattice" building block: :func:`gpe_relax` finds it as a genuine
21
+ stationary GPE solution, and comparing its rotating-frame energy against
22
+ the vortex-free ground state reproduces the standard textbook criterion
23
+ for the critical rotation frequency :math:`\\Omega_c` above which nucleating
24
+ a vortex lowers the energy.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import numpy as np
30
+
31
+ __all__ = [
32
+ "harmonic_trap_grid",
33
+ "gpe_imprint_vortex",
34
+ "gpe_relax",
35
+ "gpe_evolve",
36
+ "gpe_energy",
37
+ "count_vortices",
38
+ "casimir_mode_frequencies",
39
+ "casimir_energy_1d",
40
+ ]
41
+
42
+
43
+ def harmonic_trap_grid(n: int, length: float) -> tuple:
44
+ """Build a centered real-space and wavenumber grid for a 2D harmonic trap.
45
+
46
+ Parameters
47
+ ----------
48
+ n : int
49
+ Number of grid points along each axis.
50
+ length : float
51
+ Physical domain size (the domain is ``[-length/2, length/2)``).
52
+
53
+ Returns
54
+ -------
55
+ X, Y : ndarray, shape (n, n)
56
+ Real-space coordinate grids, centered at the trap origin.
57
+ KX, KY : ndarray, shape (n, n)
58
+ Wavenumber grids.
59
+ K2 : ndarray, shape (n, n)
60
+ :math:`K_X^2 + K_Y^2`.
61
+
62
+ Examples
63
+ --------
64
+ >>> X, Y, KX, KY, K2 = harmonic_trap_grid(32, 12.0)
65
+ >>> float(X[0, 0])
66
+ -6.0
67
+ """
68
+ x = np.linspace(-length / 2, length / 2, n, endpoint=False)
69
+ X, Y = np.meshgrid(x, x, indexing="ij")
70
+ k = 2 * np.pi * np.fft.fftfreq(n, d=length / n)
71
+ KX, KY = np.meshgrid(k, k, indexing="ij")
72
+ K2 = KX**2 + KY**2
73
+ return X, Y, KX, KY, K2
74
+
75
+
76
+ def gpe_imprint_vortex(psi: np.ndarray, X: np.ndarray, Y: np.ndarray, positions) -> np.ndarray:
77
+ """Imprint one singly-quantized vortex per position by multiplying in a phase winding.
78
+
79
+ Parameters
80
+ ----------
81
+ psi : ndarray of complex, shape (n, n)
82
+ Wavefunction to imprint onto.
83
+ X, Y : ndarray, shape (n, n)
84
+ Real-space coordinate grids from :func:`harmonic_trap_grid`.
85
+ positions : sequence of tuple(float, float)
86
+ ``(x0, y0)`` center of each vortex to imprint.
87
+
88
+ Returns
89
+ -------
90
+ ndarray of complex, shape (n, n)
91
+ ``psi`` multiplied by :math:`\\prod_i [(x-x_{0,i}) + i(y-y_{0,i})]`,
92
+ renormalized to preserve the input norm.
93
+
94
+ Examples
95
+ --------
96
+ >>> import numpy as np
97
+ >>> X, Y, KX, KY, K2 = harmonic_trap_grid(32, 12.0)
98
+ >>> psi0 = np.exp(-0.5 * (X ** 2 + Y ** 2)).astype(complex)
99
+ >>> psi = gpe_imprint_vortex(psi0, X, Y, [(0.0, 0.0)])
100
+ >>> bool(abs(psi[16, 16]) < 1e-10)
101
+ True
102
+ """
103
+ dx = X[1, 0] - X[0, 0]
104
+ norm0 = np.sum(np.abs(psi) ** 2) * dx * dx
105
+ out = psi.astype(complex).copy()
106
+ for x0, y0 in positions:
107
+ out = out * ((X - x0) + 1j * (Y - y0))
108
+ norm1 = np.sum(np.abs(out) ** 2) * dx * dx
109
+ return out * np.sqrt(norm0 / norm1)
110
+
111
+
112
+ def gpe_relax(
113
+ psi0: np.ndarray,
114
+ V: np.ndarray,
115
+ g: float,
116
+ dtau: float,
117
+ steps: int,
118
+ X: np.ndarray,
119
+ Y: np.ndarray,
120
+ K2: np.ndarray,
121
+ Omega: float = 0.0,
122
+ n_particles: float = 1.0,
123
+ ) -> np.ndarray:
124
+ """Relax a GPE initial condition toward a stationary state via imaginary-time propagation.
125
+
126
+ Parameters
127
+ ----------
128
+ psi0 : ndarray of complex, shape (n, n)
129
+ Initial wavefunction.
130
+ V : ndarray, shape (n, n)
131
+ External trapping potential.
132
+ g : float
133
+ Interaction (nonlinearity) strength.
134
+ dtau : float
135
+ Imaginary-time step.
136
+ steps : int
137
+ Number of steps to advance.
138
+ X, Y, K2 : ndarray, shape (n, n)
139
+ Grids from :func:`harmonic_trap_grid` (``KX``, ``KY`` are not needed here).
140
+ Omega : float, default=0.0
141
+ Rotation frequency of the trap.
142
+ n_particles : float, default=1.0
143
+ Total particle number; the wavefunction is renormalized to this
144
+ value after every step (imaginary-time propagation does not
145
+ conserve norm on its own).
146
+
147
+ Returns
148
+ -------
149
+ ndarray of complex, shape (n, n)
150
+ The relaxed (approximately stationary) wavefunction.
151
+
152
+ See Also
153
+ --------
154
+ gpe_energy : Evaluate the energy of a relaxed state.
155
+ gpe_imprint_vortex : Seed an initial condition with quantized vortices.
156
+
157
+ Notes
158
+ -----
159
+ Energy decreases monotonically under this propagation whenever it is
160
+ implemented correctly (a basic sanity check worth verifying on any new
161
+ potential or parameter regime).
162
+
163
+ Examples
164
+ --------
165
+ Comparing the rotating-frame energy of the vortex-free ground state
166
+ against a state seeded with one centered vortex reproduces the
167
+ standard vortex-nucleation criterion: :math:`\\Omega_c = \\Delta E/\\Delta L_z`,
168
+ above which the vortex state has lower energy in the rotating frame:
169
+
170
+ >>> import numpy as np
171
+ >>> n, length, g = 64, 12.0, 4.0
172
+ >>> X, Y, KX, KY, K2 = harmonic_trap_grid(n, length)
173
+ >>> V = 0.5 * (X ** 2 + Y ** 2)
174
+ >>> psi_vf = gpe_relax(np.exp(-0.5 * (X**2 + Y**2)).astype(complex), V, g, dtau=5e-4, steps=4000, X=X, Y=Y, K2=K2)
175
+ >>> psi0_v = gpe_imprint_vortex(np.exp(-0.5 * (X**2 + Y**2)).astype(complex), X, Y, [(0.0, 0.0)])
176
+ >>> psi_v = gpe_relax(psi0_v, V, g, dtau=5e-4, steps=4000, X=X, Y=Y, K2=K2)
177
+ >>> E0, E1 = gpe_energy(psi_vf, V, g, X, Y, K2), gpe_energy(psi_v, V, g, X, Y, K2)
178
+ >>> Omega_c = (E1["total"] - E0["total"]) / (E1["angular_momentum"] - E0["angular_momentum"])
179
+ >>> bool(0.0 < Omega_c < 1.0)
180
+ True
181
+ """
182
+ dx = X[1, 0] - X[0, 0]
183
+ psi = np.array(psi0, dtype=complex, copy=True)
184
+ norm = np.sum(np.abs(psi) ** 2) * dx * dx
185
+ psi *= np.sqrt(n_particles / norm)
186
+ for _ in range(steps):
187
+ psi *= np.exp(-dtau * (V + g * np.abs(psi) ** 2))
188
+ if Omega != 0.0:
189
+ dpsidx = (np.roll(psi, -1, axis=0) - np.roll(psi, 1, axis=0)) / (2 * dx)
190
+ dpsidy = (np.roll(psi, -1, axis=1) - np.roll(psi, 1, axis=1)) / (2 * dx)
191
+ psi = psi - 1j * dtau * Omega * (X * dpsidy - Y * dpsidx)
192
+ psi_hat = np.fft.fft2(psi)
193
+ psi_hat *= np.exp(-dtau * 0.5 * K2)
194
+ psi = np.fft.ifft2(psi_hat)
195
+ norm = np.sum(np.abs(psi) ** 2) * dx * dx
196
+ psi *= np.sqrt(n_particles / norm)
197
+ return psi
198
+
199
+
200
+ def gpe_evolve(psi0: np.ndarray, V: np.ndarray, g: float, dt: float, steps: int, K2: np.ndarray, snapshot_stride: int = 1) -> tuple:
201
+ """Real-time propagation of the 2D Gross-Pitaevskii / cubic NLS equation via split-step Fourier.
202
+
203
+ Solves :math:`i\\partial_t\\psi = [-\\tfrac{1}{2}\\nabla^2 + V + g|\\psi|^2]\\psi`
204
+ forward in *real* time (unlike :func:`gpe_relax`'s imaginary-time
205
+ relaxation, which only finds stationary states): the kinetic term is
206
+ exact in Fourier space, and the potential-plus-nonlinear term is exact
207
+ as a pointwise phase rotation in real space, the same split-step
208
+ structure as :func:`physicskit.fields.solitons.nls_evolve` generalized
209
+ to 2D and to an external potential. Real-time evolution is unitary and
210
+ conserves the norm on its own (no renormalization needed, unlike
211
+ imaginary time).
212
+
213
+ This one stepper serves two purposes, distinguished only by ``V`` and
214
+ the sign of ``g``:
215
+
216
+ - With a harmonic trap (``V = 0.5*(X**2+Y**2)``) and repulsive
217
+ interactions (``g > 0``), an off-center vortex genuinely precesses
218
+ around the trap under the density gradient -- real vortex dynamics,
219
+ as opposed to the static relaxed state :func:`gpe_relax` finds.
220
+ - With ``V = 0`` (or weak) and attractive interactions (``g < 0``
221
+ here, opposite sign convention from ``nls_evolve``'s ``g`` since this
222
+ module's equation carries a ``+g|psi|^2`` term), a sufficiently tall,
223
+ narrow initial packet self-focuses, concentrating into a narrower,
224
+ taller peak -- a numerical stand-in for wave collapse. True collapse
225
+ is a singularity in finite time; this integrator (like any
226
+ finite-grid scheme) cannot resolve it and the calculation should be
227
+ stopped once the peak density is still visibly growing, not carried
228
+ through the blow-up itself.
229
+
230
+ Parameters
231
+ ----------
232
+ psi0 : ndarray of complex, shape (n, n)
233
+ Initial wavefunction.
234
+ V : ndarray, shape (n, n)
235
+ External potential (use ``np.zeros_like`` for the free/collapse case).
236
+ g : float
237
+ Interaction strength and sign (see above).
238
+ dt : float
239
+ Time step.
240
+ steps : int
241
+ Number of steps to advance.
242
+ K2 : ndarray, shape (n, n)
243
+ Wavenumber-squared grid from :func:`harmonic_trap_grid`.
244
+ snapshot_stride : int, default=1
245
+ Record a snapshot every this many steps (plus the initial condition).
246
+
247
+ Returns
248
+ -------
249
+ snapshots : ndarray of complex, shape (n_recorded, n, n)
250
+ Wavefunction at ``t=0`` and after every recorded step.
251
+ times : ndarray, shape (n_recorded,)
252
+ Time of each recorded snapshot.
253
+
254
+ See Also
255
+ --------
256
+ gpe_relax : Imaginary-time relaxation to a stationary state.
257
+ physicskit.fields.solitons.nls_evolve : The 1D analog (opposite sign convention for ``g``).
258
+
259
+ Examples
260
+ --------
261
+ Norm is conserved under real-time evolution, unlike the imaginary-time
262
+ propagation in :func:`gpe_relax` (which requires explicit renormalization):
263
+
264
+ >>> import numpy as np
265
+ >>> n, length = 48, 12.0
266
+ >>> X, Y, KX, KY, K2 = harmonic_trap_grid(n, length)
267
+ >>> dxg = X[1, 0] - X[0, 0]
268
+ >>> V = 0.5 * (X ** 2 + Y ** 2)
269
+ >>> psi0 = np.exp(-0.5 * (X ** 2 + Y ** 2)).astype(complex)
270
+ >>> psi0 *= 1.0 / np.sqrt(np.sum(np.abs(psi0) ** 2) * dxg * dxg)
271
+ >>> snaps, times = gpe_evolve(psi0, V, g=2.0, dt=1e-3, steps=200, K2=K2, snapshot_stride=50)
272
+ >>> norms = np.sum(np.abs(snaps) ** 2, axis=(1, 2)) * dxg * dxg
273
+ >>> bool(np.max(np.abs(norms - norms[0])) < 1e-6)
274
+ True
275
+ """
276
+ psi = np.array(psi0, dtype=complex, copy=True)
277
+ lin_prop = np.exp(-1j * 0.5 * K2 * dt)
278
+ n_snap = steps // snapshot_stride + 1
279
+ snapshots = np.empty((n_snap, *psi.shape), dtype=complex)
280
+ times = np.empty(n_snap)
281
+ snapshots[0] = psi
282
+ times[0] = 0.0
283
+ idx = 1
284
+ for step in range(1, steps + 1):
285
+ psi_hat = np.fft.fft2(psi)
286
+ psi_hat *= lin_prop
287
+ psi = np.fft.ifft2(psi_hat)
288
+ psi *= np.exp(-1j * (V + g * np.abs(psi) ** 2) * dt)
289
+ if step % snapshot_stride == 0:
290
+ snapshots[idx] = psi
291
+ times[idx] = step * dt
292
+ idx += 1
293
+ return snapshots[:idx], times[:idx]
294
+
295
+
296
+ def gpe_energy(psi: np.ndarray, V: np.ndarray, g: float, X: np.ndarray, Y: np.ndarray, K2: np.ndarray) -> dict:
297
+ """Evaluate the energy and angular momentum of a GPE wavefunction.
298
+
299
+ Parameters
300
+ ----------
301
+ psi : ndarray of complex, shape (n, n)
302
+ Wavefunction.
303
+ V : ndarray, shape (n, n)
304
+ External trapping potential.
305
+ g : float
306
+ Interaction strength.
307
+ X, Y, K2 : ndarray, shape (n, n)
308
+ Grids from :func:`harmonic_trap_grid` (``KX``, ``KY`` are not needed here).
309
+
310
+ Returns
311
+ -------
312
+ dict
313
+ ``{"kinetic", "potential", "interaction", "angular_momentum", "total"}``,
314
+ where ``total`` is the lab-frame energy (kinetic + potential + interaction)
315
+ and ``angular_momentum`` is :math:`\\langle L_z \\rangle`. The
316
+ rotating-frame energy at rotation rate ``Omega`` is
317
+ ``total - Omega * angular_momentum``.
318
+
319
+ Examples
320
+ --------
321
+ >>> import numpy as np
322
+ >>> X, Y, KX, KY, K2 = harmonic_trap_grid(48, 10.0)
323
+ >>> V = 0.5 * (X ** 2 + Y ** 2)
324
+ >>> psi = np.exp(-0.5 * (X ** 2 + Y ** 2)).astype(complex)
325
+ >>> psi *= 1.0 / np.sqrt(np.sum(np.abs(psi) ** 2) * (X[1, 0] - X[0, 0]) ** 2)
326
+ >>> E = gpe_energy(psi, V, g=0.0, X=X, Y=Y, K2=K2)
327
+ >>> round(float(E["kinetic"] + E["potential"]), 4)
328
+ 1.0
329
+ """
330
+ dx = X[1, 0] - X[0, 0]
331
+ n = X.shape[0]
332
+ psi_hat = np.fft.fft2(psi)
333
+ kinetic = np.sum(0.5 * K2 * np.abs(psi_hat) ** 2) / n**2 * dx * dx
334
+ dens = np.abs(psi) ** 2
335
+ potential = np.sum(V * dens) * dx * dx
336
+ interaction = 0.5 * g * np.sum(dens**2) * dx * dx
337
+ dpsidx = (np.roll(psi, -1, axis=0) - np.roll(psi, 1, axis=0)) / (2 * dx)
338
+ dpsidy = (np.roll(psi, -1, axis=1) - np.roll(psi, 1, axis=1)) / (2 * dx)
339
+ angular_momentum = float(np.real(np.sum(np.conj(psi) * (-1j) * (X * dpsidy - Y * dpsidx))) * dx * dx)
340
+ total = kinetic + potential + interaction
341
+ return {"kinetic": kinetic, "potential": potential, "interaction": interaction, "angular_momentum": angular_momentum, "total": total}
342
+
343
+
344
+ def count_vortices(psi: np.ndarray, density_threshold: float = 0.05) -> np.ndarray:
345
+ """Locate quantized vortices by summing the phase winding around each grid plaquette.
346
+
347
+ Plaquettes in very low density regions are excluded, since the phase
348
+ of a near-zero-amplitude wavefunction is dominated by numerical noise
349
+ and produces spurious windings there.
350
+
351
+ A vortex core that sits exactly on a grid vertex (rather than strictly
352
+ inside a plaquette) can go undetected, since its circulation is then
353
+ split ambiguously between the four plaquettes touching that vertex; in
354
+ practice this is avoided by seeding vortices at positions not exactly
355
+ on the grid.
356
+
357
+ Parameters
358
+ ----------
359
+ psi : ndarray of complex, shape (n, n)
360
+ Wavefunction.
361
+ density_threshold : float, default=0.05
362
+ Plaquettes where :math:`|\\psi|^2` (relative to its maximum) falls
363
+ below this fraction are excluded from the search.
364
+
365
+ Returns
366
+ -------
367
+ ndarray of int, shape (n, n)
368
+ Integer winding number around each plaquette's corner ``(i, j)``;
369
+ nonzero entries mark a vortex core (``+1`` or ``-1`` for a
370
+ singly-quantized vortex/antivortex) enclosed by that plaquette.
371
+
372
+ Examples
373
+ --------
374
+ >>> import numpy as np
375
+ >>> X, Y, KX, KY, K2 = harmonic_trap_grid(48, 10.0)
376
+ >>> psi0 = np.exp(-0.5 * (X ** 2 + Y ** 2)).astype(complex)
377
+ >>> psi_vortex = gpe_imprint_vortex(psi0, X, Y, [(0.0, 0.0)])
378
+ >>> winding = count_vortices(psi_vortex)
379
+ >>> int(np.sum(np.abs(winding)))
380
+ 1
381
+ """
382
+ phase = np.angle(psi)
383
+ dphi_x = np.angle(np.exp(1j * (np.roll(phase, -1, axis=0) - phase)))
384
+ dphi_y = np.angle(np.exp(1j * (np.roll(phase, -1, axis=1) - phase)))
385
+ circ = dphi_x + np.roll(dphi_y, -1, axis=0) - np.roll(dphi_x, -1, axis=1) - dphi_y
386
+ winding = np.round(circ / (2 * np.pi)).astype(int)
387
+ dens = np.abs(psi) ** 2
388
+ mask = dens < density_threshold * dens.max()
389
+ winding[mask] = 0
390
+ return winding
391
+
392
+
393
+ # -- QFT vacuum fluctuations / Casimir effect (1D toy cavity) ----------------
394
+ #
395
+ # A simplified, standard textbook treatment, not a 3D electromagnetic
396
+ # calculation: a scalar field confined between two parallel "plates" a
397
+ # distance d apart has only the discrete standing-wave modes
398
+ # omega_n = n*pi*c/d (n=1,2,...) rather than a continuum, and the
399
+ # difference between this discrete zero-point sum and the continuum it
400
+ # approaches at large d is the (finite, physical) Casimir energy. The bare
401
+ # sum (1/2) * sum_n omega_n diverges and is regularized here by an
402
+ # exponential (Abel-summation) cutoff, exp(-omega_n * cutoff), with
403
+ # cutoff -> 0 taken as a limit; the leading cutoff^-2 divergence is the same
404
+ # one a plate-free continuum calculation would produce with the same
405
+ # regulator, so it is subtracted exactly (via the known Laurent expansion of
406
+ # the regularized sum) rather than fit numerically, leaving the finite,
407
+ # cutoff-independent remainder that is the physical (measurable) energy.
408
+
409
+
410
+ def casimir_mode_frequencies(d: float, c: float = 1.0, n_max: int = 200) -> np.ndarray:
411
+ """Discrete standing-wave mode frequencies of a 1D cavity of plate separation ``d``.
412
+
413
+ Parameters
414
+ ----------
415
+ d : float
416
+ Plate separation.
417
+ c : float, default=1.0
418
+ Wave speed (``=1`` in natural units; use the physical speed of
419
+ light for SI-unit frequencies).
420
+ n_max : int, default=200
421
+ Number of modes to return.
422
+
423
+ Returns
424
+ -------
425
+ ndarray, shape (n_max,)
426
+ :math:`\\omega_n = n\\pi c/d` for :math:`n=1,\\dots,n_{max}`.
427
+
428
+ See Also
429
+ --------
430
+ casimir_energy_1d : The regularized zero-point energy of this mode spectrum.
431
+
432
+ Examples
433
+ --------
434
+ >>> omega = casimir_mode_frequencies(d=2.0, c=1.0, n_max=3)
435
+ >>> [round(float(w), 4) for w in omega]
436
+ [1.5708, 3.1416, 4.7124]
437
+ """
438
+ n = np.arange(1, n_max + 1)
439
+ return n * np.pi * c / d
440
+
441
+
442
+ def casimir_energy_1d(d: float, c: float = 1.0, cutoff: float | None = None) -> float:
443
+ """Regularized zero-point (Casimir) energy of the discrete 1D cavity spectrum.
444
+
445
+ Uses the standard exponential-cutoff regularization: the sum
446
+ :math:`\\sum_n n x^n = x/(1-x)^2` (with :math:`x=e^{-a}`,
447
+ :math:`a=\\pi c\\,\\text{cutoff}/d`) has an exact closed form, so no
448
+ series truncation is needed. Its small-``cutoff`` (small-``a``)
449
+ expansion is :math:`\\tfrac{1}{4\\sinh^2(a/2)} = 1/a^2 - 1/12 + O(a^2)`;
450
+ the :math:`1/a^2` piece is the (unphysical, cutoff-scheme-dependent)
451
+ divergence that a continuum reference calculation regularized the same
452
+ way would also produce, so it is subtracted exactly, leaving the finite
453
+ remainder that survives as ``cutoff -> 0``:
454
+
455
+ .. math::
456
+
457
+ E(d) \\to -\\frac{\\pi c}{24 d}
458
+
459
+ the standard 1D massless-field Casimir energy (equivalently, the
460
+ Casimir energy of a CFT strip with central charge 1).
461
+
462
+ Parameters
463
+ ----------
464
+ d : float
465
+ Plate separation.
466
+ c : float, default=1.0
467
+ Wave speed.
468
+ cutoff : float, optional
469
+ Regulator scale. Defaults to ``1e-3 * d / c``. This subtraction is
470
+ a difference of two large, nearly-equal floating-point terms
471
+ (:math:`\\propto 1/\\text{cutoff}^2`), so making ``cutoff`` too
472
+ small *loses* precision to cancellation rather than gaining it;
473
+ ``1e-4*d/c`` to ``1e-2*d/c`` is the well-behaved range in double
474
+ precision.
475
+
476
+ Returns
477
+ -------
478
+ float
479
+ The regularized (finite, cutoff-subtracted) zero-point energy.
480
+
481
+ See Also
482
+ --------
483
+ casimir_mode_frequencies : The (bare, un-regularized) mode spectrum being summed.
484
+
485
+ Examples
486
+ --------
487
+ The cutoff-and-subtract result agrees with the known closed form
488
+ :math:`-\\pi c/(24d)`, and (within the well-behaved cutoff range noted
489
+ above) agrees more closely as the cutoff shrinks:
490
+
491
+ >>> d = 3.0
492
+ >>> exact = -np.pi * 1.0 / (24 * d)
493
+ >>> bool(abs(casimir_energy_1d(d, cutoff=3e-3 * d) - exact) < 1e-6)
494
+ True
495
+ >>> bool(abs(casimir_energy_1d(d, cutoff=7e-4 * d) - exact) < 1e-8)
496
+ True
497
+
498
+ The energy grows less negative (weaker confinement of vacuum energy)
499
+ as the plates separate, giving an attractive force :math:`-dE/dd < 0`:
500
+
501
+ >>> bool(casimir_energy_1d(1.0) < casimir_energy_1d(2.0) < 0)
502
+ True
503
+ """
504
+ if cutoff is None:
505
+ cutoff = 1e-3 * d / c
506
+ a = np.pi * c * cutoff / d
507
+ x = np.exp(-a)
508
+ E_reg = (np.pi * c) / (2 * d) * x / (1 - x) ** 2
509
+ divergent = d / (2 * np.pi * c * cutoff**2)
510
+ return float(E_reg - divergent)