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,135 @@
1
+ """Base class every ensemble in physicskit.rmt implements."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import ABC, abstractmethod
6
+
7
+ import numpy as np
8
+
9
+ from ..spectrum import Spectrum
10
+ from ..utils.random_state import as_generator
11
+
12
+
13
+ class MatrixEnsemble(ABC):
14
+ """A distribution over matrices (or, equivalently, over eigenvalue
15
+ tuples). Subclasses implement ``_sample_eigenvalues`` -- eigenvalues,
16
+ not dense matrices, are the primary product, since several ensembles
17
+ (the Gaussian beta-ensembles via the Dumitriu-Edelman tridiagonal
18
+ model) can produce exact-in-distribution eigenvalues far more
19
+ efficiently than forming and diagonalizing a dense matrix.
20
+
21
+ Mirrors the ``scipy.stats`` convention of a distribution object with
22
+ a ``.sample()``/``.rvs()``-style draw method, rather than a bare
23
+ generator function.
24
+ """
25
+
26
+ #: Dyson index; set by the subclass (either fixed, e.g. GOE.beta=1,
27
+ #: or passed at construction for continuum-beta ensembles).
28
+ beta: float | None = None
29
+
30
+ def __init__(self, n: int, seed: int | np.random.Generator | None = None) -> None:
31
+ """
32
+ Parameters
33
+ ----------
34
+ n : int
35
+ Matrix dimension.
36
+ seed : int, numpy.random.Generator, or None, optional
37
+ Seed for reproducible sampling. See
38
+ :func:`~physicskit.rmt.utils.random_state.as_generator`.
39
+ """
40
+ self.n = n
41
+ self.seed = seed
42
+ self._rng = as_generator(seed)
43
+
44
+ @abstractmethod
45
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
46
+ """Draw one realization's eigenvalues. Must return a 1-D array of
47
+ length ``self.n``.
48
+
49
+ Parameters
50
+ ----------
51
+ rng : numpy.random.Generator
52
+
53
+ Returns
54
+ -------
55
+ numpy.ndarray, shape (n,)
56
+ """
57
+ raise NotImplementedError # pragma: no cover -- unreachable: ABC blocks
58
+ # instantiating any subclass that doesn't override this abstract method,
59
+ # so this body can never actually run.
60
+
61
+ def _sample_eigenvalues_and_vectors(self, rng: np.random.Generator) -> tuple[np.ndarray, np.ndarray]:
62
+ """Draw one realization's eigenvalues AND eigenvectors (columns).
63
+ Optional: only ensembles that support eigenvector-level
64
+ statistics (e.g. the inverse participation ratio, see
65
+ ``physicskit.rmt.stats.localization``) override this. The default raises
66
+ NotImplementedError.
67
+
68
+ Parameters
69
+ ----------
70
+ rng : numpy.random.Generator
71
+
72
+ Returns
73
+ -------
74
+ eigenvalues : numpy.ndarray, shape (n,)
75
+ eigenvectors : numpy.ndarray, shape (m, n)
76
+ Column ``i`` is the eigenvector for ``eigenvalues[i]``.
77
+ """
78
+ raise NotImplementedError(
79
+ f"{type(self).__name__} does not support sample(return_eigenvectors=True) -- no _sample_eigenvalues_and_vectors implementation."
80
+ )
81
+
82
+ def sample(self, n_samples: int = 1, return_eigenvectors: bool = False) -> Spectrum:
83
+ """Draw ``n_samples`` independent realizations.
84
+
85
+ Parameters
86
+ ----------
87
+ n_samples : int, optional
88
+ Number of independent realizations to draw. Default 1.
89
+ return_eigenvectors : bool, optional
90
+ If True, also draw eigenvectors and attach them to the
91
+ returned ``Spectrum`` (see ``Spectrum.eigenvectors``).
92
+ Substantially more expensive in time and memory (O(n^2) per
93
+ sample instead of O(n)) and only supported by ensembles that
94
+ implement ``_sample_eigenvalues_and_vectors``; raises
95
+ NotImplementedError otherwise. Default False.
96
+
97
+ Returns
98
+ -------
99
+ Spectrum
100
+ """
101
+ if return_eigenvectors:
102
+ eig_rows = []
103
+ vec_rows = []
104
+ for _ in range(n_samples):
105
+ eigs, vecs = self._sample_eigenvalues_and_vectors(self._rng)
106
+ eig_rows.append(eigs)
107
+ vec_rows.append(vecs)
108
+ eigenvalues = np.stack(eig_rows)
109
+ eigenvectors: np.ndarray | None = np.stack(vec_rows)
110
+ else:
111
+ rows = [self._sample_eigenvalues(self._rng) for _ in range(n_samples)]
112
+ eigenvalues = np.stack(rows) # dtype (real or complex) inferred automatically;
113
+ # also accommodates ensembles whose eigenvalue count isn't exactly
114
+ # self.n (e.g. GinSE, which returns 2*n genuinely distinct
115
+ # conjugate-paired eigenvalues per sample -- see ensembles/ginibre.py).
116
+ eigenvectors = None
117
+ return Spectrum(
118
+ eigenvalues=eigenvalues,
119
+ n=self.n,
120
+ beta=self.beta,
121
+ ensemble=type(self).__name__,
122
+ scale=self.natural_scale(),
123
+ eigenvectors=eigenvectors,
124
+ )
125
+
126
+ def natural_scale(self) -> float:
127
+ """Factor by which raw eigenvalues should be divided to reach the
128
+ ensemble's standard asymptotic normalization. Default: no rescaling;
129
+ subclasses override where a known theoretical scale applies.
130
+
131
+ Returns
132
+ -------
133
+ float
134
+ """
135
+ return 1.0
@@ -0,0 +1,218 @@
1
+ """Bogoliubov-de Gennes (BdG) / Altland-Zirnbauer superconductor classes:
2
+ D, C, CI, DIII.
3
+
4
+ These extend Dyson's threefold way (classes A, AI, AII) by adding
5
+ particle-hole (charge-conjugation) symmetry, appropriate to
6
+ non-interacting fermionic Hamiltonians in disordered/chaotic
7
+ superconductors. Together with the threefold way and the three chiral
8
+ classes (AIII, BDI, CII -- QCD-type, realized elsewhere in this package
9
+ via the Wishart/Laguerre singular-value connection), these four complete
10
+ Altland and Zirnbauer's "tenfold way".
11
+
12
+ References
13
+ ----------
14
+ A. Altland, M. R. Zirnbauer, "Nonstandard symmetry classes in
15
+ mesoscopic normal-superconducting hybrid structures", Phys. Rev. B 55
16
+ (1997) 1142.
17
+ M. A. Stephanov, J. J. M. Verbaarschot, T. Wettig, "Random Matrices"
18
+ (Wiley Encyclopedia of Electrical and Electronics Engineering, 2005),
19
+ arXiv:hep-ph/0509286 -- the block structure and (alpha, beta) table for
20
+ classes D and C used here.
21
+ M. Stolz, "Fluctuations of Wigner-type random matrices associated with
22
+ symmetric spaces of class DIII and CI", arXiv:1707.03793 -- the
23
+ explicit, unambiguous matrix-space definitions for DIII and CI used
24
+ here (Section 2), stated in purely mathematical terms independent of
25
+ any physics convention.
26
+
27
+ Construction
28
+ ------------
29
+ All four classes have the :math:`2N \\times 2N` Hermitian block structure
30
+
31
+ .. math::
32
+
33
+ H = \\begin{pmatrix} A & B \\\\ B^\\dagger & -A^T \\end{pmatrix}
34
+
35
+ (class D, C) or, equivalently in the special case where :math:`B`
36
+ happens to equal its own conjugate transpose (true for the specific
37
+ reality/symmetry combinations used in CI and DIII),
38
+
39
+ .. math::
40
+
41
+ H = \\begin{pmatrix} X_1 & X_2 \\\\ X_2 & -X_1 \\end{pmatrix}
42
+
43
+ (class CI, DIII), where::
44
+
45
+ Class D (beta=2): A complex Hermitian (N x N), B complex antisymmetric.
46
+ Class C (beta=2): A complex Hermitian (N x N), B complex symmetric.
47
+ Class CI (beta=1): X1, X2 real symmetric (N x N) -- H is real symmetric.
48
+ Class DIII (beta=4): X1, X2 purely imaginary skew-symmetric (N x N)
49
+ -- i.e. i times a real antisymmetric matrix,
50
+ which is itself Hermitian.
51
+
52
+ or, in symmetry-constraint form,
53
+
54
+ .. math::
55
+
56
+ \\text{D: } A^\\dagger = A,\\ B^T = -B \\qquad
57
+ \\text{C: } A^\\dagger = A,\\ B^T = B
58
+
59
+ .. math::
60
+
61
+ \\text{CI: } X_1^T = X_1,\\ X_2^T = X_2,\\ X_1, X_2 \\in \\mathbb{R} \\qquad
62
+ \\text{DIII: } X_1^T = -X_1,\\ X_2^T = -X_2,\\ X_1, X_2 \\in i\\mathbb{R}
63
+
64
+ This block structure has a built-in particle-hole (charge-conjugation)
65
+ symmetry
66
+
67
+ .. math::
68
+
69
+ \\mathcal{C} H \\mathcal{C}^{-1} = -H, \\qquad
70
+ \\mathcal{C} = \\tau_x \\mathcal{K}, \\qquad
71
+ \\tau_x = \\begin{pmatrix} 0 & I_N \\\\ I_N & 0 \\end{pmatrix}
72
+
73
+ (:math:`\\mathcal{K}` complex conjugation) that forces the spectrum to be
74
+ symmetric about zero: if :math:`\\lambda` is an eigenvalue, so is
75
+ :math:`-\\lambda`. This is NOT a degeneracy (unlike the Kramers doubling
76
+ in GSE/CSE) -- :math:`\\lambda` and :math:`-\\lambda` are generically
77
+ distinct eigenvalues. Verified during development: all four
78
+ constructions are exactly Hermitian (to machine precision) and exhibit
79
+ this :math:`\\pm\\lambda` pairing to machine precision -- see
80
+ ``tests/test_bdg.py``. Going further (validating the exact bulk/edge
81
+ eigenvalue density, which follows Laguerre-type statistics in the
82
+ variable :math:`\\lambda^2` per the :math:`(\\alpha, \\beta)` table in
83
+ Stephanov-Verbaarschot-Wettig) is deferred; only the structural
84
+ properties above are validated here.
85
+ """
86
+
87
+ import numpy as np
88
+
89
+ from .base import MatrixEnsemble
90
+
91
+
92
+ def _dense_hermitian(n: int, rng: np.random.Generator, complex_entries: bool) -> np.ndarray:
93
+ if complex_entries:
94
+ x = (rng.standard_normal((n, n)) + 1j * rng.standard_normal((n, n))) / np.sqrt(2.0)
95
+ return (x + x.conj().T) / 2.0
96
+ x = rng.standard_normal((n, n))
97
+ return (x + x.T) / np.sqrt(2.0)
98
+
99
+
100
+ def _dense_symmetric(n: int, rng: np.random.Generator, complex_entries: bool) -> np.ndarray:
101
+ if complex_entries:
102
+ x = (rng.standard_normal((n, n)) + 1j * rng.standard_normal((n, n))) / np.sqrt(2.0)
103
+ else:
104
+ x = rng.standard_normal((n, n))
105
+ return (x + x.T) / np.sqrt(2.0)
106
+
107
+
108
+ def _dense_antisymmetric(n: int, rng: np.random.Generator, complex_entries: bool) -> np.ndarray:
109
+ if complex_entries:
110
+ x = (rng.standard_normal((n, n)) + 1j * rng.standard_normal((n, n))) / np.sqrt(2.0)
111
+ else:
112
+ x = rng.standard_normal((n, n))
113
+ return (x - x.T) / np.sqrt(2.0)
114
+
115
+
116
+ class BdGClassD(MatrixEnsemble):
117
+ """Altland-Zirnbauer class D (beta=2).
118
+
119
+ .. math::
120
+
121
+ H = \\begin{pmatrix} A & B \\\\ B^\\dagger & -A^T \\end{pmatrix},
122
+ \\qquad A^\\dagger = A,\\ \\ B^T = -B
123
+
124
+ with :math:`A` complex Hermitian and :math:`B` complex antisymmetric
125
+ (both :math:`N \\times N`). ``n`` is the block size :math:`N`; each
126
+ sample is a :math:`2N \\times 2N` Hermitian matrix with :math:`2N`
127
+ eigenvalues occurring in :math:`\\pm\\lambda` pairs."""
128
+
129
+ beta: float = 2
130
+
131
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
132
+ n = self.n
133
+ a = _dense_hermitian(n, rng, complex_entries=True)
134
+ b = _dense_antisymmetric(n, rng, complex_entries=True)
135
+ h = np.block([[a, b], [b.conj().T, -a.T]])
136
+ h = (h + h.conj().T) / 2.0 # symmetrize away numerical asymmetry
137
+ return np.linalg.eigvalsh(h)
138
+
139
+ def natural_scale(self) -> float:
140
+ return np.sqrt(self.n)
141
+
142
+
143
+ class BdGClassC(MatrixEnsemble):
144
+ """Altland-Zirnbauer class C (beta=2).
145
+
146
+ .. math::
147
+
148
+ H = \\begin{pmatrix} A & B \\\\ B^\\dagger & -A^T \\end{pmatrix},
149
+ \\qquad A^\\dagger = A,\\ \\ B^T = B
150
+
151
+ with :math:`A` complex Hermitian and :math:`B` complex symmetric
152
+ (both :math:`N \\times N`). ``n`` is the block size :math:`N`; each
153
+ sample is a :math:`2N \\times 2N` Hermitian matrix with :math:`2N`
154
+ eigenvalues occurring in :math:`\\pm\\lambda` pairs."""
155
+
156
+ beta: float = 2
157
+
158
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
159
+ n = self.n
160
+ a = _dense_hermitian(n, rng, complex_entries=True)
161
+ b = _dense_symmetric(n, rng, complex_entries=True)
162
+ h = np.block([[a, b], [b.conj().T, -a.T]])
163
+ h = (h + h.conj().T) / 2.0
164
+ return np.linalg.eigvalsh(h)
165
+
166
+ def natural_scale(self) -> float:
167
+ return np.sqrt(self.n)
168
+
169
+
170
+ class BdGClassCI(MatrixEnsemble):
171
+ """Altland-Zirnbauer class CI (beta=1).
172
+
173
+ .. math::
174
+
175
+ H = \\begin{pmatrix} X_1 & X_2 \\\\ X_2 & -X_1 \\end{pmatrix},
176
+ \\qquad X_1^T = X_1,\\ \\ X_2^T = X_2,\\ \\ X_1, X_2 \\in \\mathbb{R}^{N \\times N}
177
+
178
+ so :math:`H` is real symmetric (:math:`2N \\times 2N`)."""
179
+
180
+ beta: float = 1
181
+
182
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
183
+ n = self.n
184
+ x1 = _dense_symmetric(n, rng, complex_entries=False)
185
+ x2 = _dense_symmetric(n, rng, complex_entries=False)
186
+ h = np.block([[x1, x2], [x2, -x1]])
187
+ h = (h + h.T) / 2.0
188
+ return np.linalg.eigvalsh(h)
189
+
190
+ def natural_scale(self) -> float:
191
+ return np.sqrt(self.n)
192
+
193
+
194
+ class BdGClassDIII(MatrixEnsemble):
195
+ """Altland-Zirnbauer class DIII (beta=4).
196
+
197
+ .. math::
198
+
199
+ H = \\begin{pmatrix} X_1 & X_2 \\\\ X_2 & -X_1 \\end{pmatrix},
200
+ \\qquad X_1 = iY_1,\\ X_2 = iY_2,\\ \\ Y_1^T = -Y_1,\\ Y_2^T = -Y_2,\\ \\ Y_1, Y_2 \\in \\mathbb{R}^{N \\times N}
201
+
202
+ i.e. :math:`X_1, X_2` are purely imaginary skew-symmetric
203
+ (:math:`N \\times N`, hence themselves Hermitian). :math:`H` is
204
+ complex Hermitian (:math:`2N \\times 2N`)."""
205
+
206
+ beta: float = 4
207
+
208
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
209
+ n = self.n
210
+ y1 = _dense_antisymmetric(n, rng, complex_entries=False)
211
+ y2 = _dense_antisymmetric(n, rng, complex_entries=False)
212
+ x1, x2 = 1j * y1, 1j * y2
213
+ h = np.block([[x1, x2], [x2, -x1]])
214
+ h = (h + h.conj().T) / 2.0
215
+ return np.linalg.eigvalsh(h)
216
+
217
+ def natural_scale(self) -> float:
218
+ return np.sqrt(self.n)
@@ -0,0 +1,308 @@
1
+ """Chiral ensembles -- chGOE, chGUE, chGSE (Altland-Zirnbauer classes
2
+ BDI, AIII, CII): block off-diagonal Hamiltonians with an anticommuting
3
+ chiral symmetry, the QCD-type ("Dirac operator") random matrix ensembles
4
+ of Verbaarschot and Zahed. Together with the threefold way (A, AI, AII,
5
+ realized in ``physicskit.rmt.ensembles.gaussian``) and the four BdG classes
6
+ (``physicskit.rmt.ensembles.bdg``), these complete Altland-Zirnbauer's "tenfold
7
+ way".
8
+
9
+ References
10
+ ----------
11
+ J. J. M. Verbaarschot, I. Zahed, "Spectral density of the QCD Dirac
12
+ operator near zero virtuality", Phys. Rev. Lett. 70 (1993) 3852.
13
+ J. J. M. Verbaarschot, "The spectrum of the QCD Dirac operator and
14
+ chiral random matrix theory", Phys. Rev. Lett. 72 (1994) 2531.
15
+ A. Altland, M. R. Zirnbauer, "Nonstandard symmetry classes in
16
+ mesoscopic normal-superconducting hybrid structures", Phys. Rev. B 55
17
+ (1997) 1142 -- classes BDI, AIII, CII within the tenfold way.
18
+ M. A. Stephanov, J. J. M. Verbaarschot, T. Wettig, "Random Matrices",
19
+ arXiv:hep-ph/0509286 -- the chiral <-> Wishart/Laguerre equivalence
20
+ used here.
21
+
22
+ Construction
23
+ ------------
24
+ A chiral Hamiltonian has the block off-diagonal form
25
+
26
+ .. math::
27
+
28
+ H = \\begin{pmatrix} 0 & W \\\\ W^\\dagger & 0 \\end{pmatrix}
29
+
30
+ where :math:`W` is a rectangular :math:`N \\times (N+\\nu)` matrix
31
+ (:math:`\\nu \\geq 0` the topological index -- the number of exact zero
32
+ modes, i.e. the QCD Dirac operator's index), drawn with i.i.d. entries
33
+ from the Dyson symmetry class matching beta: real (beta=1, class BDI,
34
+ chGOE), complex (beta=2, class AIII, chGUE), or quaternionic (beta=4,
35
+ class CII, chGSE). :math:`H` is Hermitian by construction and
36
+ anticommutes with the chiral "gamma_5" operator
37
+ :math:`\\Gamma = \\mathrm{diag}(I_N, -I_{N+\\nu})`:
38
+
39
+ .. math::
40
+
41
+ \\Gamma H \\Gamma = -H
42
+
43
+ -- the defining symmetry of this class (verified directly, to machine
44
+ precision, in ``tests/test_chiral.py``), forcing the spectrum to be
45
+ exactly symmetric about zero -- like BdG's particle-hole symmetry
46
+ (``physicskit.rmt.ensembles.bdg``), but via an ANTIcommuting rather than a
47
+ commuting operator, and via a block off-diagonal rather than a block
48
+ diagonal-plus-symmetric structure.
49
+
50
+ Because
51
+
52
+ .. math::
53
+
54
+ H^2 = \\begin{pmatrix} WW^\\dagger & 0 \\\\ 0 & W^\\dagger W \\end{pmatrix},
55
+
56
+ :math:`H`'s nonzero eigenvalues are exactly :math:`\\pm\\sigma_k`, the
57
+ singular values of :math:`W` -- and :math:`W^\\dagger W` is EXACTLY a
58
+ beta-Wishart/Laguerre matrix (``physicskit.rmt.ensembles.wishart``).
59
+ This is why the chiral ensembles need no new sampling machinery: unlike
60
+ BdG, which needed genuinely new dense constructions, chiral eigenvalues
61
+ are generated here by reusing
62
+ ``physicskit.rmt.utils.tridiagonal.sample_laguerre_beta_eigenvalues`` directly
63
+ and taking its square root -- exact in distribution (via the same
64
+ Dumitriu-Edelman generalized-beta mechanism used by
65
+ ``HermiteBetaEnsemble``/``LaguerreBetaEnsemble``), without ever forming
66
+ or diagonalizing a dense matrix. This also means that, exactly as
67
+ ``HermiteBetaEnsemble``'s GSE (beta=4) returns n eigenvalues (not the 2n
68
+ a dense quaternion embedding would give -- see
69
+ ``physicskit.rmt.ensembles.ginibre``'s GinSE for that contrast), the chiral
70
+ ensembles here return ``n`` +-sigma pairs at every beta, including 4 --
71
+ NOT a doubled count from an explicit quaternion embedding.
72
+
73
+ The ``nu`` exact zero eigenvalues (the topological zero modes) are
74
+ appended directly, since W^dagger @ W (an (N+nu) x (N+nu) matrix of rank
75
+ <= N) has exactly ``nu`` zero eigenvalues whenever nu > 0 -- not merely
76
+ small, exactly zero, reflecting the index-theorem structure underlying
77
+ this construction (the same reason a private ``_dense_chiral_hamiltonian``
78
+ helper below, used only for direct structural verification in the test
79
+ suite, checks this on the literal block matrix rather than trusting it
80
+ transitively from the Laguerre connection).
81
+
82
+ Since ``sample_laguerre_beta_eigenvalues`` already returns
83
+ Marchenko-Pastur-normalized eigenvalues (support
84
+ [(1-sqrt(gamma))^2, (1+sqrt(gamma))^2], gamma = n/(n+nu)),
85
+ ``natural_scale`` is 1.0 here too (matching
86
+ ``LaguerreBetaEnsemble.natural_scale``): the nonzero +-sigma_k already
87
+ lie in [-(1+sqrt(gamma)), -(1-sqrt(gamma))] union
88
+ [(1-sqrt(gamma)), (1+sqrt(gamma))].
89
+
90
+ Two eigenvalue-convention presentations
91
+ ----------------------------------------
92
+ ``ChiralBetaEnsemble``/``chGOE``/``chGUE``/``chGSE`` present the HERMITIAN
93
+ gamma_5-Hamiltonian :math:`H` (real eigenvalues :math:`\\pm\\sigma_k` and
94
+ :math:`\\nu` exact zeros). The lattice-QCD and chiral-random-matrix-theory
95
+ literature, however, usually works directly with the (anti-Hermitian)
96
+ EUCLIDEAN DIRAC OPERATOR :math:`D`, related to :math:`H` by
97
+
98
+ .. math::
99
+
100
+ D = iH,
101
+
102
+ whose eigenvalues are therefore purely imaginary: :math:`\\pm i\\sigma_k`
103
+ (the nonzero "virtualities") plus :math:`\\nu` exact zero modes.
104
+ ``QCDDiracEnsemble``/``QCDDiracGOE``/``QCDDiracGUE``/
105
+ ``QCDDiracGSE`` below provide exactly this presentation -- a thin
106
+ wrapper multiplying ``ChiralBetaEnsemble``'s eigenvalues by ``i``, not a
107
+ mathematically distinct construction, provided purely so the eigenvalue
108
+ convention matches what papers in that literature actually plot
109
+ (Im(lambda_n), the Dirac spectral density rho(lambda)) without the
110
+ caller having to remember to do the rotation themselves.
111
+ """
112
+
113
+ from __future__ import annotations
114
+
115
+ import numpy as np
116
+
117
+ from ..utils.tridiagonal import sample_laguerre_beta_eigenvalues
118
+ from .base import MatrixEnsemble
119
+
120
+
121
+ class ChiralBetaEnsemble(MatrixEnsemble):
122
+ """General beta-chiral ensemble (block off-diagonal, QCD-type Dirac
123
+ operator random matrix).
124
+
125
+ .. math::
126
+
127
+ H = \\begin{pmatrix} 0 & W \\\\ W^\\dagger & 0 \\end{pmatrix},
128
+ \\qquad \\Gamma H \\Gamma = -H,
129
+ \\qquad \\Gamma = \\mathrm{diag}(I_N, -I_{N+\\nu})
130
+
131
+ beta=1, 2, 4 recover chGOE, chGUE, chGSE (Altland-Zirnbauer classes
132
+ BDI, AIII, CII) exactly; any beta > 0 is a valid continuum
133
+ generalization (inherited from the underlying beta-Laguerre
134
+ construction).
135
+
136
+ Parameters
137
+ ----------
138
+ n : int
139
+ Number of nonzero +-sigma eigenvalue pairs (the smaller block
140
+ dimension N).
141
+ beta : float
142
+ Dyson index.
143
+ nu : int, optional
144
+ Topological index: number of exact zero eigenvalues (default
145
+ 0). The larger block dimension is N + nu.
146
+ """
147
+
148
+ def __init__(
149
+ self,
150
+ n: int,
151
+ beta: float,
152
+ nu: int = 0,
153
+ seed: int | np.random.Generator | None = None,
154
+ ) -> None:
155
+ if beta <= 0:
156
+ raise ValueError(f"beta must be positive, got {beta}")
157
+ if nu < 0:
158
+ raise ValueError(f"nu (topological index) must be >= 0, got {nu}")
159
+ super().__init__(n, seed=seed)
160
+ self.beta: float = float(beta)
161
+ self.nu = nu
162
+
163
+ @property
164
+ def gamma(self) -> float:
165
+ """Aspect ratio :math:`\\gamma = n/(n+\\nu)` controlling the
166
+ Marchenko-Pastur-derived support :math:`[(1-\\sqrt{\\gamma})^2,
167
+ (1+\\sqrt{\\gamma})^2]` of the nonzero :math:`\\pm\\sigma` eigenvalues."""
168
+ return self.n / (self.n + self.nu)
169
+
170
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
171
+ m = self.n + self.nu
172
+ squared_singular_values = sample_laguerre_beta_eigenvalues(m, self.n, self.beta, rng)
173
+ sigma = np.sqrt(squared_singular_values)
174
+ zero_modes = np.zeros(self.nu)
175
+ return np.concatenate([-sigma, zero_modes, sigma])
176
+
177
+ def natural_scale(self) -> float:
178
+ return 1.0
179
+
180
+
181
+ class chGOE(ChiralBetaEnsemble):
182
+ """Chiral Orthogonal Ensemble (beta=1, Altland-Zirnbauer class BDI).
183
+
184
+ .. math::
185
+
186
+ H = \\begin{pmatrix} 0 & W \\\\ W^T & 0 \\end{pmatrix}, \\qquad W \\in \\mathbb{R}^{N \\times (N+\\nu)}
187
+
188
+ real block off-diagonal Hamiltonian (:math:`W` real)."""
189
+
190
+ def __init__(self, n: int, nu: int = 0, seed: int | np.random.Generator | None = None) -> None:
191
+ super().__init__(n, beta=1, nu=nu, seed=seed)
192
+
193
+
194
+ class chGUE(ChiralBetaEnsemble):
195
+ """Chiral Unitary Ensemble (beta=2, Altland-Zirnbauer class AIII).
196
+
197
+ .. math::
198
+
199
+ H = \\begin{pmatrix} 0 & W \\\\ W^\\dagger & 0 \\end{pmatrix}, \\qquad W \\in \\mathbb{C}^{N \\times (N+\\nu)}
200
+
201
+ complex block off-diagonal Hamiltonian (:math:`W` complex) -- the
202
+ QCD Dirac operator random matrix ensemble of Verbaarschot-Zahed."""
203
+
204
+ def __init__(self, n: int, nu: int = 0, seed: int | np.random.Generator | None = None) -> None:
205
+ super().__init__(n, beta=2, nu=nu, seed=seed)
206
+
207
+
208
+ class chGSE(ChiralBetaEnsemble):
209
+ """Chiral Symplectic Ensemble (beta=4, Altland-Zirnbauer class CII).
210
+
211
+ .. math::
212
+
213
+ H = \\begin{pmatrix} 0 & W \\\\ W^\\dagger & 0 \\end{pmatrix}, \\qquad W \\in \\mathbb{H}^{N \\times (N+\\nu)}
214
+
215
+ quaternionic block off-diagonal Hamiltonian (:math:`W` quaternionic)."""
216
+
217
+ def __init__(self, n: int, nu: int = 0, seed: int | np.random.Generator | None = None) -> None:
218
+ super().__init__(n, beta=4, nu=nu, seed=seed)
219
+
220
+
221
+ class QCDDiracEnsemble(ChiralBetaEnsemble):
222
+ """The QCD Dirac operator
223
+
224
+ .. math::
225
+
226
+ D = iH
227
+
228
+ in the anti-Hermitian convention standard in the lattice-QCD and
229
+ chiral-random-matrix literature (Verbaarschot-Zahed): eigenvalues
230
+ are purely imaginary, :math:`\\pm i\\sigma_k` plus :math:`\\nu` exact
231
+ zero modes, rather than ``ChiralBetaEnsemble``'s real
232
+ :math:`\\pm\\sigma_k` -- see the module docstring section "Two
233
+ eigenvalue-convention presentations". Parameters are identical to
234
+ ``ChiralBetaEnsemble``.
235
+ """
236
+
237
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
238
+ return 1j * super()._sample_eigenvalues(rng)
239
+
240
+
241
+ class QCDDiracGOE(QCDDiracEnsemble):
242
+ """QCD Dirac operator built on chGOE (beta=1, class BDI): real
243
+ coupling block W, purely imaginary Dirac eigenvalues."""
244
+
245
+ def __init__(self, n: int, nu: int = 0, seed: int | np.random.Generator | None = None) -> None:
246
+ super().__init__(n, beta=1, nu=nu, seed=seed)
247
+
248
+
249
+ class QCDDiracGUE(QCDDiracEnsemble):
250
+ """QCD Dirac operator built on chGUE (beta=2, class AIII): complex
251
+ coupling block W, purely imaginary Dirac eigenvalues -- the
252
+ Verbaarschot-Zahed QCD Dirac operator ensemble in its standard
253
+ anti-Hermitian presentation."""
254
+
255
+ def __init__(self, n: int, nu: int = 0, seed: int | np.random.Generator | None = None) -> None:
256
+ super().__init__(n, beta=2, nu=nu, seed=seed)
257
+
258
+
259
+ class QCDDiracGSE(QCDDiracEnsemble):
260
+ """QCD Dirac operator built on chGSE (beta=4, class CII):
261
+ quaternionic coupling block W, purely imaginary Dirac eigenvalues."""
262
+
263
+ def __init__(self, n: int, nu: int = 0, seed: int | np.random.Generator | None = None) -> None:
264
+ super().__init__(n, beta=4, nu=nu, seed=seed)
265
+
266
+
267
+ def _sample_block(n: int, m: int, rng: np.random.Generator, beta: int) -> np.ndarray:
268
+ """Rectangular N x M coupling block W matching the Dyson symmetry
269
+ class beta, via an EXPLICIT dense (quaternion-embedded, for beta=4)
270
+ construction. Used only for direct structural verification of the
271
+ chiral-symmetry construction in the test suite -- the efficient
272
+ production sampler above (``ChiralBetaEnsemble._sample_eigenvalues``)
273
+ never forms this matrix; see the module docstring for why."""
274
+ if beta == 1:
275
+ return rng.standard_normal((n, m))
276
+ if beta == 2:
277
+ return (rng.standard_normal((n, m)) + 1j * rng.standard_normal((n, m))) / np.sqrt(2.0)
278
+ if beta == 4:
279
+ a = rng.standard_normal((n, m))
280
+ b = rng.standard_normal((n, m))
281
+ c = rng.standard_normal((n, m))
282
+ d = rng.standard_normal((n, m))
283
+ w = np.zeros((2 * n, 2 * m), dtype=complex)
284
+ w[0::2, 0::2] = a + 1j * b
285
+ w[0::2, 1::2] = c + 1j * d
286
+ w[1::2, 0::2] = -c + 1j * d
287
+ w[1::2, 1::2] = a - 1j * b
288
+ return w / np.sqrt(2.0)
289
+ raise ValueError(f"beta must be 1, 2, or 4, got {beta}")
290
+
291
+
292
+ def _dense_chiral_hamiltonian(n: int, nu: int, rng: np.random.Generator, beta: int) -> np.ndarray:
293
+ """Dense block off-diagonal chiral Hamiltonian H = [[0, W], [W^dagger, 0]]
294
+ -- used only for direct structural verification (Hermiticity, exact
295
+ chiral-symmetry anticommutation with Gamma = diag(I, -I), and the
296
+ +-singular-value / exact-zero-mode eigenvalue structure) in the test
297
+ suite. Note beta=4 uses an explicit quaternion embedding here, so its
298
+ block sizes are doubled relative to the (n, n+nu) the fast sampler
299
+ above works with directly -- an independent linear-algebra fact
300
+ about the chiral block structure, not tied to which of the two
301
+ (embedding vs. generalized-beta) conventions is used to realize it.
302
+ """
303
+ m = n + nu
304
+ w = _sample_block(n, m, rng, beta)
305
+ n_dim, m_dim = w.shape
306
+ top = np.hstack([np.zeros((n_dim, n_dim), dtype=complex), w])
307
+ bottom = np.hstack([w.conj().T, np.zeros((m_dim, m_dim), dtype=complex)])
308
+ return np.vstack([top, bottom])