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,275 @@
1
+ """Spin glasses: quenched disorder, frustration, and replica symmetry breaking.
2
+
3
+ Unlike the pure Ising model, where every bond has the same sign, a spin
4
+ glass's bond couplings are themselves random variables, fixed ("quenched")
5
+ for the lifetime of a given sample rather than fluctuating with the spins.
6
+ A plaquette with an odd number of antiferromagnetic bonds is *frustrated*:
7
+ no spin configuration can satisfy every one of its bonds simultaneously.
8
+ This produces a rugged, many-valley energy landscape and, below a spin-glass
9
+ transition temperature, a frozen but disordered ground state -- detected not
10
+ by a conventional magnetization but by the Edwards-Anderson order
11
+ parameter, the overlap between two independently thermalized replicas of
12
+ the same disorder realization.
13
+
14
+ :class:`EdwardsAndersonSpinGlass2D` is the short-range, nearest-neighbor
15
+ version of this story on a 2D lattice. :class:`SherringtonKirkpatrick` is
16
+ its infinite-range completion: every spin couples to every other spin, the
17
+ model Sherrington and Kirkpatrick introduced in 1975 and that Giorgio
18
+ Parisi's 1979-1980 replica-symmetry-breaking solution ultimately resolved,
19
+ revealing an equilibrium phase built not from one ground state but from a
20
+ hierarchy of infinitely many, organized by a nontrivial overlap
21
+ distribution :math:`P(q)` rather than a single frozen value.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import numpy as np
27
+
28
+ from physicskit.statphys.core.monte_carlo import (
29
+ metropolis_sweep_sk,
30
+ metropolis_sweep_spin_glass,
31
+ seed_numba_random,
32
+ sk_total_energy,
33
+ spin_glass_total_energy,
34
+ )
35
+
36
+ __all__ = ["EdwardsAndersonSpinGlass2D", "SherringtonKirkpatrick"]
37
+
38
+
39
+ class EdwardsAndersonSpinGlass2D:
40
+ """The 2D +/-J Edwards-Anderson Ising spin glass on a periodic L x L lattice.
41
+
42
+ Parameters
43
+ ----------
44
+ L : int, default=32
45
+ Linear lattice size.
46
+ J : float, default=1.0
47
+ Bond magnitude; each bond independently takes the value ``+J`` or
48
+ ``-J`` with equal probability (the "bimodal" Edwards-Anderson
49
+ glass).
50
+ kB : float, default=1.0
51
+ Boltzmann constant.
52
+ seed : int, optional
53
+ Seed for the quenched disorder realization, the initial spin
54
+ configuration, and the Metropolis dynamics.
55
+
56
+ Attributes
57
+ ----------
58
+ spins : ndarray of shape (L, L)
59
+ Current spin configuration, values in ``{-1, +1}``.
60
+ J_right, J_down : ndarray of shape (L, L)
61
+ Quenched bond couplings; see
62
+ :func:`physicskit.statphys.core.monte_carlo.metropolis_sweep_spin_glass` for
63
+ their indexing convention. Fixed for the model's lifetime.
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
+ self.J_right = self._rng.choice(np.array([-J, J]), size=(L, L))
76
+ self.J_down = self._rng.choice(np.array([-J, J]), size=(L, L))
77
+
78
+ def sweep(self, beta, n_sweeps=1):
79
+ """Advance the spins by ``n_sweeps`` Metropolis-Hastings sweeps (bonds are fixed).
80
+
81
+ Parameters
82
+ ----------
83
+ beta : float
84
+ Inverse temperature.
85
+ n_sweeps : int, default=1
86
+ Number of sweeps to perform.
87
+ """
88
+ for _ in range(n_sweeps):
89
+ metropolis_sweep_spin_glass(self.spins, beta, self.J_right, self.J_down)
90
+
91
+ def energy(self):
92
+ """Total energy :math:`-\\sum_{\\langle i,j\\rangle} J_{ij} s_i s_j` of the current configuration."""
93
+ return spin_glass_total_energy(self.spins, self.J_right, self.J_down)
94
+
95
+ def frustration_density(self):
96
+ """Fraction of elementary plaquettes that are frustrated.
97
+
98
+ A plaquette is frustrated when the product of its four bond
99
+ couplings is negative -- no spin configuration can satisfy all four
100
+ bonds at once. This is a fixed geometric property of the quenched
101
+ disorder, independent of the current spin configuration.
102
+
103
+ Returns
104
+ -------
105
+ float
106
+ """
107
+ product = self.J_right * np.roll(self.J_down, -1, axis=1) * np.roll(self.J_right, -1, axis=0) * self.J_down
108
+ return float(np.mean(product < 0))
109
+
110
+ def edwards_anderson_order_parameter(self, beta, n_equil=200, n_measure=200, measure_every=1):
111
+ """Estimate :math:`\\langle q^2 \\rangle`, the mean-squared Edwards-Anderson replica overlap.
112
+
113
+ Two independently initialized and thermalized replicas, sharing the
114
+ *same* quenched bonds, are compared via their spin overlap
115
+ :math:`q = \\frac{1}{N}\\sum_i s_i^{(1)} s_i^{(2)}`. Even though
116
+ each replica's spins keep fluctuating, below the spin-glass
117
+ transition they fluctuate around the same disorder-selected frozen
118
+ pattern, so :math:`\\langle q^2 \\rangle` stays nonzero; above it,
119
+ the replicas decorrelate and :math:`\\langle q^2 \\rangle \\to 0`.
120
+
121
+ Parameters
122
+ ----------
123
+ beta : float
124
+ Inverse temperature.
125
+ n_equil : int, default=200
126
+ Equilibration sweeps for each replica.
127
+ n_measure : int, default=200
128
+ Number of overlap measurements.
129
+ measure_every : int, default=1
130
+ Sweeps between successive measurements.
131
+
132
+ Returns
133
+ -------
134
+ float
135
+ Estimated :math:`\\langle q^2 \\rangle \\in [0, 1]`.
136
+ """
137
+ replica_a = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=(self.L, self.L))
138
+ replica_b = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=(self.L, self.L))
139
+ for _ in range(n_equil):
140
+ metropolis_sweep_spin_glass(replica_a, beta, self.J_right, self.J_down)
141
+ metropolis_sweep_spin_glass(replica_b, beta, self.J_right, self.J_down)
142
+
143
+ overlaps = np.empty(n_measure)
144
+ for k in range(n_measure):
145
+ for _ in range(measure_every):
146
+ metropolis_sweep_spin_glass(replica_a, beta, self.J_right, self.J_down)
147
+ metropolis_sweep_spin_glass(replica_b, beta, self.J_right, self.J_down)
148
+ overlaps[k] = np.mean(replica_a * replica_b)
149
+ return float(np.mean(overlaps**2))
150
+
151
+
152
+ class SherringtonKirkpatrick:
153
+ """The infinite-range Sherrington-Kirkpatrick Ising spin glass on N fully-connected spins.
154
+
155
+ Every pair of spins is coupled by an independent Gaussian random bond,
156
+
157
+ .. math::
158
+
159
+ H = -\\sum_{i<j} J_{ij}\\, s_i s_j, \\qquad
160
+ J_{ij} \\sim \\mathcal{N}\\!\\left(0, \\frac{J^2}{N}\\right),
161
+
162
+ where the :math:`1/N` variance scaling is what keeps the energy
163
+ extensive as :math:`N \\to \\infty`. Rather than attempt Parisi's
164
+ analytic replica-symmetry-breaking solution, :meth:`overlap_distribution`
165
+ measures its numerically observable fingerprint directly: the
166
+ distribution :math:`P(q)` of the replica overlap
167
+ :math:`q = \\frac{1}{N}\\sum_i s_i^{(1)} s_i^{(2)}`, pooled over many
168
+ independent disorder realizations. A single sharp peak at :math:`q=0`
169
+ signals the trivial (replica-symmetric) paramagnetic phase; a broad,
170
+ non-Gaussian, non-self-averaging :math:`P(q)` is the finite-size
171
+ signature of the many-valley spin-glass phase that Parisi's solution
172
+ describes exactly in the :math:`N \\to \\infty` limit.
173
+
174
+ Parameters
175
+ ----------
176
+ N : int, default=128
177
+ Number of spins. Note one sweep costs :math:`O(N^2)`, since every
178
+ spin couples to every other one.
179
+ J : float, default=1.0
180
+ Coupling scale; bond strengths are drawn from :math:`\\mathcal{N}(0,
181
+ J^2/N)`.
182
+ kB : float, default=1.0
183
+ Boltzmann constant.
184
+ seed : int, optional
185
+ Seed for the quenched disorder, initial spins, and dynamics.
186
+
187
+ Attributes
188
+ ----------
189
+ spins : ndarray of shape (N,)
190
+ Current spin configuration, values in ``{-1, +1}``.
191
+ J : ndarray of shape (N, N)
192
+ Quenched, symmetric coupling matrix with zero diagonal. Fixed for
193
+ the model's lifetime.
194
+ """
195
+
196
+ def __init__(self, N=128, J=1.0, kB=1.0, seed=None):
197
+ self.N = N
198
+ self.J_scale = J
199
+ self.kB = kB
200
+ self._rng = np.random.default_rng(seed)
201
+ if seed is not None:
202
+ seed_numba_random(seed)
203
+ self.spins = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=N)
204
+ bonds = self._rng.normal(loc=0.0, scale=J / np.sqrt(N), size=(N, N))
205
+ upper = np.triu(bonds, k=1)
206
+ self.J = upper + upper.T
207
+
208
+ def sweep(self, beta, n_sweeps=1):
209
+ """Advance the spins by ``n_sweeps`` Metropolis-Hastings sweeps (bonds are fixed).
210
+
211
+ Parameters
212
+ ----------
213
+ beta : float
214
+ Inverse temperature.
215
+ n_sweeps : int, default=1
216
+ Number of sweeps to perform.
217
+ """
218
+ for _ in range(n_sweeps):
219
+ metropolis_sweep_sk(self.spins, beta, self.J)
220
+
221
+ def energy(self):
222
+ """Total energy :math:`-\\sum_{i<j} J_{ij} s_i s_j` of the current configuration."""
223
+ return sk_total_energy(self.spins, self.J)
224
+
225
+ def overlap_distribution(self, beta, n_disorder=30, n_equil=300, n_measure=100, measure_every=1):
226
+ """Sample the replica-overlap distribution P(q), pooled over independent disorder realizations.
227
+
228
+ For each of ``n_disorder`` independent bond realizations, two
229
+ replicas are initialized randomly, thermalized under that shared
230
+ disorder, and their overlap :math:`q = \\frac{1}{N}\\sum_i
231
+ s_i^{(1)} s_i^{(2)}` recorded repeatedly. Pooling samples across
232
+ many disorder realizations (rather than just many measurements of
233
+ one realization) is essential here: unlike the Edwards-Anderson
234
+ model's single well-defined :math:`\\langle q^2 \\rangle`, the SK
235
+ spin glass's overlap distribution is sample-dependent (it does not
236
+ self-average) below the transition, and it is exactly this
237
+ sample-to-sample variability that Parisi's solution organizes into
238
+ a hierarchy of pure states.
239
+
240
+ Parameters
241
+ ----------
242
+ beta : float
243
+ Inverse temperature.
244
+ n_disorder : int, default=30
245
+ Number of independent quenched-disorder realizations to sample.
246
+ n_equil : int, default=300
247
+ Equilibration sweeps per replica, for each disorder realization.
248
+ n_measure : int, default=100
249
+ Number of overlap measurements per disorder realization.
250
+ measure_every : int, default=1
251
+ Sweeps between successive measurements.
252
+
253
+ Returns
254
+ -------
255
+ ndarray of shape (n_disorder * n_measure,)
256
+ Pooled overlap samples :math:`q \\in [-1, 1]`.
257
+ """
258
+ samples = np.empty(n_disorder * n_measure)
259
+ idx = 0
260
+ for _ in range(n_disorder):
261
+ bonds = self._rng.normal(loc=0.0, scale=self.J_scale / np.sqrt(self.N), size=(self.N, self.N))
262
+ upper = np.triu(bonds, k=1)
263
+ J = upper + upper.T
264
+ replica_a = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=self.N)
265
+ replica_b = self._rng.choice(np.array([-1, 1], dtype=np.int64), size=self.N)
266
+ for _ in range(n_equil):
267
+ metropolis_sweep_sk(replica_a, beta, J)
268
+ metropolis_sweep_sk(replica_b, beta, J)
269
+ for _ in range(n_measure):
270
+ for _ in range(measure_every):
271
+ metropolis_sweep_sk(replica_a, beta, J)
272
+ metropolis_sweep_sk(replica_b, beta, J)
273
+ samples[idx] = np.mean(replica_a * replica_b)
274
+ idx += 1
275
+ return samples
@@ -0,0 +1,10 @@
1
+ """Low-level, Numba-accelerated simulation kernels.
2
+
3
+ :mod:`physicskit.statphys.core.monte_carlo` holds the Metropolis-Hastings and Wolff
4
+ lattice-update kernels used by :mod:`physicskit.statphys.chapters.ising_lattice`.
5
+ :mod:`physicskit.statphys.core.md_engine` holds the Lennard-Jones force evaluation and
6
+ Velocity Verlet integrator used by :mod:`physicskit.statphys.chapters.molecular_dynamics`.
7
+
8
+ These functions operate on plain NumPy arrays and carry no state; the
9
+ stateful, user-facing model classes live in :mod:`physicskit.statphys.chapters`.
10
+ """
@@ -0,0 +1,53 @@
1
+ """Numba-accelerated Restricted Solid-On-Solid (RSOS) growth dynamics.
2
+
3
+ The RSOS model is the standard discrete lattice realization of the
4
+ Kardar-Parisi-Zhang universality class in 1+1 dimensions: a local growth
5
+ rule with no free parameters to tune, whose interface width nonetheless
6
+ reproduces the continuum KPZ equation's universal roughness, growth, and
7
+ dynamic exponents.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import numpy as np
13
+ from numba import njit
14
+
15
+ __all__ = ["run_rsos"]
16
+
17
+
18
+ @njit(cache=True)
19
+ def run_rsos(heights, n_attempts, L):
20
+ """Attempt ``n_attempts`` random single-site RSOS deposition events, in place.
21
+
22
+ At each attempt, a uniformly random site ``i`` is chosen and its height
23
+ tentatively raised by one. The move is accepted only if it keeps the
24
+ restricted solid-on-solid constraint :math:`|h_i - h_{i\\pm1}| \\le 1`
25
+ satisfied with both periodic neighbors; otherwise the site is left
26
+ unchanged. This single local constraint -- with no explicit surface
27
+ tension or nonlinear term written anywhere -- is enough to place the
28
+ resulting interface in the KPZ universality class.
29
+
30
+ Parameters
31
+ ----------
32
+ heights : ndarray of shape (L,), dtype int64
33
+ Interface height profile. Modified in place.
34
+ n_attempts : int
35
+ Number of random deposition attempts to perform. One Monte Carlo
36
+ sweep conventionally corresponds to ``n_attempts = L``, i.e. one
37
+ attempt per site on average.
38
+ L : int
39
+ Number of sites (periodic boundary conditions).
40
+
41
+ Returns
42
+ -------
43
+ ndarray of shape (L,)
44
+ The same array passed in.
45
+ """
46
+ for _ in range(n_attempts):
47
+ i = np.random.randint(0, L)
48
+ left = heights[(i - 1) % L]
49
+ right = heights[(i + 1) % L]
50
+ new_h = heights[i] + 1
51
+ if abs(new_h - left) <= 1 and abs(new_h - right) <= 1:
52
+ heights[i] = new_h
53
+ return heights
@@ -0,0 +1,157 @@
1
+ """Numba-accelerated molecular dynamics engine: Lennard-Jones forces and Velocity Verlet.
2
+
3
+ Implements a minimal-image, periodic-boundary N-body simulator for a 2D
4
+ Lennard-Jones gas. The pairwise force evaluation is the O(N^2) inner loop and
5
+ is the part that benefits from JIT compilation; everything else is thin
6
+ Python bookkeeping around it.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import numpy as np
12
+ from numba import njit
13
+
14
+ __all__ = ["initialize_maxwell_boltzmann_velocities", "lj_forces", "velocity_verlet_step"]
15
+
16
+
17
+ @njit(cache=True)
18
+ def lj_forces(positions, box_size, epsilon=1.0, sigma=1.0, cutoff=2.5):
19
+ """Pairwise Lennard-Jones forces and potential energy under minimum-image PBC.
20
+
21
+ Parameters
22
+ ----------
23
+ positions : ndarray of shape (N, 2)
24
+ Particle positions, expected in ``[0, box_size)``.
25
+ box_size : float
26
+ Side length of the square periodic simulation box.
27
+ epsilon : float, default=1.0
28
+ Lennard-Jones well depth.
29
+ sigma : float, default=1.0
30
+ Lennard-Jones length scale (zero-crossing distance).
31
+ cutoff : float, default=2.5
32
+ Interaction cutoff radius, in the same length units as ``sigma``.
33
+
34
+ Returns
35
+ -------
36
+ forces : ndarray of shape (N, 2)
37
+ Net force on each particle.
38
+ potential_energy : float
39
+ Total (uncut-shifted) Lennard-Jones potential energy of the
40
+ configuration.
41
+
42
+ Notes
43
+ -----
44
+ The Lennard-Jones potential is
45
+ :math:`V(r) = 4\\epsilon\\left[(\\sigma/r)^{12} - (\\sigma/r)^{6}\\right]`,
46
+ giving the force magnitude
47
+ :math:`f(r) = 24\\epsilon\\left[2(\\sigma/r)^{12} - (\\sigma/r)^{6}\\right] / r`.
48
+ """
49
+ n = positions.shape[0]
50
+ forces = np.zeros((n, 2), dtype=np.float64)
51
+ potential_energy = 0.0
52
+ cutoff2 = cutoff * cutoff
53
+ sigma2 = sigma * sigma
54
+ for a in range(n):
55
+ xa = positions[a, 0]
56
+ ya = positions[a, 1]
57
+ for b in range(a + 1, n):
58
+ dx = xa - positions[b, 0]
59
+ dy = ya - positions[b, 1]
60
+ dx -= box_size * np.round(dx / box_size)
61
+ dy -= box_size * np.round(dy / box_size)
62
+ r2 = dx * dx + dy * dy
63
+ if 1e-12 < r2 < cutoff2:
64
+ inv_r2 = sigma2 / r2
65
+ inv_r6 = inv_r2 * inv_r2 * inv_r2
66
+ inv_r12 = inv_r6 * inv_r6
67
+ f_over_r2 = 24.0 * epsilon * (2.0 * inv_r12 - inv_r6) / r2
68
+ fx = f_over_r2 * dx
69
+ fy = f_over_r2 * dy
70
+ forces[a, 0] += fx
71
+ forces[a, 1] += fy
72
+ forces[b, 0] -= fx
73
+ forces[b, 1] -= fy
74
+ potential_energy += 4.0 * epsilon * (inv_r12 - inv_r6)
75
+ return forces, potential_energy
76
+
77
+
78
+ def velocity_verlet_step(positions, velocities, forces, dt, box_size, mass=1.0, **lj_kwargs):
79
+ """Advance positions and velocities by one Velocity Verlet step.
80
+
81
+ Parameters
82
+ ----------
83
+ positions : ndarray of shape (N, 2)
84
+ Current positions. Not modified; a new array is returned.
85
+ velocities : ndarray of shape (N, 2)
86
+ Current velocities.
87
+ forces : ndarray of shape (N, 2)
88
+ Forces evaluated at the current positions (from the previous step's
89
+ call, so the force is only ever computed once per step).
90
+ dt : float
91
+ Integration time step.
92
+ box_size : float
93
+ Side length of the periodic simulation box.
94
+ mass : float, default=1.0
95
+ Common particle mass.
96
+ **lj_kwargs
97
+ Extra keyword arguments (``epsilon``, ``sigma``, ``cutoff``) forwarded
98
+ to :func:`lj_forces`.
99
+
100
+ Returns
101
+ -------
102
+ new_positions : ndarray of shape (N, 2)
103
+ Positions after one step, wrapped into ``[0, box_size)``.
104
+ new_velocities : ndarray of shape (N, 2)
105
+ Velocities after one step.
106
+ new_forces : ndarray of shape (N, 2)
107
+ Forces evaluated at ``new_positions``, ready for the next call.
108
+ potential_energy : float
109
+ Potential energy at ``new_positions``.
110
+ """
111
+ new_positions = positions + velocities * dt + 0.5 * (forces / mass) * dt * dt
112
+ new_positions = np.mod(new_positions, box_size)
113
+ new_forces, potential_energy = lj_forces(new_positions, box_size, **lj_kwargs)
114
+ new_velocities = velocities + 0.5 * (forces + new_forces) / mass * dt
115
+ return new_positions, new_velocities, new_forces, potential_energy
116
+
117
+
118
+ def initialize_maxwell_boltzmann_velocities(n_particles, temperature, mass=1.0, kB=1.0, rng=None):
119
+ """Draw initial 2D velocities from the Maxwell-Boltzmann distribution and remove drift.
120
+
121
+ Each velocity component is drawn i.i.d. from
122
+ :math:`\\mathcal{N}(0, k_B T / m)`, then the center-of-mass velocity is
123
+ subtracted so the total momentum is zero.
124
+
125
+ Parameters
126
+ ----------
127
+ n_particles : int
128
+ Number of particles.
129
+ temperature : float
130
+ Target temperature.
131
+ mass : float, default=1.0
132
+ Particle mass.
133
+ kB : float, default=1.0
134
+ Boltzmann constant, in whatever unit system is being used.
135
+ rng : numpy.random.Generator, optional
136
+ Random number generator. A fresh default generator is created if not
137
+ given.
138
+
139
+ Returns
140
+ -------
141
+ ndarray of shape (n_particles, 2)
142
+ Initial velocities with zero net momentum.
143
+
144
+ Examples
145
+ --------
146
+ >>> v = initialize_maxwell_boltzmann_velocities(100, temperature=1.5, rng=np.random.default_rng(0))
147
+ >>> v.shape
148
+ (100, 2)
149
+ >>> np.allclose(v.mean(axis=0), 0.0)
150
+ True
151
+ """
152
+ if rng is None:
153
+ rng = np.random.default_rng()
154
+ std = np.sqrt(kB * temperature / mass)
155
+ velocities = rng.normal(loc=0.0, scale=std, size=(n_particles, 2))
156
+ velocities -= velocities.mean(axis=0, keepdims=True)
157
+ return velocities