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,112 @@
1
+ """The Ehrenfest urn model: the simplest illustration of statistical irreversibility.
2
+
3
+ Loschmidt and Zermelo objected that Boltzmann's H-theorem could not be
4
+ right, since microscopically reversible dynamics cannot produce genuinely
5
+ irreversible macroscopic behavior (Loschmidt), and any bounded mechanical
6
+ system must eventually return arbitrarily close to its initial state
7
+ (Zermelo, via Poincare recurrence). The Ehrenfests' 1907 urn model resolves
8
+ both objections in the simplest possible setting: the dynamics is exactly
9
+ reversible and does recur exactly, yet for any macroscopic number of balls
10
+ the expected recurrence time is astronomically long, while the approach to
11
+ equilibrium is essentially instantaneous -- reconciling reversible
12
+ microphysics with an observed arrow of time.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import numpy as np
18
+ from scipy.special import gammaln
19
+
20
+ __all__ = ["EhrenfestUrn"]
21
+
22
+
23
+ class EhrenfestUrn:
24
+ """The Ehrenfest urn model of N labeled balls exchanged between two boxes.
25
+
26
+ At each time step, one of the ``n_balls`` balls (chosen uniformly at
27
+ random) is moved from whichever box it currently occupies to the other.
28
+
29
+ Parameters
30
+ ----------
31
+ n_balls : int, default=100
32
+ Total number of balls, N.
33
+ n_left_init : int, optional
34
+ Initial number of balls in the left box. Defaults to ``n_balls``
35
+ (all balls start in one box, a maximally non-equilibrium state).
36
+ seed : int, optional
37
+ Seed for the ball-selection sequence.
38
+
39
+ Attributes
40
+ ----------
41
+ n_left : int
42
+ Current number of balls in the left box.
43
+ """
44
+
45
+ def __init__(self, n_balls=100, n_left_init=None, seed=None):
46
+ self.n_balls = n_balls
47
+ self.n_left = n_balls if n_left_init is None else n_left_init
48
+ self._rng = np.random.default_rng(seed)
49
+
50
+ def step(self):
51
+ """Move one uniformly random ball to the other box.
52
+
53
+ Returns
54
+ -------
55
+ int
56
+ The updated :attr:`n_left`.
57
+ """
58
+ chosen = self._rng.integers(0, self.n_balls)
59
+ if chosen < self.n_left:
60
+ self.n_left -= 1
61
+ else:
62
+ self.n_left += 1
63
+ return self.n_left
64
+
65
+ def entropy(self):
66
+ """Boltzmann entropy :math:`S/k_B = \\ln W` of the current macrostate.
67
+
68
+ :math:`W = \\binom{N}{n_{\\text{left}}}` counts the ball-labelings
69
+ consistent with the current left-box occupancy; the binomial
70
+ coefficient is evaluated via the log-gamma function
71
+ (``scipy.special.gammaln``) to stay numerically stable for large
72
+ :math:`N`.
73
+
74
+ Returns
75
+ -------
76
+ float
77
+ """
78
+ N, n = self.n_balls, self.n_left
79
+ return float(gammaln(N + 1) - gammaln(n + 1) - gammaln(N - n + 1))
80
+
81
+ def run(self, n_steps):
82
+ """Run the urn for ``n_steps`` and record its history.
83
+
84
+ Parameters
85
+ ----------
86
+ n_steps : int
87
+ Number of steps to simulate.
88
+
89
+ Returns
90
+ -------
91
+ dict of str -> ndarray
92
+ Keys ``"t"``, ``"n_left"``, ``"entropy"``, each of length
93
+ ``n_steps + 1`` (including the initial state).
94
+
95
+ Examples
96
+ --------
97
+ >>> urn = EhrenfestUrn(n_balls=50, seed=0)
98
+ >>> history = urn.run(200)
99
+ >>> history["n_left"].shape
100
+ (201,)
101
+ >>> int(history["n_left"][0])
102
+ 50
103
+ """
104
+ n_left = np.empty(n_steps + 1, dtype=np.int64)
105
+ entropy = np.empty(n_steps + 1, dtype=np.float64)
106
+ n_left[0] = self.n_left
107
+ entropy[0] = self.entropy()
108
+ for t in range(1, n_steps + 1):
109
+ self.step()
110
+ n_left[t] = self.n_left
111
+ entropy[t] = self.entropy()
112
+ return {"t": np.arange(n_steps + 1), "n_left": n_left, "entropy": entropy}
@@ -0,0 +1,431 @@
1
+ """Lattice spin models: the 2D Ising model, the q-state Potts model, and the XY model.
2
+
3
+ Three user-facing classes wrap the Numba kernels in
4
+ :mod:`physicskit.statphys.core.monte_carlo`:
5
+
6
+ - :class:`Ising2D` -- the archetypal discrete ferromagnet, with an exactly
7
+ known critical temperature and both Metropolis and Wolff dynamics.
8
+ - :class:`PottsModel2D` -- its :math:`q`-state generalization, whose
9
+ transition sharpens from second order (:math:`q \\le 4`) to first order
10
+ (:math:`q > 4`) on the square lattice.
11
+ - :class:`XYModel2D` -- continuous planar spins hosting the topological
12
+ Kosterlitz-Thouless transition, driven by vortex-antivortex unbinding
13
+ rather than symmetry breaking.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import numpy as np
19
+
20
+ from physicskit.statphys.core.monte_carlo import (
21
+ ising_total_energy,
22
+ ising_total_magnetization,
23
+ metropolis_sweep_ising,
24
+ metropolis_sweep_potts,
25
+ metropolis_sweep_xy,
26
+ potts_total_energy,
27
+ seed_numba_random,
28
+ wolff_step_ising,
29
+ xy_plaquette_vorticity,
30
+ xy_total_energy,
31
+ )
32
+ from physicskit.statphys.utils.thermodynamics import specific_heat, susceptibility
33
+
34
+ __all__ = ["Ising2D", "PottsModel2D", "XYModel2D"]
35
+
36
+
37
+ class Ising2D:
38
+ """The 2D ferromagnetic Ising model on a periodic :math:`L \\times L` lattice.
39
+
40
+ Parameters
41
+ ----------
42
+ L : int, default=32
43
+ Linear lattice size.
44
+ J : float, default=1.0
45
+ Ferromagnetic coupling constant.
46
+ kB : float, default=1.0
47
+ Boltzmann constant, in whatever unit system ``J`` and ``T`` are
48
+ expressed in.
49
+ seed : int, optional
50
+ Seed for reproducible initial spin configurations and Metropolis
51
+ dynamics.
52
+
53
+ Attributes
54
+ ----------
55
+ spins : ndarray of shape (L, L)
56
+ Current spin configuration, values in ``{-1, +1}``.
57
+
58
+ Examples
59
+ --------
60
+ >>> model = Ising2D(L=16, seed=0)
61
+ >>> model.sweep(beta=1.0, n_sweeps=50)
62
+ >>> -1.0 <= model.magnetization() / model.n_sites <= 1.0
63
+ True
64
+ """
65
+
66
+ def __init__(self, L=32, J=1.0, kB=1.0, seed=None):
67
+ self.L = L
68
+ self.J = J
69
+ self.kB = kB
70
+ self.n_sites = L * L
71
+ self._rng = np.random.default_rng(seed)
72
+ if seed is not None:
73
+ seed_numba_random(seed)
74
+ self.spins = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=(L, L))
75
+
76
+ @property
77
+ def T_C(self):
78
+ """Onsager's exact critical temperature, :math:`2J / (k_B \\ln(1 + \\sqrt{2})) \\approx 2.269 J / k_B`."""
79
+ return 2.0 * self.J / (self.kB * np.log(1.0 + np.sqrt(2.0)))
80
+
81
+ def reset(self, ordered=False):
82
+ """Reinitialize the spin configuration.
83
+
84
+ Parameters
85
+ ----------
86
+ ordered : bool, default=False
87
+ If True, start from a fully aligned (all ``+1``) configuration
88
+ (a low-temperature / :math:`T=0` state). Otherwise draw an
89
+ independent random ``\\pm 1`` configuration (a :math:`T=\\infty`
90
+ state).
91
+ """
92
+ if ordered:
93
+ self.spins = np.ones((self.L, self.L), dtype=np.int64)
94
+ else:
95
+ self.spins = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=(self.L, self.L))
96
+
97
+ def sweep(self, beta, algorithm="metropolis", n_sweeps=1):
98
+ """Advance the lattice by one or more Monte Carlo sweeps.
99
+
100
+ Parameters
101
+ ----------
102
+ beta : float
103
+ Inverse temperature :math:`1/(k_B T)`.
104
+ algorithm : {"metropolis", "wolff"}, default="metropolis"
105
+ Update rule. Metropolis flips single spins; Wolff grows and flips
106
+ whole clusters, which decorrelates much faster near :math:`T_c`.
107
+ n_sweeps : int, default=1
108
+ Number of sweeps (Metropolis) or cluster updates (Wolff) to
109
+ perform.
110
+
111
+ Returns
112
+ -------
113
+ int or None
114
+ For ``"wolff"``, the size of the last cluster flipped; ``None``
115
+ for ``"metropolis"``.
116
+ """
117
+ last_cluster = None
118
+ for _ in range(n_sweeps):
119
+ if algorithm == "metropolis":
120
+ metropolis_sweep_ising(self.spins, beta, self.J)
121
+ elif algorithm == "wolff":
122
+ last_cluster = wolff_step_ising(self.spins, beta, self.J)
123
+ else:
124
+ raise ValueError("algorithm must be 'metropolis' or 'wolff'")
125
+ return last_cluster
126
+
127
+ def energy(self):
128
+ """Total energy of the current configuration, :math:`-J \\sum_{\\langle i,j\\rangle} s_i s_j`."""
129
+ return ising_total_energy(self.spins, self.J)
130
+
131
+ def magnetization(self):
132
+ """Total magnetization :math:`M = \\sum_i s_i` of the current configuration."""
133
+ return ising_total_magnetization(self.spins)
134
+
135
+ def run_temperature_sweep(self, temperatures, n_equil=200, n_measure=500, algorithm="metropolis", measure_every=1):
136
+ """Sweep over a range of temperatures, measuring equilibrium thermodynamics at each.
137
+
138
+ At every temperature the lattice is first equilibrated for
139
+ ``n_equil`` sweeps, then sampled every ``measure_every`` sweeps for
140
+ ``n_measure`` measurements, from which the specific heat and magnetic
141
+ susceptibility are estimated via their fluctuation-dissipation
142
+ relations. The final configuration at each temperature seeds the next
143
+ (simulated annealing), which shortens equilibration as the sweep
144
+ proceeds.
145
+
146
+ Parameters
147
+ ----------
148
+ temperatures : array_like
149
+ Temperatures to sample, typically ordered from high to low to
150
+ exploit annealing.
151
+ n_equil : int, default=200
152
+ Equilibration sweeps discarded before measuring at each
153
+ temperature.
154
+ n_measure : int, default=500
155
+ Number of measurements collected at each temperature.
156
+ algorithm : {"metropolis", "wolff"}, default="metropolis"
157
+ Update rule, see :meth:`sweep`.
158
+ measure_every : int, default=1
159
+ Number of sweeps between successive measurements.
160
+
161
+ Returns
162
+ -------
163
+ dict of str -> ndarray
164
+ Keys ``"T"``, ``"E"``, ``"M"``, ``"C_v"``, ``"chi"``, each an
165
+ array aligned with ``temperatures``. ``"E"`` and ``"M"`` are
166
+ per-site averages; ``"C_v"`` and ``"chi"`` are per-site.
167
+
168
+ Examples
169
+ --------
170
+ >>> model = Ising2D(L=12, seed=1)
171
+ >>> result = model.run_temperature_sweep(
172
+ ... [3.5, 2.269, 1.0], n_equil=20, n_measure=20
173
+ ... )
174
+ >>> sorted(result.keys())
175
+ ['C_v', 'E', 'M', 'T', 'chi']
176
+ """
177
+ temperatures = np.asarray(temperatures, dtype=np.float64)
178
+ n_T = len(temperatures)
179
+ E_mean = np.empty(n_T)
180
+ M_mean = np.empty(n_T)
181
+ C_v = np.empty(n_T)
182
+ chi = np.empty(n_T)
183
+
184
+ for k, T in enumerate(temperatures):
185
+ beta = 1.0 / (self.kB * T)
186
+ self.sweep(beta, algorithm=algorithm, n_sweeps=n_equil)
187
+
188
+ energies = np.empty(n_measure)
189
+ magnetizations = np.empty(n_measure)
190
+ for m in range(n_measure):
191
+ self.sweep(beta, algorithm=algorithm, n_sweeps=measure_every)
192
+ energies[m] = self.energy()
193
+ magnetizations[m] = self.magnetization()
194
+
195
+ E_mean[k] = energies.mean() / self.n_sites
196
+ M_mean[k] = np.abs(magnetizations).mean() / self.n_sites
197
+ C_v[k] = specific_heat(energies, T, self.n_sites, kB=self.kB)
198
+ chi[k] = susceptibility(np.abs(magnetizations), T, self.n_sites, kB=self.kB)
199
+
200
+ return {"T": temperatures, "E": E_mean, "M": M_mean, "C_v": C_v, "chi": chi}
201
+
202
+
203
+ class PottsModel2D:
204
+ """The 2D ferromagnetic q-state Potts model on a periodic :math:`L \\times L` lattice.
205
+
206
+ Each site carries a discrete state :math:`s_i \\in \\{0, \\ldots, q-1\\}`,
207
+ and the Hamiltonian rewards neighboring sites for matching:
208
+ :math:`H = -J \\sum_{\\langle i,j \\rangle} \\delta(s_i, s_j)`. The Ising
209
+ model is the special case :math:`q = 2` (with a rescaled coupling). On the
210
+ square lattice the transition is second order for :math:`q \\le 4` and
211
+ first order for :math:`q > 4`.
212
+
213
+ Parameters
214
+ ----------
215
+ L : int, default=32
216
+ Linear lattice size.
217
+ q : int, default=3
218
+ Number of Potts states.
219
+ J : float, default=1.0
220
+ Coupling constant.
221
+ kB : float, default=1.0
222
+ Boltzmann constant.
223
+ seed : int, optional
224
+ Seed for reproducible dynamics.
225
+
226
+ Attributes
227
+ ----------
228
+ spins : ndarray of shape (L, L)
229
+ Current state configuration, values in ``{0, ..., q-1}``.
230
+ """
231
+
232
+ def __init__(self, L=32, q=3, J=1.0, kB=1.0, seed=None):
233
+ self.L = L
234
+ self.q = q
235
+ self.J = J
236
+ self.kB = kB
237
+ self.n_sites = L * L
238
+ self._rng = np.random.default_rng(seed)
239
+ if seed is not None:
240
+ seed_numba_random(seed)
241
+ self.spins = self._rng.integers(0, q, size=(L, L)).astype(np.int64)
242
+
243
+ @property
244
+ def T_C(self):
245
+ """Exact critical temperature of the square-lattice Potts model, :math:`J / (k_B \\ln(1 + \\sqrt{q}))`."""
246
+ return self.J / (self.kB * np.log(1.0 + np.sqrt(self.q)))
247
+
248
+ def sweep(self, beta, n_sweeps=1):
249
+ """Advance the lattice by ``n_sweeps`` Metropolis-Hastings sweeps.
250
+
251
+ Parameters
252
+ ----------
253
+ beta : float
254
+ Inverse temperature.
255
+ n_sweeps : int, default=1
256
+ Number of sweeps to perform.
257
+ """
258
+ for _ in range(n_sweeps):
259
+ metropolis_sweep_potts(self.spins, beta, self.J, self.q)
260
+
261
+ def energy(self):
262
+ """Total energy :math:`-J \\sum_{\\langle i,j\\rangle} \\delta(s_i, s_j)` of the current configuration."""
263
+ return potts_total_energy(self.spins, self.J)
264
+
265
+ def order_parameter(self):
266
+ """Potts order parameter, the rescaled fraction of sites in the majority state.
267
+
268
+ .. math::
269
+
270
+ m = \\frac{q \\cdot n_{\\max} / N - 1}{q - 1}
271
+
272
+ where :math:`n_{\\max}` is the largest population among the ``q``
273
+ states. ``m`` is ``0`` in the fully disordered phase and ``1`` in the
274
+ fully ordered phase.
275
+
276
+ Returns
277
+ -------
278
+ float
279
+ """
280
+ counts = np.bincount(self.spins.ravel(), minlength=self.q)
281
+ n_max = counts.max()
282
+ return (self.q * n_max / self.n_sites - 1.0) / (self.q - 1.0)
283
+
284
+ def run_temperature_sweep(self, temperatures, n_equil=200, n_measure=500, measure_every=1):
285
+ """Sweep over temperatures, measuring energy, order parameter, and specific heat.
286
+
287
+ See :meth:`Ising2D.run_temperature_sweep` for the equilibration and
288
+ measurement protocol; this follows the same pattern.
289
+
290
+ Parameters
291
+ ----------
292
+ temperatures : array_like
293
+ Temperatures to sample.
294
+ n_equil : int, default=200
295
+ Equilibration sweeps at each temperature.
296
+ n_measure : int, default=500
297
+ Measurements collected at each temperature.
298
+ measure_every : int, default=1
299
+ Sweeps between successive measurements.
300
+
301
+ Returns
302
+ -------
303
+ dict of str -> ndarray
304
+ Keys ``"T"``, ``"E"``, ``"m"``, ``"C_v"``.
305
+ """
306
+ temperatures = np.asarray(temperatures, dtype=np.float64)
307
+ n_T = len(temperatures)
308
+ E_mean = np.empty(n_T)
309
+ m_mean = np.empty(n_T)
310
+ C_v = np.empty(n_T)
311
+
312
+ for k, T in enumerate(temperatures):
313
+ beta = 1.0 / (self.kB * T)
314
+ self.sweep(beta, n_sweeps=n_equil)
315
+
316
+ energies = np.empty(n_measure)
317
+ orders = np.empty(n_measure)
318
+ for i in range(n_measure):
319
+ self.sweep(beta, n_sweeps=measure_every)
320
+ energies[i] = self.energy()
321
+ orders[i] = self.order_parameter()
322
+
323
+ E_mean[k] = energies.mean() / self.n_sites
324
+ m_mean[k] = orders.mean()
325
+ C_v[k] = specific_heat(energies, T, self.n_sites, kB=self.kB)
326
+
327
+ return {"T": temperatures, "E": E_mean, "m": m_mean, "C_v": C_v}
328
+
329
+
330
+ class XYModel2D:
331
+ """The 2D classical XY model on a periodic :math:`L \\times L` lattice.
332
+
333
+ Each site carries a planar spin angle :math:`\\theta_i \\in [0, 2\\pi)`,
334
+ with Hamiltonian :math:`H = -J \\sum_{\\langle i,j \\rangle}
335
+ \\cos(\\theta_i - \\theta_j)`. The Mermin-Wagner theorem forbids
336
+ conventional long-range order in 2D, but the model still hosts the
337
+ topological Kosterlitz-Thouless (KT) transition at
338
+ :math:`T_{\\text{KT}} \\approx 0.893\\, J / k_B`: bound vortex-antivortex
339
+ pairs at low temperature unbind into a free vortex plasma above
340
+ :math:`T_{\\text{KT}}`.
341
+
342
+ Parameters
343
+ ----------
344
+ L : int, default=32
345
+ Linear lattice size.
346
+ J : float, default=1.0
347
+ Coupling constant.
348
+ kB : float, default=1.0
349
+ Boltzmann constant.
350
+ seed : int, optional
351
+ Seed for reproducible dynamics.
352
+
353
+ Attributes
354
+ ----------
355
+ theta : ndarray of shape (L, L)
356
+ Current spin angles, in radians.
357
+ """
358
+
359
+ #: Numerically established Kosterlitz-Thouless temperature, in units of J/kB.
360
+ _T_KT_REDUCED = 0.8929
361
+
362
+ def __init__(self, L=32, J=1.0, kB=1.0, seed=None):
363
+ self.L = L
364
+ self.J = J
365
+ self.kB = kB
366
+ self.n_sites = L * L
367
+ self._rng = np.random.default_rng(seed)
368
+ if seed is not None:
369
+ seed_numba_random(seed)
370
+ self.theta = self._rng.uniform(0.0, 2.0 * np.pi, size=(L, L))
371
+
372
+ @property
373
+ def T_KT(self):
374
+ """Approximate (numerically established) Kosterlitz-Thouless transition temperature, :math:`\\approx 0.893\\, J / k_B`."""
375
+ return self._T_KT_REDUCED * self.J / self.kB
376
+
377
+ def sweep(self, beta, n_sweeps=1, delta=1.0):
378
+ """Advance the lattice by ``n_sweeps`` Metropolis-Hastings sweeps.
379
+
380
+ Parameters
381
+ ----------
382
+ beta : float
383
+ Inverse temperature.
384
+ n_sweeps : int, default=1
385
+ Number of sweeps to perform.
386
+ delta : float, default=1.0
387
+ Maximum trial angular step (radians); tune towards an acceptance
388
+ rate near 50% for efficient sampling.
389
+ """
390
+ for _ in range(n_sweeps):
391
+ metropolis_sweep_xy(self.theta, beta, self.J, delta)
392
+
393
+ def energy(self):
394
+ """Total energy :math:`-J \\sum_{\\langle i,j\\rangle} \\cos(\\theta_i - \\theta_j)` of the current configuration."""
395
+ return xy_total_energy(self.theta, self.J)
396
+
397
+ def magnetization_vector(self):
398
+ """Net planar magnetization vector :math:`(\\sum_i \\cos\\theta_i, \\sum_i \\sin\\theta_i)`."""
399
+ return np.array([np.cos(self.theta).sum(), np.sin(self.theta).sum()])
400
+
401
+ def vorticity(self):
402
+ """Topological charge of every plaquette; see :func:`physicskit.statphys.core.monte_carlo.xy_plaquette_vorticity`.
403
+
404
+ Returns
405
+ -------
406
+ ndarray of shape (L, L)
407
+ Plaquette vorticity, close to an integer everywhere and nonzero
408
+ (:math:`\\pm 1`) at vortex/antivortex cores.
409
+ """
410
+ return xy_plaquette_vorticity(self.theta)
411
+
412
+ def vortex_count(self, threshold=0.5):
413
+ """Count vortices and antivortices by thresholding the plaquette vorticity.
414
+
415
+ Parameters
416
+ ----------
417
+ threshold : float, default=0.5
418
+ Minimum ``|vorticity|`` for a plaquette to be counted as hosting
419
+ a topological charge.
420
+
421
+ Returns
422
+ -------
423
+ n_vortices : int
424
+ Number of plaquettes with vorticity near ``+1``.
425
+ n_antivortices : int
426
+ Number of plaquettes with vorticity near ``-1``.
427
+ """
428
+ q = self.vorticity()
429
+ n_vortices = int(np.sum(q > threshold))
430
+ n_antivortices = int(np.sum(q < -threshold))
431
+ return n_vortices, n_antivortices
@@ -0,0 +1,129 @@
1
+ """The Kardar-Parisi-Zhang equation: universal roughening of growing interfaces.
2
+
3
+ Kardar, Parisi, and Zhang's 1986 stochastic partial differential equation,
4
+
5
+ .. math::
6
+
7
+ \\frac{\\partial h}{\\partial t} = \\nu \\nabla^2 h
8
+ + \\frac{\\lambda}{2}(\\nabla h)^2 + \\eta(x, t),
9
+
10
+ describes a growing interface driven by uncorrelated noise :math:`\\eta`,
11
+ smoothed by surface tension :math:`\\nu`, and locally accelerated by the
12
+ nonlinear slope term :math:`\\lambda(\\nabla h)^2` -- growth normal to the
13
+ surface, not straight up. That nonlinear term is what separates the KPZ
14
+ universality class from the simpler Edwards-Wilkinson equation
15
+ (:math:`\\lambda = 0`): it couples length scales together and produces a
16
+ new, nontrivial set of scaling exponents shared by an enormous range of
17
+ physical growth processes, from bacterial colonies to burning paper fronts.
18
+
19
+ Rather than discretize the continuum SPDE directly (whose nonlinear term is
20
+ notoriously delicate to finite-difference consistently), this module
21
+ implements the Restricted Solid-On-Solid (RSOS) model, an exact discrete
22
+ growth automaton with no adjustable surface-tension or coupling parameters
23
+ at all, long established (Kim & Kosterlitz, 1989) to lie in the KPZ
24
+ universality class.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import numpy as np
30
+
31
+ from physicskit.statphys.core.kpz_engine import run_rsos
32
+ from physicskit.statphys.core.monte_carlo import seed_numba_random
33
+
34
+ __all__ = ["KPZInterface"]
35
+
36
+
37
+ class KPZInterface:
38
+ """A 1D Restricted Solid-On-Solid growing interface on a periodic lattice of L sites.
39
+
40
+ Parameters
41
+ ----------
42
+ L : int, default=256
43
+ Number of sites (periodic boundary conditions).
44
+ seed : int, optional
45
+ Seed for the random deposition-site sequence.
46
+
47
+ Attributes
48
+ ----------
49
+ heights : ndarray of shape (L,)
50
+ Current interface height profile, initialized flat at zero.
51
+ time : float
52
+ Elapsed time, in units of Monte Carlo sweeps (one sweep = L
53
+ attempted deposition events).
54
+ """
55
+
56
+ def __init__(self, L=256, seed=None):
57
+ self.L = L
58
+ self.heights = np.zeros(L, dtype=np.int64)
59
+ self.time = 0.0
60
+ if seed is not None:
61
+ seed_numba_random(seed)
62
+
63
+ def grow(self, n_sweeps=1):
64
+ """Advance the interface by ``n_sweeps`` Monte Carlo sweeps of RSOS deposition.
65
+
66
+ Parameters
67
+ ----------
68
+ n_sweeps : float, default=1
69
+ Number of sweeps (``L`` deposition attempts each) to perform.
70
+ """
71
+ n_attempts = int(round(n_sweeps * self.L))
72
+ run_rsos(self.heights, n_attempts, self.L)
73
+ self.time += n_sweeps
74
+
75
+ def width(self):
76
+ """Interface width :math:`w = \\sqrt{\\langle (h - \\bar h)^2 \\rangle}`, the key KPZ observable.
77
+
78
+ Returns
79
+ -------
80
+ float
81
+ """
82
+ h = self.heights.astype(np.float64)
83
+ return float(np.sqrt(np.mean((h - h.mean()) ** 2)))
84
+
85
+ def mean_height(self):
86
+ """Mean interface height :math:`\\bar h`, which grows linearly in time on average."""
87
+ return float(self.heights.mean())
88
+
89
+ def run_growth_curve(self, t_max, n_points=40, log_spaced=True):
90
+ """Grow the interface while recording the width at a sequence of checkpoint times.
91
+
92
+ The width is expected to grow as :math:`w(t) \\sim t^{\\beta}` with
93
+ :math:`\\beta = 1/3` at early times, crossing over to a
94
+ length-limited saturation :math:`w_{\\text{sat}} \\sim L^{\\alpha}`
95
+ with :math:`\\alpha = 1/2` once :math:`t` exceeds the correlation
96
+ time :math:`\\sim L^{z}` (:math:`z = 3/2`).
97
+
98
+ Parameters
99
+ ----------
100
+ t_max : float
101
+ Final time (in sweeps) to grow to.
102
+ n_points : int, default=40
103
+ Number of checkpoints to record.
104
+ log_spaced : bool, default=True
105
+ Use logarithmically spaced checkpoints (recommended for
106
+ resolving the early-time power-law growth regime) rather than
107
+ linearly spaced ones.
108
+
109
+ Returns
110
+ -------
111
+ times : ndarray of shape (n_points,)
112
+ widths : ndarray of shape (n_points,)
113
+ """
114
+ if log_spaced:
115
+ checkpoints = np.unique(np.round(np.logspace(0, np.log10(t_max), n_points)).astype(np.int64))
116
+ else:
117
+ checkpoints = np.unique(np.round(np.linspace(1, t_max, n_points)).astype(np.int64))
118
+
119
+ times = np.empty(len(checkpoints))
120
+ widths = np.empty(len(checkpoints))
121
+ t_done = 0
122
+ for k, t in enumerate(checkpoints):
123
+ dt = int(t) - t_done
124
+ if dt > 0:
125
+ self.grow(n_sweeps=dt)
126
+ t_done = int(t)
127
+ times[k] = self.time
128
+ widths[k] = self.width()
129
+ return times, widths