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,462 @@
1
+ """Numba-accelerated Monte Carlo kernels for lattice spin models.
2
+
3
+ This module holds the hot inner loops shared by :mod:`physicskit.statphys.chapters.ising_lattice`:
4
+ single-spin-flip Metropolis-Hastings sweeps for the Ising and Potts models, a
5
+ continuous-angle Metropolis sweep for the XY model, and the Wolff single-cluster
6
+ algorithm for the Ising model. Functions are JIT-compiled with :func:`numba.njit`
7
+ so that a full lattice sweep of :math:`L \\times L` sites costs a handful of
8
+ microseconds rather than a Python-loop pass.
9
+
10
+ All lattices use periodic boundary conditions.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import numpy as np
16
+ from numba import njit
17
+
18
+ __all__ = [
19
+ "ising_total_energy",
20
+ "ising_total_magnetization",
21
+ "metropolis_sweep_ising",
22
+ "metropolis_sweep_potts",
23
+ "metropolis_sweep_sk",
24
+ "metropolis_sweep_spin_glass",
25
+ "metropolis_sweep_xy",
26
+ "potts_total_energy",
27
+ "seed_numba_random",
28
+ "sk_total_energy",
29
+ "spin_glass_total_energy",
30
+ "wolff_step_ising",
31
+ "xy_plaquette_vorticity",
32
+ "xy_total_energy",
33
+ ]
34
+
35
+
36
+ @njit(cache=True)
37
+ def seed_numba_random(seed):
38
+ """Seed the random-number generator used by every ``@njit`` kernel in physicskit.statphys.
39
+
40
+ Plain ``numpy.random.seed`` only reseeds NumPy's own global generator
41
+ and has **no effect** on Numba-compiled (``@njit``) code, which
42
+ maintains a single separate internal RNG state shared by every
43
+ ``@njit`` function in the process (regardless of which module defines
44
+ them). Calling ``np.random.seed`` from *inside* jitted code, as this
45
+ thin wrapper does, is the only way to obtain reproducible dynamics from
46
+ any of physicskit.statphys's Monte Carlo sweep or random-walk kernels.
47
+
48
+ Parameters
49
+ ----------
50
+ seed : int
51
+ Seed value.
52
+ """
53
+ np.random.seed(seed)
54
+
55
+
56
+ @njit(cache=True)
57
+ def _ising_neighbor_sum(spins, i, j, L):
58
+ top = spins[(i - 1) % L, j]
59
+ bottom = spins[(i + 1) % L, j]
60
+ left = spins[i, (j - 1) % L]
61
+ right = spins[i, (j + 1) % L]
62
+ return top + bottom + left + right
63
+
64
+
65
+ @njit(cache=True)
66
+ def metropolis_sweep_ising(spins, beta, J):
67
+ """Perform one Metropolis-Hastings sweep of an Ising lattice, in place.
68
+
69
+ Parameters
70
+ ----------
71
+ spins : ndarray of shape (L, L), dtype int64
72
+ Spin configuration with values in ``{-1, +1}``. Modified in place.
73
+ beta : float
74
+ Inverse temperature :math:`1 / (k_B T)`.
75
+ J : float
76
+ Ferromagnetic (``J > 0``) or antiferromagnetic (``J < 0``) coupling.
77
+
78
+ Returns
79
+ -------
80
+ ndarray of shape (L, L)
81
+ The same array passed in (returned for convenience).
82
+
83
+ Notes
84
+ -----
85
+ One sweep proposes :math:`L^2` single-spin flips at randomly chosen sites,
86
+ each accepted with probability :math:`\\min(1, e^{-\\beta \\Delta E})`, where
87
+ :math:`\\Delta E = 2 J s_i \\sum_{\\langle i,j \\rangle} s_j`.
88
+ """
89
+ L = spins.shape[0]
90
+ n = L * L
91
+ for _ in range(n):
92
+ i = np.random.randint(0, L)
93
+ j = np.random.randint(0, L)
94
+ s = spins[i, j]
95
+ neighbor_sum = _ising_neighbor_sum(spins, i, j, L)
96
+ dE = 2.0 * J * s * neighbor_sum
97
+ if dE <= 0.0 or np.random.random() < np.exp(-beta * dE):
98
+ spins[i, j] = -s
99
+ return spins
100
+
101
+
102
+ @njit(cache=True)
103
+ def wolff_step_ising(spins, beta, J):
104
+ """Grow and flip a single Wolff cluster on an Ising lattice, in place.
105
+
106
+ The Wolff algorithm adds a same-spin neighbor to the growing cluster with
107
+ probability :math:`p_{\\text{add}} = 1 - e^{-2 \\beta J}`, then flips the
108
+ entire cluster at once. It suppresses the critical slowing down that
109
+ afflicts single-spin-flip Metropolis dynamics near :math:`T_c`.
110
+
111
+ Parameters
112
+ ----------
113
+ spins : ndarray of shape (L, L), dtype int64
114
+ Spin configuration with values in ``{-1, +1}``. Modified in place.
115
+ beta : float
116
+ Inverse temperature.
117
+ J : float
118
+ Ferromagnetic coupling constant (should be positive).
119
+
120
+ Returns
121
+ -------
122
+ int
123
+ Number of spins flipped in this cluster update.
124
+ """
125
+ L = spins.shape[0]
126
+ p_add = 1.0 - np.exp(-2.0 * beta * J)
127
+
128
+ stack_i = np.empty(L * L, dtype=np.int64)
129
+ stack_j = np.empty(L * L, dtype=np.int64)
130
+ top = 0
131
+
132
+ i0 = np.random.randint(0, L)
133
+ j0 = np.random.randint(0, L)
134
+ cluster_spin = spins[i0, j0]
135
+
136
+ in_cluster = np.zeros((L, L), dtype=np.bool_)
137
+ in_cluster[i0, j0] = True
138
+ spins[i0, j0] = -cluster_spin
139
+ stack_i[top] = i0
140
+ stack_j[top] = j0
141
+ top += 1
142
+ cluster_size = 1
143
+
144
+ while top > 0:
145
+ top -= 1
146
+ i = stack_i[top]
147
+ j = stack_j[top]
148
+ for di, dj in ((-1, 0), (1, 0), (0, -1), (0, 1)):
149
+ ni = (i + di) % L
150
+ nj = (j + dj) % L
151
+ if (not in_cluster[ni, nj]) and spins[ni, nj] == cluster_spin and np.random.random() < p_add:
152
+ in_cluster[ni, nj] = True
153
+ spins[ni, nj] = -cluster_spin
154
+ stack_i[top] = ni
155
+ stack_j[top] = nj
156
+ top += 1
157
+ cluster_size += 1
158
+ return cluster_size
159
+
160
+
161
+ @njit(cache=True)
162
+ def metropolis_sweep_potts(spins, beta, J, q):
163
+ """Perform one Metropolis-Hastings sweep of a q-state Potts lattice, in place.
164
+
165
+ Parameters
166
+ ----------
167
+ spins : ndarray of shape (L, L), dtype int64
168
+ Spin configuration with values in ``{0, ..., q-1}``. Modified in place.
169
+ beta : float
170
+ Inverse temperature.
171
+ J : float
172
+ Coupling constant. The bond energy is :math:`-J` when neighboring
173
+ spins agree and ``0`` otherwise (Potts Hamiltonian).
174
+ q : int
175
+ Number of Potts states.
176
+
177
+ Returns
178
+ -------
179
+ ndarray of shape (L, L)
180
+ The same array passed in.
181
+ """
182
+ L = spins.shape[0]
183
+ n = L * L
184
+ for _ in range(n):
185
+ i = np.random.randint(0, L)
186
+ j = np.random.randint(0, L)
187
+ s = spins[i, j]
188
+ top = spins[(i - 1) % L, j]
189
+ bottom = spins[(i + 1) % L, j]
190
+ left = spins[i, (j - 1) % L]
191
+ right = spins[i, (j + 1) % L]
192
+ new_s = np.random.randint(0, q)
193
+ old_matches = (s == top) + (s == bottom) + (s == left) + (s == right)
194
+ new_matches = (new_s == top) + (new_s == bottom) + (new_s == left) + (new_s == right)
195
+ dE = -J * (new_matches - old_matches)
196
+ if dE <= 0.0 or np.random.random() < np.exp(-beta * dE):
197
+ spins[i, j] = new_s
198
+ return spins
199
+
200
+
201
+ @njit(cache=True)
202
+ def metropolis_sweep_xy(theta, beta, J, delta=1.0):
203
+ """Perform one Metropolis-Hastings sweep of a 2D XY lattice, in place.
204
+
205
+ Parameters
206
+ ----------
207
+ theta : ndarray of shape (L, L), dtype float64
208
+ Planar spin angles in radians, :math:`\\theta_i \\in [0, 2\\pi)`.
209
+ Modified in place.
210
+ beta : float
211
+ Inverse temperature.
212
+ J : float
213
+ Coupling constant. Bond energy is :math:`-J \\cos(\\theta_i - \\theta_j)`.
214
+ delta : float, default=1.0
215
+ Maximum angular step of a trial move, drawn uniformly from
216
+ ``[-delta, delta]``.
217
+
218
+ Returns
219
+ -------
220
+ ndarray of shape (L, L)
221
+ The same array passed in.
222
+ """
223
+ L = theta.shape[0]
224
+ n = L * L
225
+ two_pi = 2.0 * np.pi
226
+ for _ in range(n):
227
+ i = np.random.randint(0, L)
228
+ j = np.random.randint(0, L)
229
+ old = theta[i, j]
230
+ new = old + (2.0 * np.random.random() - 1.0) * delta
231
+
232
+ top = theta[(i - 1) % L, j]
233
+ bottom = theta[(i + 1) % L, j]
234
+ left = theta[i, (j - 1) % L]
235
+ right = theta[i, (j + 1) % L]
236
+
237
+ old_energy = -J * (np.cos(old - top) + np.cos(old - bottom) + np.cos(old - left) + np.cos(old - right))
238
+ new_energy = -J * (np.cos(new - top) + np.cos(new - bottom) + np.cos(new - left) + np.cos(new - right))
239
+ dE = new_energy - old_energy
240
+ if dE <= 0.0 or np.random.random() < np.exp(-beta * dE):
241
+ spin = new % two_pi
242
+ theta[i, j] = spin
243
+ return theta
244
+
245
+
246
+ @njit(cache=True)
247
+ def ising_total_energy(spins, J):
248
+ """Total Ising Hamiltonian :math:`E = -J \\sum_{\\langle i,j \\rangle} s_i s_j`.
249
+
250
+ Each bond is counted once (only the right and bottom neighbor of every
251
+ site), giving the physical extensive energy for a periodic :math:`L
252
+ \\times L` lattice.
253
+ """
254
+ L = spins.shape[0]
255
+ E = 0.0
256
+ for i in range(L):
257
+ for j in range(L):
258
+ s = spins[i, j]
259
+ right = spins[i, (j + 1) % L]
260
+ bottom = spins[(i + 1) % L, j]
261
+ E += -J * s * (right + bottom)
262
+ return E
263
+
264
+
265
+ @njit(cache=True)
266
+ def ising_total_magnetization(spins):
267
+ """Total magnetization :math:`M = \\sum_i s_i`."""
268
+ return spins.sum()
269
+
270
+
271
+ @njit(cache=True)
272
+ def potts_total_energy(spins, J):
273
+ """Total Potts Hamiltonian :math:`E = -J \\sum_{\\langle i,j \\rangle} \\delta(s_i, s_j)`."""
274
+ L = spins.shape[0]
275
+ E = 0.0
276
+ for i in range(L):
277
+ for j in range(L):
278
+ s = spins[i, j]
279
+ right = spins[i, (j + 1) % L]
280
+ bottom = spins[(i + 1) % L, j]
281
+ E += -J * ((s == right) + (s == bottom))
282
+ return E
283
+
284
+
285
+ @njit(cache=True)
286
+ def xy_total_energy(theta, J):
287
+ """Total XY Hamiltonian :math:`E = -J \\sum_{\\langle i,j \\rangle} \\cos(\\theta_i - \\theta_j)`."""
288
+ L = theta.shape[0]
289
+ E = 0.0
290
+ for i in range(L):
291
+ for j in range(L):
292
+ t = theta[i, j]
293
+ right = theta[i, (j + 1) % L]
294
+ bottom = theta[(i + 1) % L, j]
295
+ E += -J * (np.cos(t - right) + np.cos(t - bottom))
296
+ return E
297
+
298
+
299
+ @njit(cache=True)
300
+ def xy_plaquette_vorticity(theta):
301
+ """Topological charge of every elementary plaquette of an XY lattice.
302
+
303
+ The vorticity of the plaquette with lower-left corner ``(i, j)`` is
304
+
305
+ .. math::
306
+
307
+ q_{ij} = \\frac{1}{2\\pi} \\oint \\nabla \\theta \\cdot d\\mathbf{l}
308
+ = \\frac{1}{2\\pi} \\sum_{k} \\text{wrap}(\\theta_{k+1} - \\theta_k)
309
+
310
+ summed counter-clockwise around the four bonds of the plaquette, where
311
+ ``wrap`` maps angle differences into :math:`(-\\pi, \\pi]`. It is close to
312
+ an integer (:math:`0` in the bulk, :math:`\\pm 1` at a vortex core).
313
+
314
+ Parameters
315
+ ----------
316
+ theta : ndarray of shape (L, L), dtype float64
317
+ Planar spin angles.
318
+
319
+ Returns
320
+ -------
321
+ ndarray of shape (L, L), dtype float64
322
+ Vorticity charge attached to each plaquette (periodic lattice, so
323
+ every site indexes one plaquette).
324
+ """
325
+ L = theta.shape[0]
326
+ q = np.zeros((L, L), dtype=np.float64)
327
+ two_pi = 2.0 * np.pi
328
+ for i in range(L):
329
+ for j in range(L):
330
+ t00 = theta[i, j]
331
+ t10 = theta[i, (j + 1) % L]
332
+ t11 = theta[(i + 1) % L, (j + 1) % L]
333
+ t01 = theta[(i + 1) % L, j]
334
+ total = 0.0
335
+ for a, b in ((t00, t10), (t10, t11), (t11, t01), (t01, t00)):
336
+ d = b - a
337
+ d = d - two_pi * np.floor((d + np.pi) / two_pi)
338
+ total += d
339
+ q[i, j] = total / two_pi
340
+ return q
341
+
342
+
343
+ @njit(cache=True)
344
+ def metropolis_sweep_spin_glass(spins, beta, J_right, J_down):
345
+ """Perform one Metropolis-Hastings sweep of an Edwards-Anderson Ising spin glass, in place.
346
+
347
+ Unlike :func:`metropolis_sweep_ising`, the bond coupling is a quenched,
348
+ site-dependent random variable rather than a single constant: ``J_right[i,
349
+ j]`` is the coupling between site ``(i, j)`` and its right neighbor
350
+ ``(i, j+1)``, and ``J_down[i, j]`` is the coupling between ``(i, j)`` and
351
+ its neighbor below, ``(i+1, j)`` (both periodic). A site's left and top
352
+ bonds are read from its neighbor's ``J_right``/``J_down`` entries.
353
+
354
+ Parameters
355
+ ----------
356
+ spins : ndarray of shape (L, L), dtype int64
357
+ Spin configuration with values in ``{-1, +1}``. Modified in place.
358
+ beta : float
359
+ Inverse temperature.
360
+ J_right : ndarray of shape (L, L), dtype float64
361
+ Quenched rightward bond couplings.
362
+ J_down : ndarray of shape (L, L), dtype float64
363
+ Quenched downward bond couplings.
364
+
365
+ Returns
366
+ -------
367
+ ndarray of shape (L, L)
368
+ The same array passed in.
369
+ """
370
+ L = spins.shape[0]
371
+ n = L * L
372
+ for _ in range(n):
373
+ i = np.random.randint(0, L)
374
+ j = np.random.randint(0, L)
375
+ s = spins[i, j]
376
+
377
+ ip = (i + 1) % L
378
+ im = (i - 1) % L
379
+ jp = (j + 1) % L
380
+ jm = (j - 1) % L
381
+
382
+ dE = 2.0 * s * (J_right[i, j] * spins[i, jp] + J_right[i, jm] * spins[i, jm] + J_down[i, j] * spins[ip, j] + J_down[im, j] * spins[im, j])
383
+ if dE <= 0.0 or np.random.random() < np.exp(-beta * dE):
384
+ spins[i, j] = -s
385
+ return spins
386
+
387
+
388
+ @njit(cache=True)
389
+ def spin_glass_total_energy(spins, J_right, J_down):
390
+ """Total Edwards-Anderson Hamiltonian :math:`E = -\\sum_{\\langle i,j \\rangle} J_{ij} s_i s_j`.
391
+
392
+ Each bond is counted once, using the same ``J_right``/``J_down``
393
+ indexing convention as :func:`metropolis_sweep_spin_glass`.
394
+ """
395
+ L = spins.shape[0]
396
+ E = 0.0
397
+ for i in range(L):
398
+ for j in range(L):
399
+ s = spins[i, j]
400
+ right = spins[i, (j + 1) % L]
401
+ bottom = spins[(i + 1) % L, j]
402
+ E += -J_right[i, j] * s * right - J_down[i, j] * s * bottom
403
+ return E
404
+
405
+
406
+ @njit(cache=True)
407
+ def metropolis_sweep_sk(spins, beta, J):
408
+ """Perform one Metropolis-Hastings sweep of a fully-connected Sherrington-Kirkpatrick spin glass, in place.
409
+
410
+ Unlike the nearest-neighbor lattice models, every spin couples to every
411
+ other spin: flipping site ``i`` requires the full local field
412
+ :math:`\\sum_k J_{ik} s_k`, an :math:`O(N)` sum, so one sweep of
413
+ :math:`N` attempted flips costs :math:`O(N^2)` -- the price of the
414
+ model's infinite-range connectivity.
415
+
416
+ Parameters
417
+ ----------
418
+ spins : ndarray of shape (N,), dtype int64
419
+ Spin configuration with values in ``{-1, +1}``. Modified in place.
420
+ beta : float
421
+ Inverse temperature.
422
+ J : ndarray of shape (N, N), dtype float64
423
+ Quenched, symmetric coupling matrix with zero diagonal.
424
+
425
+ Returns
426
+ -------
427
+ ndarray of shape (N,)
428
+ The same array passed in.
429
+ """
430
+ N = spins.shape[0]
431
+ for _ in range(N):
432
+ i = np.random.randint(0, N)
433
+ field = 0.0
434
+ for k in range(N):
435
+ field += J[i, k] * spins[k]
436
+ dE = 2.0 * spins[i] * field
437
+ if dE <= 0.0 or np.random.random() < np.exp(-beta * dE):
438
+ spins[i] = -spins[i]
439
+ return spins
440
+
441
+
442
+ @njit(cache=True)
443
+ def sk_total_energy(spins, J):
444
+ """Total Sherrington-Kirkpatrick Hamiltonian :math:`E = -\\sum_{i<j} J_{ij} s_i s_j`.
445
+
446
+ Parameters
447
+ ----------
448
+ spins : ndarray of shape (N,), dtype int64
449
+ Spin configuration with values in ``{-1, +1}``.
450
+ J : ndarray of shape (N, N), dtype float64
451
+ Quenched, symmetric coupling matrix with zero diagonal.
452
+
453
+ Returns
454
+ -------
455
+ float
456
+ """
457
+ N = spins.shape[0]
458
+ total = 0.0
459
+ for i in range(N):
460
+ for k in range(N):
461
+ total += J[i, k] * spins[i] * spins[k]
462
+ return -0.5 * total
@@ -0,0 +1,68 @@
1
+ """Numba-accelerated random walk trajectory generation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import numpy as np
6
+ from numba import njit
7
+
8
+ __all__ = ["simulate_gaussian_walks", "simulate_lattice_walks"]
9
+
10
+
11
+ @njit(cache=True)
12
+ def simulate_lattice_walks(n_walkers, n_steps, dim):
13
+ """Simulate independent nearest-neighbor random walks on a hypercubic lattice.
14
+
15
+ Each step picks one of the ``dim`` axes uniformly at random and moves
16
+ :math:`\\pm 1` along it.
17
+
18
+ Parameters
19
+ ----------
20
+ n_walkers : int
21
+ Number of independent walkers.
22
+ n_steps : int
23
+ Number of steps per walker.
24
+ dim : int
25
+ Spatial dimension.
26
+
27
+ Returns
28
+ -------
29
+ ndarray of shape (n_steps + 1, n_walkers, dim), dtype int64
30
+ Walker positions at every time, starting from the origin at ``t=0``.
31
+ """
32
+ positions = np.zeros((n_steps + 1, n_walkers, dim), dtype=np.int64)
33
+ for w in range(n_walkers):
34
+ pos = np.zeros(dim, dtype=np.int64)
35
+ for t in range(1, n_steps + 1):
36
+ axis = np.random.randint(0, dim)
37
+ step = 1 if np.random.random() < 0.5 else -1
38
+ pos[axis] += step
39
+ positions[t, w, :] = pos
40
+ return positions
41
+
42
+
43
+ @njit(cache=True)
44
+ def simulate_gaussian_walks(n_walkers, n_steps, dim, step_std):
45
+ """Simulate independent continuous Brownian walks with Gaussian steps.
46
+
47
+ Parameters
48
+ ----------
49
+ n_walkers : int
50
+ Number of independent walkers.
51
+ n_steps : int
52
+ Number of steps per walker.
53
+ dim : int
54
+ Spatial dimension.
55
+ step_std : float
56
+ Standard deviation of each per-axis Gaussian step.
57
+
58
+ Returns
59
+ -------
60
+ ndarray of shape (n_steps + 1, n_walkers, dim), dtype float64
61
+ Walker positions at every time, starting from the origin at ``t=0``.
62
+ """
63
+ positions = np.zeros((n_steps + 1, n_walkers, dim), dtype=np.float64)
64
+ for w in range(n_walkers):
65
+ for t in range(1, n_steps + 1):
66
+ for d in range(dim):
67
+ positions[t, w, d] = positions[t - 1, w, d] + np.random.normal(0.0, step_std)
68
+ return positions
@@ -0,0 +1,52 @@
1
+ """Numba-accelerated toppling dynamics for the Bak-Tang-Wiesenfeld sandpile."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from numba import njit
6
+
7
+ __all__ = ["topple_to_stability"]
8
+
9
+
10
+ @njit(cache=True)
11
+ def topple_to_stability(heights, threshold=4):
12
+ """Relax a sandpile height grid to stability by repeated toppling, in place.
13
+
14
+ Open boundary conditions: grains toppled off the edge are lost from the
15
+ system. A site with height >= ``threshold`` topples, losing
16
+ ``threshold`` grains and giving one grain to each of its (up to four)
17
+ orthogonal neighbors.
18
+
19
+ Parameters
20
+ ----------
21
+ heights : ndarray of shape (L, L), dtype int64
22
+ Grid of pile heights. Modified in place.
23
+ threshold : int, default=4
24
+ Critical height at which a site topples (4 is the standard BTW
25
+ value on the square lattice, one grain per neighbor direction).
26
+
27
+ Returns
28
+ -------
29
+ int
30
+ Total number of individual topplings that occurred during this
31
+ relaxation (the avalanche size).
32
+ """
33
+ L0, L1 = heights.shape
34
+ n_topplings = 0
35
+ unstable = True
36
+ while unstable:
37
+ unstable = False
38
+ for i in range(L0):
39
+ for j in range(L1):
40
+ if heights[i, j] >= threshold:
41
+ unstable = True
42
+ heights[i, j] -= threshold
43
+ n_topplings += 1
44
+ if i > 0:
45
+ heights[i - 1, j] += 1
46
+ if i < L0 - 1:
47
+ heights[i + 1, j] += 1
48
+ if j > 0:
49
+ heights[i, j - 1] += 1
50
+ if j < L1 - 1:
51
+ heights[i, j + 1] += 1
52
+ return n_topplings
File without changes
@@ -0,0 +1,66 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from physicskit.statphys.utils.dynamics import autocorrelation_function, integrated_autocorrelation_time
5
+
6
+
7
+ def test_autocorrelation_function_zero_lag_is_one():
8
+ rng = np.random.default_rng(0)
9
+ x = rng.normal(size=2000)
10
+ rho = autocorrelation_function(x)
11
+ assert rho[0] == pytest.approx(1.0)
12
+
13
+
14
+ def test_autocorrelation_decays_for_white_noise():
15
+ rng = np.random.default_rng(1)
16
+ x = rng.normal(size=5000)
17
+ rho = autocorrelation_function(x, max_lag=50)
18
+ assert abs(rho[20]) < 0.2
19
+
20
+
21
+ def test_autocorrelation_function_high_for_slow_series():
22
+ rng = np.random.default_rng(2)
23
+ # a slowly varying (highly autocorrelated) random walk
24
+ x = np.cumsum(rng.normal(size=2000))
25
+ rho = autocorrelation_function(x, max_lag=10)
26
+ assert rho[5] > 0.5
27
+
28
+
29
+ def test_integrated_autocorrelation_time_small_for_independent_samples():
30
+ rng = np.random.default_rng(3)
31
+ x = rng.normal(size=5000)
32
+ tau = integrated_autocorrelation_time(x)
33
+ assert 0.0 < tau < 3.0
34
+
35
+
36
+ def test_integrated_autocorrelation_time_larger_for_correlated_series():
37
+ rng = np.random.default_rng(4)
38
+ n = 5000
39
+ # AR(1) process with strong positive autocorrelation
40
+ x = np.empty(n)
41
+ x[0] = rng.normal()
42
+ phi = 0.9
43
+ for i in range(1, n):
44
+ x[i] = phi * x[i - 1] + rng.normal()
45
+
46
+ tau_correlated = integrated_autocorrelation_time(x)
47
+ tau_independent = integrated_autocorrelation_time(rng.normal(size=n))
48
+ assert tau_correlated > tau_independent
49
+
50
+
51
+ def test_integrated_autocorrelation_time_falls_back_when_window_never_closes():
52
+ # A strongly autocorrelated AR(1) series (tau grows large), restricted
53
+ # to a small max_lag: the automatic-windowing condition c*tau <= M is
54
+ # never satisfied within that short lag range, so the function should
55
+ # fall back to the full-sum estimate instead of raising or looping
56
+ # forever.
57
+ rng = np.random.default_rng(4)
58
+ n = 5000
59
+ x = np.empty(n)
60
+ x[0] = rng.normal()
61
+ phi = 0.95
62
+ for i in range(1, n):
63
+ x[i] = phi * x[i - 1] + rng.normal()
64
+
65
+ tau = integrated_autocorrelation_time(x, max_lag=3)
66
+ assert tau > 0.0
@@ -0,0 +1,44 @@
1
+ from physicskit.statphys.chapters.ehrenfest_urn import EhrenfestUrn
2
+
3
+
4
+ def test_default_starts_full():
5
+ urn = EhrenfestUrn(n_balls=50, seed=0)
6
+ assert urn.n_left == 50
7
+
8
+
9
+ def test_step_changes_n_left_by_one():
10
+ urn = EhrenfestUrn(n_balls=50, seed=1)
11
+ before = urn.n_left
12
+ after = urn.step()
13
+ assert abs(after - before) == 1
14
+
15
+
16
+ def test_n_left_bounded():
17
+ urn = EhrenfestUrn(n_balls=30, seed=2)
18
+ for _ in range(500):
19
+ urn.step()
20
+ assert 0 <= urn.n_left <= 30
21
+
22
+
23
+ def test_entropy_maximal_at_half_full():
24
+ urn = EhrenfestUrn(n_balls=40, n_left_init=20, seed=3)
25
+ S_half = urn.entropy()
26
+ urn2 = EhrenfestUrn(n_balls=40, n_left_init=40, seed=3)
27
+ S_full = urn2.entropy()
28
+ assert S_half > S_full
29
+
30
+
31
+ def test_relaxation_toward_equilibrium():
32
+ urn = EhrenfestUrn(n_balls=200, seed=4)
33
+ history = urn.run(3000)
34
+ early = history["n_left"][:50].mean()
35
+ late = history["n_left"][-500:].mean()
36
+ assert abs(late - 100) < abs(early - 100)
37
+
38
+
39
+ def test_run_history_shapes():
40
+ urn = EhrenfestUrn(n_balls=50, seed=5)
41
+ history = urn.run(100)
42
+ assert history["n_left"].shape == (101,)
43
+ assert history["entropy"].shape == (101,)
44
+ assert history["n_left"][0] == 50