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,44 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from physicskit.statphys.chapters.renormalization import BlockSpinRG
5
+
6
+
7
+ def test_iterate_shrinks_grid_by_half_each_step():
8
+ rg = BlockSpinRG(L=16, T=100.0, seed=0, n_equil_sweeps=5)
9
+ grids = rg.iterate(n_steps=3)
10
+ assert [g.shape[0] for g in grids] == [16, 8, 4, 2]
11
+
12
+
13
+ def test_default_n_steps_stops_at_2x2():
14
+ rg = BlockSpinRG(L=16, T=100.0, seed=0, n_equil_sweeps=5)
15
+ grids = rg.iterate()
16
+ assert grids[-1].shape == (2, 2)
17
+
18
+
19
+ def test_high_temperature_flows_toward_disorder():
20
+ rg = BlockSpinRG(L=32, T=1000.0, seed=1, n_equil_sweeps=5)
21
+ grids = rg.iterate(n_steps=4)
22
+ orders = [rg.order_parameter(g) for g in grids]
23
+ # disordered starting point: order parameter should stay small throughout
24
+ assert orders[0] < 0.3
25
+
26
+
27
+ def test_low_temperature_flows_toward_order():
28
+ rg = BlockSpinRG(L=32, T=0.5, seed=2, n_equil_sweeps=200)
29
+ grids = rg.iterate(n_steps=3)
30
+ orders = [rg.order_parameter(g) for g in grids]
31
+ assert orders[-1] > 0.8
32
+
33
+
34
+ def test_coarse_grain_step_requires_even_size():
35
+ rg = BlockSpinRG(L=16, T=100.0, seed=0, n_equil_sweeps=1)
36
+ with pytest.raises(ValueError):
37
+ rg.coarse_grain_step(np.ones((5, 5), dtype=np.int64))
38
+
39
+
40
+ def test_majority_rule_unanimous_block():
41
+ rg = BlockSpinRG(L=8, T=100.0, seed=3, n_equil_sweeps=1)
42
+ block = np.ones((4, 4), dtype=np.int64)
43
+ coarse = rg.coarse_grain_step(block)
44
+ assert np.all(coarse == 1)
@@ -0,0 +1,44 @@
1
+ import numpy as np
2
+
3
+ from physicskit.statphys.chapters.sandpile import BTWSandpile
4
+
5
+
6
+ def test_initial_heights_are_zero():
7
+ pile = BTWSandpile(L=10, seed=0)
8
+ assert np.all(pile.heights == 0)
9
+
10
+
11
+ def test_heights_stay_below_threshold_after_relaxation():
12
+ pile = BTWSandpile(L=16, seed=1)
13
+ pile.run(n_grains=500)
14
+ assert np.all(pile.heights < pile.threshold)
15
+
16
+
17
+ def test_avalanche_sizes_are_non_negative():
18
+ pile = BTWSandpile(L=16, seed=2)
19
+ sizes = pile.run(n_grains=200)
20
+ assert np.all(sizes >= 0)
21
+
22
+
23
+ def test_add_grain_at_specific_site_below_threshold():
24
+ pile = BTWSandpile(L=10, threshold=4, seed=3)
25
+ size = pile.add_grain(site=(5, 5))
26
+ assert size == 0
27
+ assert pile.heights[5, 5] == 1
28
+
29
+
30
+ def test_forced_toppling_conserves_grains_in_bulk():
31
+ pile = BTWSandpile(L=20, threshold=4, seed=4)
32
+ pile.heights[10, 10] = 3
33
+ grains_before = pile.total_grains()
34
+ size = pile.add_grain(site=(10, 10))
35
+ assert size == 1
36
+ # a single interior toppling conserves grains (4 out, 4 in); only the
37
+ # one added grain changes the total.
38
+ assert pile.total_grains() == grains_before + 1
39
+
40
+
41
+ def test_large_run_produces_nontrivial_avalanches():
42
+ pile = BTWSandpile(L=24, seed=5)
43
+ sizes = pile.run(n_grains=2000, warmup=1000)
44
+ assert sizes.max() > 1
@@ -0,0 +1,73 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from physicskit.statphys.chapters.spin_glass import EdwardsAndersonSpinGlass2D, SherringtonKirkpatrick
5
+
6
+
7
+ def test_bonds_are_bimodal():
8
+ model = EdwardsAndersonSpinGlass2D(L=10, J=1.0, seed=0)
9
+ assert set(np.unique(model.J_right)) <= {-1.0, 1.0}
10
+ assert set(np.unique(model.J_down)) <= {-1.0, 1.0}
11
+
12
+
13
+ def test_frustration_density_between_zero_and_one():
14
+ model = EdwardsAndersonSpinGlass2D(L=20, seed=1)
15
+ f = model.frustration_density()
16
+ assert 0.0 <= f <= 1.0
17
+
18
+
19
+ def test_frustration_density_near_one_half_for_random_bonds():
20
+ model = EdwardsAndersonSpinGlass2D(L=40, seed=2)
21
+ assert model.frustration_density() == pytest.approx(0.5, abs=0.05)
22
+
23
+
24
+ def test_ferromagnet_has_zero_frustration():
25
+ model = EdwardsAndersonSpinGlass2D(L=10, seed=3)
26
+ model.J_right[:] = 1.0
27
+ model.J_down[:] = 1.0
28
+ assert model.frustration_density() == pytest.approx(0.0)
29
+
30
+
31
+ def test_sweep_changes_configuration():
32
+ model = EdwardsAndersonSpinGlass2D(L=16, seed=4)
33
+ before = model.spins.copy()
34
+ model.sweep(beta=1.0, n_sweeps=5)
35
+ assert not np.array_equal(before, model.spins)
36
+
37
+
38
+ def test_energy_is_finite():
39
+ model = EdwardsAndersonSpinGlass2D(L=12, seed=5)
40
+ model.sweep(beta=1.0, n_sweeps=10)
41
+ assert np.isfinite(model.energy())
42
+
43
+
44
+ def test_ea_order_parameter_bounds():
45
+ model = EdwardsAndersonSpinGlass2D(L=8, seed=6)
46
+ q2 = model.edwards_anderson_order_parameter(beta=2.0, n_equil=20, n_measure=20)
47
+ assert 0.0 <= q2 <= 1.0 + 1e-9
48
+
49
+
50
+ def test_sk_coupling_matrix_is_symmetric_with_zero_diagonal():
51
+ model = SherringtonKirkpatrick(N=30, seed=0)
52
+ assert np.allclose(model.J, model.J.T)
53
+ assert np.all(np.diag(model.J) == 0.0)
54
+
55
+
56
+ def test_sk_sweep_changes_configuration():
57
+ model = SherringtonKirkpatrick(N=40, seed=1)
58
+ before = model.spins.copy()
59
+ model.sweep(beta=1.0, n_sweeps=5)
60
+ assert not np.array_equal(before, model.spins)
61
+
62
+
63
+ def test_sk_energy_is_finite():
64
+ model = SherringtonKirkpatrick(N=30, seed=2)
65
+ model.sweep(beta=1.0, n_sweeps=5)
66
+ assert np.isfinite(model.energy())
67
+
68
+
69
+ def test_sk_overlap_distribution_shape_and_bounds():
70
+ model = SherringtonKirkpatrick(N=20, seed=3)
71
+ samples = model.overlap_distribution(beta=1.5, n_disorder=4, n_equil=10, n_measure=5)
72
+ assert samples.shape == (20,)
73
+ assert np.all(samples >= -1.0 - 1e-9) and np.all(samples <= 1.0 + 1e-9)
@@ -0,0 +1,121 @@
1
+ import numpy as np
2
+ import pytest
3
+ from scipy.integrate import trapezoid
4
+
5
+ from physicskit.statphys.utils.thermodynamics import (
6
+ bec_condensate_fraction,
7
+ binder_cumulant,
8
+ bose_einstein_occupation,
9
+ fermi_dirac_occupation,
10
+ maxwell_boltzmann_component_pdf,
11
+ maxwell_boltzmann_speed_pdf,
12
+ specific_heat,
13
+ spin_correlation_function,
14
+ susceptibility,
15
+ )
16
+
17
+
18
+ def test_specific_heat_zero_for_constant_energy():
19
+ E = np.full(1000, -50.0)
20
+ assert specific_heat(E, temperature=2.0, n_sites=64) == pytest.approx(0.0)
21
+
22
+
23
+ def test_specific_heat_positive_for_fluctuating_energy():
24
+ rng = np.random.default_rng(0)
25
+ E = rng.normal(-100.0, 5.0, size=5000)
26
+ assert specific_heat(E, temperature=2.0, n_sites=64) > 0
27
+
28
+
29
+ def test_susceptibility_scales_with_variance():
30
+ rng = np.random.default_rng(1)
31
+ M_low = rng.normal(0.0, 1.0, size=5000)
32
+ M_high = rng.normal(0.0, 5.0, size=5000)
33
+ assert susceptibility(M_high, 1.0, 64) > susceptibility(M_low, 1.0, 64)
34
+
35
+
36
+ def test_binder_cumulant_gaussian_limit():
37
+ rng = np.random.default_rng(2)
38
+ m = rng.normal(0.0, 1.0, size=200_000)
39
+ # for a zero-mean Gaussian, <m^4>/<m^2>^2 = 3, so U4 -> 0
40
+ assert binder_cumulant(m) == pytest.approx(0.0, abs=0.05)
41
+
42
+
43
+ def test_binder_cumulant_delta_distribution():
44
+ m = np.full(1000, 2.5)
45
+ assert binder_cumulant(m) == pytest.approx(2.0 / 3.0)
46
+
47
+
48
+ def test_spin_correlation_function_zero_lag_equals_variance():
49
+ rng = np.random.default_rng(3)
50
+ spins = rng.choice([-1, 1], size=(20, 20))
51
+ r, G = spin_correlation_function(spins)
52
+ assert r[0] == 0
53
+ assert G[0] == pytest.approx(1.0 - spins.mean() ** 2, abs=1e-9)
54
+
55
+
56
+ def test_maxwell_boltzmann_speed_pdf_normalizes_to_one():
57
+ v = np.linspace(0, 20, 200_000)
58
+ pdf = maxwell_boltzmann_speed_pdf(v, temperature=2.0, mass=1.0, dim=2)
59
+ integral = trapezoid(pdf, v)
60
+ assert integral == pytest.approx(1.0, abs=1e-3)
61
+
62
+
63
+ def test_maxwell_boltzmann_speed_pdf_invalid_dim_raises():
64
+ with pytest.raises(ValueError):
65
+ maxwell_boltzmann_speed_pdf(np.array([1.0]), temperature=1.0, dim=4)
66
+
67
+
68
+ @pytest.mark.parametrize("dim", [1, 3])
69
+ def test_maxwell_boltzmann_speed_pdf_normalizes_to_one_in_1d_and_3d(dim):
70
+ v = np.linspace(0, 20, 200_000)
71
+ pdf = maxwell_boltzmann_speed_pdf(v, temperature=2.0, mass=1.0, dim=dim)
72
+ integral = trapezoid(pdf, v)
73
+ assert integral == pytest.approx(1.0, abs=1e-3)
74
+
75
+
76
+ def test_maxwell_boltzmann_component_pdf_is_gaussian():
77
+ vx = np.linspace(-10, 10, 200_000)
78
+ pdf = maxwell_boltzmann_component_pdf(vx, temperature=1.5, mass=1.0)
79
+ integral = trapezoid(pdf, vx)
80
+ assert integral == pytest.approx(1.0, abs=1e-3)
81
+
82
+
83
+ def test_bose_einstein_occupation_diverges_near_ground_state():
84
+ n_close = bose_einstein_occupation(1.001, mu=1.0, temperature=1.0)
85
+ n_far = bose_einstein_occupation(5.0, mu=1.0, temperature=1.0)
86
+ assert n_close > n_far > 0
87
+
88
+
89
+ def test_fermi_dirac_occupation_bounded_between_zero_and_one():
90
+ energies = np.linspace(-5, 5, 50)
91
+ n = fermi_dirac_occupation(energies, mu=0.0, temperature=1.0)
92
+ assert np.all(n > 0.0) and np.all(n < 1.0)
93
+
94
+
95
+ def test_fermi_dirac_occupation_step_function_at_zero_temperature():
96
+ # small enough to sharpen into a step, large enough that exp(x) doesn't overflow
97
+ n_below = fermi_dirac_occupation(-1.0, mu=0.0, temperature=0.05)
98
+ n_above = fermi_dirac_occupation(1.0, mu=0.0, temperature=0.05)
99
+ assert n_below == pytest.approx(1.0, abs=1e-6)
100
+ assert n_above == pytest.approx(0.0, abs=1e-6)
101
+
102
+
103
+ def test_fermi_dirac_occupation_half_at_the_fermi_energy():
104
+ n = fermi_dirac_occupation(2.0, mu=2.0, temperature=1.0)
105
+ assert n == pytest.approx(0.5)
106
+
107
+
108
+ def test_bec_condensate_fraction_full_at_zero_temperature():
109
+ f = bec_condensate_fraction(0.0, critical_temperature=1.0)
110
+ assert float(f) == pytest.approx(1.0)
111
+
112
+
113
+ def test_bec_condensate_fraction_zero_above_tc():
114
+ f = bec_condensate_fraction(2.0, critical_temperature=1.0)
115
+ assert float(f) == pytest.approx(0.0)
116
+
117
+
118
+ def test_bec_condensate_fraction_monotonically_decreasing():
119
+ T = np.linspace(0.0, 1.5, 20)
120
+ f = bec_condensate_fraction(T, critical_temperature=1.0)
121
+ assert np.all(np.diff(f) <= 1e-12)
@@ -0,0 +1,45 @@
1
+ import numpy as np
2
+
3
+ from physicskit.statphys.chapters.ising_lattice import XYModel2D
4
+
5
+
6
+ def test_theta_in_valid_range():
7
+ model = XYModel2D(L=12, seed=0)
8
+ assert np.all(model.theta >= 0.0)
9
+ assert np.all(model.theta < 2.0 * np.pi)
10
+
11
+
12
+ def test_sweep_keeps_theta_in_range():
13
+ model = XYModel2D(L=12, seed=1)
14
+ model.sweep(beta=1.0, n_sweeps=10)
15
+ assert np.all(model.theta >= 0.0)
16
+ assert np.all(model.theta < 2.0 * np.pi)
17
+
18
+
19
+ def test_kt_temperature_is_positive_and_reasonable():
20
+ model = XYModel2D(J=1.0, kB=1.0)
21
+ assert 0.5 < model.T_KT < 1.5
22
+
23
+
24
+ def test_uniform_configuration_has_zero_vorticity():
25
+ model = XYModel2D(L=10, seed=2)
26
+ model.theta[:] = 0.0
27
+ q = model.vorticity()
28
+ assert np.allclose(q, 0.0, atol=1e-9)
29
+ n_v, n_av = model.vortex_count()
30
+ assert n_v == 0 and n_av == 0
31
+
32
+
33
+ def test_low_temperature_has_small_ordered_magnetization():
34
+ model = XYModel2D(L=14, seed=3)
35
+ model.theta[:] = model._rng.uniform(-0.05, 0.05, size=model.theta.shape) % (2 * np.pi)
36
+ model.sweep(beta=10.0, n_sweeps=30)
37
+ mag = model.magnetization_vector()
38
+ norm = np.linalg.norm(mag) / model.n_sites
39
+ assert norm > 0.5 # strongly aligned spins retain a large net moment
40
+
41
+
42
+ def test_energy_is_finite():
43
+ model = XYModel2D(L=10, seed=4)
44
+ model.sweep(beta=1.0, n_sweeps=5)
45
+ assert np.isfinite(model.energy())
@@ -0,0 +1 @@
1
+ """Thermodynamic observables computed from simulation trajectories."""
@@ -0,0 +1,100 @@
1
+ """Dynamical diagnostics for Monte Carlo time series: autocorrelation and critical slowing down.
2
+
3
+ Near a continuous phase transition, successive Monte Carlo configurations
4
+ become strongly correlated in (simulation) time -- "critical slowing down"
5
+ -- so that naively spaced samples are not statistically independent. The
6
+ integrated autocorrelation time quantifies exactly how many sweeps separate
7
+ effectively independent samples, and comparing it between update algorithms
8
+ (e.g. single-spin-flip Metropolis versus the Wolff cluster algorithm) is the
9
+ standard way to demonstrate why cluster algorithms were invented.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import numpy as np
15
+
16
+ __all__ = ["autocorrelation_function", "integrated_autocorrelation_time"]
17
+
18
+
19
+ def autocorrelation_function(series, max_lag=None):
20
+ """Normalized autocorrelation function of a scalar Monte Carlo time series.
21
+
22
+ .. math::
23
+
24
+ \\rho(t) = \\frac{\\langle (x_i - \\bar x)(x_{i+t} - \\bar x) \\rangle}{\\mathrm{Var}(x)}
25
+
26
+ computed efficiently via the FFT (Wiener-Khinchin theorem).
27
+
28
+ Parameters
29
+ ----------
30
+ series : array_like
31
+ A scalar observable sampled at successive Monte Carlo sweeps (e.g.
32
+ magnetization or energy).
33
+ max_lag : int, optional
34
+ Largest lag to return. Defaults to ``len(series) // 2``.
35
+
36
+ Returns
37
+ -------
38
+ ndarray
39
+ :math:`\\rho(t)` for :math:`t = 0, 1, \\ldots,` ``max_lag``, with
40
+ :math:`\\rho(0) = 1`.
41
+ """
42
+ x = np.asarray(series, dtype=np.float64)
43
+ x = x - x.mean()
44
+ n = len(x)
45
+ if max_lag is None:
46
+ max_lag = n // 2
47
+
48
+ padded = np.zeros(2 * n)
49
+ padded[:n] = x
50
+ fft = np.fft.fft(padded)
51
+ autocorr = np.fft.ifft(fft * np.conj(fft)).real[:n]
52
+ autocorr /= np.arange(n, 0, -1)
53
+ return autocorr[: max_lag + 1] / autocorr[0]
54
+
55
+
56
+ def integrated_autocorrelation_time(series, c=5.0, max_lag=None):
57
+ """Estimate the integrated autocorrelation time via Sokal's automatic windowing.
58
+
59
+ .. math::
60
+
61
+ \\tau_{\\text{int}}(M) = 1 + 2 \\sum_{t=1}^{M} \\rho(t)
62
+
63
+ The summation window :math:`M` is chosen automatically as the smallest
64
+ value satisfying :math:`M \\ge c \\, \\tau_{\\text{int}}(M)` (Sokal
65
+ 1997), balancing statistical noise against truncation bias.
66
+ :math:`2\\tau_{\\text{int}}` gives (approximately) the number of Monte
67
+ Carlo sweeps needed between effectively independent samples -- the
68
+ standard quantitative measure of critical slowing down.
69
+
70
+ Parameters
71
+ ----------
72
+ series : array_like
73
+ A scalar Monte Carlo observable time series.
74
+ c : float, default=5.0
75
+ Windowing constant (Sokal recommends 4-10; smaller is noisier,
76
+ larger is more biased).
77
+ max_lag : int, optional
78
+ Largest lag considered; defaults to ``len(series) // 2``.
79
+
80
+ Returns
81
+ -------
82
+ float
83
+ Estimated integrated autocorrelation time, in units of sweeps.
84
+
85
+ Examples
86
+ --------
87
+ >>> rng = np.random.default_rng(0)
88
+ >>> x = rng.normal(size=5000) # independent samples: tau ~ 0.5-1
89
+ >>> tau = integrated_autocorrelation_time(x)
90
+ >>> tau < 3.0
91
+ True
92
+ """
93
+ rho = autocorrelation_function(series, max_lag=max_lag)
94
+ cumulative = 0.0
95
+ for M in range(1, len(rho)):
96
+ cumulative += rho[M]
97
+ tau = 1.0 + 2.0 * cumulative
98
+ if c * tau <= M:
99
+ return float(tau)
100
+ return float(1.0 + 2.0 * cumulative)
@@ -0,0 +1,171 @@
1
+ """Finite-size scaling analysis: locating T_C and estimating critical exponents.
2
+
3
+ Monte Carlo simulations necessarily run on finite lattices, so an apparent
4
+ thermodynamic singularity is always rounded and shifted relative to its
5
+ infinite-volume value. Finite-size scaling theory predicts precisely how
6
+ observables at different lattice sizes :math:`L` relate near a continuous
7
+ phase transition, letting :math:`T_C` and the critical exponents be
8
+ extracted from a family of finite simulations without ever simulating an
9
+ infinite system.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import numpy as np
15
+
16
+ __all__ = [
17
+ "binder_cumulant_crossing",
18
+ "estimate_beta_over_nu",
19
+ "estimate_gamma_over_nu",
20
+ "estimate_nu_from_binder_slope",
21
+ "power_law_exponent",
22
+ ]
23
+
24
+
25
+ def power_law_exponent(x, y):
26
+ """Fit the exponent of an assumed power law :math:`y = A x^p` via log-log linear regression.
27
+
28
+ Parameters
29
+ ----------
30
+ x, y : array_like
31
+ Positive-valued samples believed to follow a power law.
32
+
33
+ Returns
34
+ -------
35
+ exponent : float
36
+ The fitted exponent :math:`p`.
37
+ prefactor : float
38
+ The fitted prefactor :math:`A`.
39
+
40
+ Examples
41
+ --------
42
+ >>> x = np.array([1.0, 2.0, 4.0, 8.0, 16.0])
43
+ >>> y = 3.0 * x**1.5
44
+ >>> p, A = power_law_exponent(x, y)
45
+ >>> round(p, 6)
46
+ 1.5
47
+ """
48
+ x = np.asarray(x, dtype=np.float64)
49
+ y = np.asarray(y, dtype=np.float64)
50
+ p, log_A = np.polyfit(np.log(x), np.log(y), 1)
51
+ return float(p), float(np.exp(log_A))
52
+
53
+
54
+ def estimate_gamma_over_nu(L_values, chi_max_values):
55
+ """Estimate :math:`\\gamma/\\nu` from the lattice-size scaling of the peak susceptibility.
56
+
57
+ Finite-size scaling predicts :math:`\\chi_{\\max}(L) \\sim L^{\\gamma/\\nu}`.
58
+
59
+ Parameters
60
+ ----------
61
+ L_values : array_like
62
+ Lattice sizes.
63
+ chi_max_values : array_like
64
+ Peak susceptibility measured at each lattice size (e.g. the maximum
65
+ of the ``"chi"`` array returned by ``Ising2D.run_temperature_sweep``).
66
+
67
+ Returns
68
+ -------
69
+ float
70
+ Estimated :math:`\\gamma / \\nu`.
71
+ """
72
+ exponent, _ = power_law_exponent(L_values, chi_max_values)
73
+ return exponent
74
+
75
+
76
+ def estimate_beta_over_nu(L_values, magnetization_at_tc_values):
77
+ """Estimate :math:`\\beta/\\nu` from the lattice-size scaling of the order parameter at T_C.
78
+
79
+ Finite-size scaling predicts :math:`M(T_C, L) \\sim L^{-\\beta/\\nu}`.
80
+
81
+ Parameters
82
+ ----------
83
+ L_values : array_like
84
+ Lattice sizes.
85
+ magnetization_at_tc_values : array_like
86
+ Order parameter measured at (approximately) :math:`T_C` for each
87
+ lattice size.
88
+
89
+ Returns
90
+ -------
91
+ float
92
+ Estimated :math:`\\beta / \\nu`.
93
+ """
94
+ exponent, _ = power_law_exponent(L_values, magnetization_at_tc_values)
95
+ return -exponent
96
+
97
+
98
+ def estimate_nu_from_binder_slope(L_values, T_grids, U4_grids, T_c):
99
+ """Estimate the correlation-length exponent :math:`\\nu` from the Binder cumulant's slope at T_C.
100
+
101
+ Finite-size scaling predicts the Binder cumulant's temperature
102
+ derivative at criticality scales as
103
+ :math:`\\left.\\frac{dU_4}{dT}\\right|_{T_C} \\sim L^{1/\\nu}`. This
104
+ numerically differentiates each lattice size's :math:`U_4(T)` curve at
105
+ :math:`T_C` (a finite-difference slope between the two grid points
106
+ bracketing :math:`T_C`) and fits the resulting :math:`L`-scaling.
107
+
108
+ Parameters
109
+ ----------
110
+ L_values : array_like
111
+ Lattice sizes.
112
+ T_grids : list of array_like
113
+ Temperature grid used at each lattice size (need not be identical
114
+ across sizes, but each must bracket ``T_c``).
115
+ U4_grids : list of array_like
116
+ Binder cumulant values on each temperature grid.
117
+ T_c : float
118
+ Critical temperature at which to evaluate the slope.
119
+
120
+ Returns
121
+ -------
122
+ float
123
+ Estimated :math:`\\nu`.
124
+ """
125
+ slopes = []
126
+ for T, U4 in zip(T_grids, U4_grids):
127
+ T = np.asarray(T, dtype=np.float64)
128
+ U4 = np.asarray(U4, dtype=np.float64)
129
+ order = np.argsort(T)
130
+ T, U4 = T[order], U4[order]
131
+ idx = np.clip(np.searchsorted(T, T_c), 1, len(T) - 1)
132
+ slope = (U4[idx] - U4[idx - 1]) / (T[idx] - T[idx - 1])
133
+ slopes.append(abs(slope))
134
+ exponent, _ = power_law_exponent(L_values, slopes)
135
+ return 1.0 / exponent
136
+
137
+
138
+ def binder_cumulant_crossing(T, U4_by_L):
139
+ """Estimate T_C as the crossing point of the two largest lattice sizes' Binder cumulant curves.
140
+
141
+ Interpolates linearly between grid points to find where the two curves
142
+ cross -- the standard, finite-size-correction-robust way to locate a
143
+ continuous transition's critical temperature.
144
+
145
+ Parameters
146
+ ----------
147
+ T : array_like
148
+ Common temperature grid shared by all lattice sizes.
149
+ U4_by_L : dict of int -> array_like
150
+ Binder cumulant values at each lattice size, evaluated on ``T``.
151
+
152
+ Returns
153
+ -------
154
+ float
155
+ Estimated crossing temperature.
156
+
157
+ Raises
158
+ ------
159
+ ValueError
160
+ If the two largest lattice sizes' curves never cross on ``T``.
161
+ """
162
+ L1, L2 = sorted(U4_by_L.keys())[-2:]
163
+ T = np.asarray(T, dtype=np.float64)
164
+ diff = np.asarray(U4_by_L[L1], dtype=np.float64) - np.asarray(U4_by_L[L2], dtype=np.float64)
165
+ sign_changes = np.where(np.diff(np.sign(diff)) != 0)[0]
166
+ if len(sign_changes) == 0:
167
+ raise ValueError("Binder cumulant curves for the two largest L do not cross on this grid")
168
+ i = sign_changes[0]
169
+ t0, t1 = T[i], T[i + 1]
170
+ d0, d1 = diff[i], diff[i + 1]
171
+ return float(t0 - d0 * (t1 - t0) / (d1 - d0))