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,445 @@
1
+ """Generic tight-binding lattice and Bloch Hamiltonian construction.
2
+
3
+ This module provides the building blocks that :mod:`physicskit.condensed.models`
4
+ uses to assemble specific band models (graphene, the Haldane model, ...):
5
+ a :class:`Lattice` describing the Bravais lattice and orbital basis, and a
6
+ :class:`Hamiltonian` that accumulates real-space hoppings and Bloch-sums them
7
+ into :math:`H(\\mathbf{k})`.
8
+
9
+ Convention
10
+ ----------
11
+ Bloch Hamiltonians in this package use the **periodic gauge**: a hopping
12
+ term with integer cell offset :math:`\\mathbf{R} = (n_1, n_2, \\dots)`
13
+ (expressed in units of the primitive lattice vectors) contributes a phase
14
+ :math:`e^{i \\mathbf{k} \\cdot \\mathbf{R}}` where :math:`\\mathbf{k}` is the
15
+ *reduced* crystal momentum conjugate to the primitive-vector indices, each
16
+ component periodic on :math:`[0, 2\\pi)`. This intracell-position-free
17
+ convention keeps :math:`H(\\mathbf{k})` manifestly periodic on the Brillouin
18
+ zone torus, which is exactly what the Fukui-Hatsugai-Suzuki Chern-number
19
+ algorithm in :mod:`physicskit.condensed.topology` needs.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import itertools
25
+ from dataclasses import dataclass, field
26
+
27
+ import numpy as np
28
+
29
+ __all__ = ["Lattice", "Hamiltonian", "build_ribbon", "build_finite_cluster", "apply_peierls_phase"]
30
+
31
+
32
+ @dataclass
33
+ class Lattice:
34
+ """A Bravais lattice with a basis of orbitals.
35
+
36
+ Parameters
37
+ ----------
38
+ lattice_vectors : array_like, shape (dim, dim)
39
+ Primitive lattice vectors as rows, in Cartesian coordinates.
40
+ orbitals : array_like, shape (n_orbitals, dim)
41
+ Orbital positions in fractional coordinates of the primitive cell.
42
+ labels : list of str, optional
43
+ Human-readable names for each orbital (defaults to ``orb0``, ``orb1``, ...).
44
+
45
+ Examples
46
+ --------
47
+ >>> lat = Lattice.honeycomb()
48
+ >>> lat.n_orbitals
49
+ 2
50
+ >>> lat.dim
51
+ 2
52
+ """
53
+
54
+ lattice_vectors: np.ndarray
55
+ orbitals: np.ndarray
56
+ labels: list = field(default_factory=list)
57
+
58
+ def __post_init__(self):
59
+ self.lattice_vectors = np.atleast_2d(np.asarray(self.lattice_vectors, dtype=float))
60
+ self.orbitals = np.atleast_2d(np.asarray(self.orbitals, dtype=float))
61
+ if not self.labels:
62
+ self.labels = [f"orb{i}" for i in range(len(self.orbitals))]
63
+
64
+ @property
65
+ def dim(self) -> int:
66
+ """int: Spatial dimension (1, 2, or 3)."""
67
+ return self.lattice_vectors.shape[0]
68
+
69
+ @property
70
+ def n_orbitals(self) -> int:
71
+ """int: Number of orbitals per unit cell."""
72
+ return self.orbitals.shape[0]
73
+
74
+ def cartesian_orbitals(self) -> np.ndarray:
75
+ """Return orbital positions in Cartesian coordinates.
76
+
77
+ Returns
78
+ -------
79
+ ndarray, shape (n_orbitals, dim)
80
+
81
+ Examples
82
+ --------
83
+ >>> lat = Lattice.square()
84
+ >>> lat.cartesian_orbitals()
85
+ array([[0., 0.]])
86
+ """
87
+ return self.orbitals @ self.lattice_vectors
88
+
89
+ def reciprocal_vectors(self) -> np.ndarray:
90
+ """Return primitive reciprocal lattice vectors :math:`\\mathbf{b}_i`.
91
+
92
+ Satisfies :math:`\\mathbf{a}_i \\cdot \\mathbf{b}_j = 2\\pi\\delta_{ij}`.
93
+
94
+ Returns
95
+ -------
96
+ ndarray, shape (dim, dim)
97
+
98
+ Examples
99
+ --------
100
+ >>> lat = Lattice.square(a=1.0)
101
+ >>> np.allclose(lat.reciprocal_vectors(), 2 * np.pi * np.eye(2))
102
+ True
103
+ """
104
+ return 2 * np.pi * np.linalg.inv(self.lattice_vectors).T
105
+
106
+ # -- Common lattice factories -----------------------------------------
107
+
108
+ @classmethod
109
+ def chain(cls, a: float = 1.0) -> Lattice:
110
+ """1D monatomic chain with lattice constant ``a``."""
111
+ return cls(lattice_vectors=[[a]], orbitals=[[0.0]])
112
+
113
+ @classmethod
114
+ def square(cls, a: float = 1.0) -> Lattice:
115
+ """2D square lattice, one orbital per cell."""
116
+ return cls(lattice_vectors=[[a, 0.0], [0.0, a]], orbitals=[[0.0, 0.0]])
117
+
118
+ @classmethod
119
+ def triangular(cls, a: float = 1.0) -> Lattice:
120
+ """2D triangular lattice, one orbital per cell."""
121
+ return cls(lattice_vectors=[[a, 0.0], [a / 2, a * np.sqrt(3) / 2]], orbitals=[[0.0, 0.0]])
122
+
123
+ @classmethod
124
+ def honeycomb(cls, a: float = 1.0) -> Lattice:
125
+ """2D honeycomb lattice (graphene structure), sublattices A and B.
126
+
127
+ ``a`` is the lattice constant (nearest-neighbor bond length is ``a/sqrt(3)``).
128
+ """
129
+ return cls(
130
+ lattice_vectors=[[a, 0.0], [a / 2, a * np.sqrt(3) / 2]],
131
+ orbitals=[[1 / 3, 1 / 3], [2 / 3, 2 / 3]],
132
+ labels=["A", "B"],
133
+ )
134
+
135
+ @classmethod
136
+ def kagome(cls, a: float = 1.0) -> Lattice:
137
+ """2D kagome lattice, three orbitals per cell (edge midpoints of a triangular lattice)."""
138
+ return cls(
139
+ lattice_vectors=[[a, 0.0], [a / 2, a * np.sqrt(3) / 2]],
140
+ orbitals=[[0.5, 0.0], [0.0, 0.5], [0.5, 0.5]],
141
+ labels=["A", "B", "C"],
142
+ )
143
+
144
+ @classmethod
145
+ def cubic(cls, a: float = 1.0) -> Lattice:
146
+ """3D simple cubic lattice, one orbital per cell."""
147
+ return cls(lattice_vectors=[[a, 0, 0], [0, a, 0], [0, 0, a]], orbitals=[[0.0, 0.0, 0.0]])
148
+
149
+
150
+ class Hamiltonian:
151
+ """Real-space tight-binding Hamiltonian, Bloch-summed into :math:`H(\\mathbf{k})`.
152
+
153
+ Parameters
154
+ ----------
155
+ lattice : Lattice
156
+ The underlying Bravais lattice and orbital basis.
157
+ onsite : array_like, shape (n_orbitals,), optional
158
+ Onsite energies. Defaults to zero for every orbital.
159
+
160
+ Examples
161
+ --------
162
+ Nearest-neighbor graphene, reproducing the linear Dirac dispersion:
163
+
164
+ >>> import numpy as np
165
+ >>> lat = Lattice.honeycomb()
166
+ >>> H = Hamiltonian(lat)
167
+ >>> t = 1.0
168
+ >>> H.add_hopping(0, 1, (0, 0), t)
169
+ >>> H.add_hopping(0, 1, (-1, 0), t)
170
+ >>> H.add_hopping(0, 1, (0, -1), t)
171
+ >>> K = np.array([2 * np.pi / 3, 4 * np.pi / 3])
172
+ >>> np.round(np.linalg.eigvalsh(H.bloch(K)), 8)
173
+ array([-0., 0.])
174
+ """
175
+
176
+ def __init__(self, lattice: Lattice, onsite=None):
177
+ self.lattice = lattice
178
+ n = lattice.n_orbitals
179
+ self.onsite = np.zeros(n) if onsite is None else np.asarray(onsite, dtype=float)
180
+ self._hoppings: list[tuple[int, int, tuple, complex]] = []
181
+
182
+ def add_hopping(self, i: int, j: int, cell_offset, amplitude: complex) -> None:
183
+ """Add a hopping term :math:`t\\, c_i^\\dagger(0) c_j(\\mathbf{R})` (+ h.c.).
184
+
185
+ Parameters
186
+ ----------
187
+ i, j : int
188
+ Orbital indices within the unit cell.
189
+ cell_offset : tuple of int
190
+ Integer offset :math:`\\mathbf{R}` (in primitive-vector units) of
191
+ orbital ``j``'s cell relative to orbital ``i``'s cell.
192
+ amplitude : complex
193
+ Hopping amplitude. The Hermitian conjugate term is added
194
+ automatically; do not add both a bond and its reverse.
195
+
196
+ Raises
197
+ ------
198
+ ValueError
199
+ If ``(i, j, cell_offset)`` describes a diagonal onsite term
200
+ (``i == j`` and ``cell_offset`` all zero); use ``onsite`` instead.
201
+ """
202
+ cell_offset = tuple(int(x) for x in cell_offset)
203
+ if i == j and all(x == 0 for x in cell_offset):
204
+ raise ValueError("Use the `onsite` array for i == j, R == 0 terms.")
205
+ self._hoppings.append((i, j, cell_offset, complex(amplitude)))
206
+
207
+ def bloch(self, k) -> np.ndarray:
208
+ """Evaluate the Bloch Hamiltonian at reduced crystal momentum ``k``.
209
+
210
+ Parameters
211
+ ----------
212
+ k : array_like, shape (dim,)
213
+ Reduced crystal momentum, each component periodic on :math:`[0, 2\\pi)`.
214
+
215
+ Returns
216
+ -------
217
+ ndarray, shape (n_orbitals, n_orbitals)
218
+ Hermitian Bloch Hamiltonian matrix.
219
+ """
220
+ k = np.asarray(k, dtype=float)
221
+ H = np.diag(self.onsite).astype(complex)
222
+ for i, j, R, amp in self._hoppings:
223
+ phase = np.exp(1j * np.dot(k, R))
224
+ H[i, j] += amp * phase
225
+ H[j, i] += np.conj(amp * phase)
226
+ return H
227
+
228
+ def bands(self, k) -> np.ndarray:
229
+ """Eigenvalues of :meth:`bloch` at ``k``, sorted ascending.
230
+
231
+ Examples
232
+ --------
233
+ >>> lat = Lattice.chain()
234
+ >>> H = Hamiltonian(lat)
235
+ >>> H.add_hopping(0, 0, (1,), 1.0)
236
+ >>> import numpy as np
237
+ >>> np.round(H.bands([np.pi]), 8)
238
+ array([-2.])
239
+ """
240
+ return np.linalg.eigvalsh(self.bloch(k))
241
+
242
+
243
+ def build_ribbon(hamiltonian: Hamiltonian, open_direction: int, n_cells: int):
244
+ """Build a ribbon/slab: periodic in-plane, open (finite) along ``open_direction``.
245
+
246
+ Truncates the periodic boundary condition along one primitive-lattice
247
+ direction, producing a quasi-1D (2D lattice) or quasi-2D (3D lattice)
248
+ strip Hamiltonian as a function of the remaining reduced momenta. This
249
+ exposes edge/surface states localized at the two open boundaries.
250
+
251
+ Parameters
252
+ ----------
253
+ hamiltonian : Hamiltonian
254
+ A Hamiltonian built on a 2D (or higher) :class:`Lattice`.
255
+ open_direction : int
256
+ Index of the primitive-lattice direction to truncate.
257
+ n_cells : int
258
+ Number of unit cells stacked along ``open_direction``.
259
+
260
+ Returns
261
+ -------
262
+ callable
263
+ A function ``H_ribbon(k_parallel)`` returning the
264
+ ``(n_cells * n_orbitals, n_cells * n_orbitals)`` ribbon Hamiltonian,
265
+ where ``k_parallel`` is a reduced-momentum vector with one fewer
266
+ component than the bulk lattice (the remaining periodic directions).
267
+
268
+ Examples
269
+ --------
270
+ SSH chain cut open into a finite 20-site wire; the topological phase
271
+ (``v < w``) hosts a mid-gap zero mode:
272
+
273
+ >>> import numpy as np
274
+ >>> from physicskit.condensed.models import ssh_lattice_hamiltonian
275
+ >>> H = ssh_lattice_hamiltonian(v=0.5, w=1.0)
276
+ >>> H_wire = build_ribbon(H, open_direction=0, n_cells=30)
277
+ >>> spectrum = np.linalg.eigvalsh(H_wire(np.array([])))
278
+ >>> bool(np.any(np.abs(spectrum) < 1e-6))
279
+ True
280
+ """
281
+ lat = hamiltonian.lattice
282
+ norb = lat.n_orbitals
283
+ dim = lat.dim
284
+ parallel_dirs = [d for d in range(dim) if d != open_direction]
285
+
286
+ def H_ribbon(k_parallel):
287
+ k_parallel = np.atleast_1d(np.asarray(k_parallel, dtype=float))
288
+ N = n_cells * norb
289
+ H = np.zeros((N, N), dtype=complex)
290
+ for c in range(n_cells):
291
+ for orb in range(norb):
292
+ H[c * norb + orb, c * norb + orb] = hamiltonian.onsite[orb]
293
+ for i, j, R, amp in hamiltonian._hoppings:
294
+ n_open = R[open_direction]
295
+ k_perp = np.array([R[d] for d in parallel_dirs], dtype=float)
296
+ phase = np.exp(1j * np.dot(k_parallel, k_perp)) if parallel_dirs else 1.0 + 0j
297
+ for c in range(n_cells):
298
+ c2 = c + n_open
299
+ if 0 <= c2 < n_cells:
300
+ H[c * norb + i, c2 * norb + j] += amp * phase
301
+ H[c2 * norb + j, c * norb + i] += np.conj(amp * phase)
302
+ return H
303
+
304
+ return H_ribbon
305
+
306
+
307
+ def build_finite_cluster(hamiltonian: Hamiltonian, n_cells, keep=None):
308
+ """Build a fully finite (open in every direction) real-space cluster.
309
+
310
+ Unlike :func:`build_ribbon`, which stays periodic along all but one
311
+ lattice direction, this truncates *every* direction, producing a
312
+ genuinely finite flake with real Cartesian site positions -- what a
313
+ boundary-sensitive real-space plot (e.g.
314
+ :func:`~physicskit.condensed.visualizers.plot_lattice_structure`) needs.
315
+
316
+ Parameters
317
+ ----------
318
+ hamiltonian : Hamiltonian
319
+ A Hamiltonian built on a :class:`Lattice` of any dimension.
320
+ n_cells : int or sequence of int
321
+ Number of unit cells spanned along each lattice direction (the
322
+ bounding-box shape). A single int is broadcast to every direction.
323
+ keep : callable, optional
324
+ ``keep(cell, orbital, position) -> bool`` predicate selecting which
325
+ sites within the bounding box survive, for carving non-rectangular
326
+ shapes (e.g. a disk) out of it. ``cell`` is the integer cell-index
327
+ tuple, ``orbital`` the orbital index within the cell, and
328
+ ``position`` its Cartesian coordinate. Defaults to keeping every
329
+ site in the bounding box.
330
+
331
+ Returns
332
+ -------
333
+ H : ndarray, shape (n_sites, n_sites)
334
+ Dense, open-boundary real-space Hamiltonian.
335
+ positions : ndarray, shape (n_sites, dim)
336
+ Cartesian coordinates of the surviving sites, in the same order as
337
+ ``H``'s rows/columns.
338
+ bonds : list of tuple(int, int, complex)
339
+ Surviving real-space hoppings ``(i, j, amplitude)``, indexing into
340
+ ``positions``/``H``.
341
+
342
+ Examples
343
+ --------
344
+ A 6-site open SSH chain (3 unit cells of 2 orbitals each) has exactly
345
+ 5 nearest-neighbor bonds, one fewer than a periodic ring would:
346
+
347
+ >>> import numpy as np
348
+ >>> from physicskit.condensed.models import ssh_lattice_hamiltonian
349
+ >>> H_bulk = ssh_lattice_hamiltonian(v=0.5, w=1.0)
350
+ >>> H, positions, bonds = build_finite_cluster(H_bulk, n_cells=3)
351
+ >>> H.shape
352
+ (6, 6)
353
+ >>> len(bonds)
354
+ 5
355
+ >>> positions.shape
356
+ (6, 1)
357
+ """
358
+ lat = hamiltonian.lattice
359
+ norb = lat.n_orbitals
360
+ dim = lat.dim
361
+
362
+ n_cells = np.atleast_1d(np.asarray(n_cells, dtype=int))
363
+ if n_cells.size == 1 and dim > 1:
364
+ n_cells = np.full(dim, n_cells[0])
365
+ cell_ranges = [range(int(n)) for n in n_cells]
366
+
367
+ index_map: dict[tuple, int] = {}
368
+ positions_list = []
369
+ for cell in itertools.product(*cell_ranges):
370
+ for orb in range(norb):
371
+ pos = (np.array(cell, dtype=float) + lat.orbitals[orb]) @ lat.lattice_vectors
372
+ if keep is not None and not keep(cell, orb, pos):
373
+ continue
374
+ index_map[(cell, orb)] = len(positions_list)
375
+ positions_list.append(pos)
376
+ positions = np.array(positions_list)
377
+
378
+ n_sites = len(positions_list)
379
+ H = np.zeros((n_sites, n_sites), dtype=complex)
380
+ for (_cell, orb), idx in index_map.items():
381
+ H[idx, idx] = hamiltonian.onsite[orb]
382
+
383
+ bonds: list[tuple[int, int, complex]] = []
384
+ for i, j, R, amp in hamiltonian._hoppings:
385
+ for cell in itertools.product(*cell_ranges):
386
+ key_i = (cell, i)
387
+ if key_i not in index_map:
388
+ continue
389
+ cell2 = tuple(c + r for c, r in zip(cell, R, strict=True))
390
+ key_j = (cell2, j)
391
+ if key_j not in index_map:
392
+ continue
393
+ idx_i, idx_j = index_map[key_i], index_map[key_j]
394
+ H[idx_i, idx_j] += amp
395
+ H[idx_j, idx_i] += np.conj(amp)
396
+ bonds.append((idx_i, idx_j, amp))
397
+
398
+ return H, positions, bonds
399
+
400
+
401
+ def apply_peierls_phase(positions: np.ndarray, hoppings, flux_quanta_per_plaquette: float, area_per_plaquette: float):
402
+ """Apply a Peierls substitution phase to real-space hoppings for a uniform magnetic field.
403
+
404
+ In the Landau gauge :math:`\\mathbf{A} = (-By, 0)`, a hopping from site
405
+ at ``r_i`` to site at ``r_j`` acquires the phase
406
+ :math:`\\exp\\!\\big(i\\frac{2\\pi\\Phi}{\\Phi_0}\\,\\bar{y}\\,(x_j-x_i)/a^2\\big)`
407
+ where :math:`\\Phi/\\Phi_0` is the flux per plaquette in units of the flux
408
+ quantum, evaluated at the bond midpoint :math:`\\bar y`.
409
+
410
+ Parameters
411
+ ----------
412
+ positions : ndarray, shape (n_sites, 2)
413
+ Real-space Cartesian coordinates of every site in a finite lattice.
414
+ hoppings : list of tuple(int, int, complex)
415
+ ``(i, j, amplitude)`` real-space bonds (indices into ``positions``).
416
+ flux_quanta_per_plaquette : float
417
+ Magnetic flux per unit-cell plaquette, in units of the flux quantum
418
+ :math:`\\Phi_0 = h/e`.
419
+ area_per_plaquette : float
420
+ Real-space area of one plaquette, used to convert flux density to
421
+ the vector potential prefactor.
422
+
423
+ Returns
424
+ -------
425
+ list of tuple(int, int, complex)
426
+ The same bonds with Peierls phases multiplied into the amplitude.
427
+
428
+ Examples
429
+ --------
430
+ >>> import numpy as np
431
+ >>> positions = np.array([[0.0, 0.0], [1.0, 0.0]])
432
+ >>> bonds = [(0, 1, 1.0)]
433
+ >>> out = apply_peierls_phase(positions, bonds, flux_quanta_per_plaquette=0.25, area_per_plaquette=1.0)
434
+ >>> bool(abs(out[0][2] - 1.0) < 1e-12)
435
+ True
436
+ """
437
+ positions = np.asarray(positions, dtype=float)
438
+ B_eff = 2 * np.pi * flux_quanta_per_plaquette / area_per_plaquette
439
+ out = []
440
+ for i, j, amp in hoppings:
441
+ y_mid = 0.5 * (positions[i, 1] + positions[j, 1])
442
+ dx = positions[j, 0] - positions[i, 0]
443
+ phase = np.exp(1j * B_eff * y_mid * dx)
444
+ out.append((i, j, amp * phase))
445
+ return out
@@ -0,0 +1,178 @@
1
+ r"""The 3D strong topological insulator: from theory (2007) to Bi2Se3/Bi2Te3 (2008-2009).
2
+
3
+ Fu, Kane, and Mele extended the 2D :math:`\mathbb{Z}_2` classification of
4
+ :mod:`physicskit.condensed.models` (``kane_mele_hamiltonian``,
5
+ ``bhz_hamiltonian``) to three dimensions, predicting a "strong" topological
6
+ insulator: a bulk band insulator whose *every* surface, regardless of
7
+ orientation, hosts a single, gapless, spin-momentum-locked Dirac cone
8
+ protected by time-reversal symmetry alone. Hasan and Cava's groups and
9
+ collaborators confirmed this directly in 2008-2009 by ARPES on
10
+ Bi\ :sub:`2`\ Se\ :sub:`3` and Bi\ :sub:`2`\ Te\ :sub:`3`, resolving exactly
11
+ one Dirac cone at the surface Brillouin zone center -- the 3D generalization
12
+ of the helical edge states Konig et al. had just observed at the 1D edge of
13
+ a 2D quantum spin Hall system.
14
+
15
+ This module implements the minimal 4-band lattice model with this physics
16
+ (Qi & Zhang, Rev. Mod. Phys. 83, 1057 (2011)):
17
+
18
+ .. math::
19
+
20
+ H(\mathbf{k}) = \sin k_x\,\Gamma_1 + \sin k_y\,\Gamma_2 + \sin k_z\,\Gamma_3
21
+ + \left(m + t\sum_{i=x,y,z}\cos k_i\right)\Gamma_0,
22
+
23
+ built from mutually anticommuting 4x4 Dirac matrices
24
+ :math:`\Gamma_0=\tau_z\otimes\sigma_0`, :math:`\Gamma_{1,2,3}=\tau_x\otimes\sigma_{x,y,z}`
25
+ (:math:`\tau` an orbital pseudospin, :math:`\sigma` the physical electron
26
+ spin) -- a cubic-lattice generalization of the BHZ model whose bulk gap
27
+ closes, and topological character changes, at every time-reversal-invariant
28
+ momentum where the mass term vanishes, :math:`m/t \in \{-3, -1, 1, 3\}`. Of
29
+ the resulting windows, :math:`1 < |m/t| < 3` is a strong topological
30
+ insulator (an open slab hosts a single, gapless surface Dirac cone at
31
+ :math:`\bar\Gamma=(0,0)` on each of its two open surfaces); :math:`|m/t| <
32
+ 1` and :math:`|m/t| > 3` are trivial.
33
+
34
+ Uses the same natural-unit convention (:math:`\hbar=e=1`) as the rest of
35
+ :mod:`physicskit.condensed`.
36
+ """
37
+
38
+ from __future__ import annotations
39
+
40
+ import numpy as np
41
+
42
+ __all__ = ["topological_insulator_3d_hamiltonian", "topological_insulator_3d_slab_hamiltonian", "surface_dirac_hamiltonian"]
43
+
44
+ _sigma_0 = np.eye(2, dtype=complex)
45
+ _sigma_x = np.array([[0, 1], [1, 0]], dtype=complex)
46
+ _sigma_y = np.array([[0, -1j], [1j, 0]], dtype=complex)
47
+ _sigma_z = np.array([[1, 0], [0, -1]], dtype=complex)
48
+ _tau_x = _sigma_x
49
+ _tau_z = _sigma_z
50
+
51
+ _GAMMA0 = np.kron(_tau_z, _sigma_0)
52
+ _GAMMA1 = np.kron(_tau_x, _sigma_x)
53
+ _GAMMA2 = np.kron(_tau_x, _sigma_y)
54
+ _GAMMA3 = np.kron(_tau_x, _sigma_z)
55
+
56
+
57
+ def topological_insulator_3d_hamiltonian(kx: float, ky: float, kz: float, m: float, t: float = 1.0) -> np.ndarray:
58
+ r"""Bloch Hamiltonian of the minimal cubic-lattice 3D topological insulator model.
59
+
60
+ Parameters
61
+ ----------
62
+ kx, ky, kz : float
63
+ Reduced crystal momenta, each periodic on :math:`[0, 2\pi)`.
64
+ m : float
65
+ Band mass. The model is a strong topological insulator for
66
+ :math:`1 < |m/t| < 3`, and trivial for :math:`|m/t| < 1` or
67
+ :math:`|m/t| > 3`.
68
+ t : float, default=1.0
69
+ Hopping amplitude setting the bulk bandwidth.
70
+
71
+ Returns
72
+ -------
73
+ ndarray, shape (4, 4)
74
+ Hermitian Bloch Hamiltonian.
75
+
76
+ Examples
77
+ --------
78
+ >>> import numpy as np
79
+ >>> H = topological_insulator_3d_hamiltonian(0.3, -0.7, 0.5, m=1.0)
80
+ >>> np.allclose(H, H.conj().T)
81
+ True
82
+ >>> H0 = topological_insulator_3d_hamiltonian(0.0, 0.0, 0.0, m=1.0, t=1.0)
83
+ >>> np.round(np.linalg.eigvalsh(H0), 8)
84
+ array([-4., -4., 4., 4.])
85
+ """
86
+ mass = m + t * (np.cos(kx) + np.cos(ky) + np.cos(kz))
87
+ return np.sin(kx) * _GAMMA1 + np.sin(ky) * _GAMMA2 + np.sin(kz) * _GAMMA3 + mass * _GAMMA0
88
+
89
+
90
+ def topological_insulator_3d_slab_hamiltonian(kx: float, ky: float, n_layers: int, m: float, t: float = 1.0) -> np.ndarray:
91
+ r"""Slab Hamiltonian: periodic in ``x``, ``y``, open (finite) along ``z``.
92
+
93
+ Truncating the ``z`` direction exposes the top and bottom (001)
94
+ surfaces. Diagonalizing at each ``(kx, ky)`` and looking for
95
+ mid-gap states localized at the outer layers reveals the surface
96
+ Dirac cone directly, with no separate topological-invariant
97
+ calculation needed.
98
+
99
+ Parameters
100
+ ----------
101
+ kx, ky : float
102
+ Reduced crystal momenta, periodic on :math:`[0, 2\pi)`.
103
+ n_layers : int
104
+ Number of atomic layers stacked along ``z``.
105
+ m : float
106
+ Band mass (see :func:`topological_insulator_3d_hamiltonian`).
107
+ t : float, default=1.0
108
+ Hopping amplitude.
109
+
110
+ Returns
111
+ -------
112
+ ndarray, shape (4 * n_layers, 4 * n_layers)
113
+ Hermitian, open-boundary slab Hamiltonian.
114
+
115
+ Examples
116
+ --------
117
+ In the strong-topological-insulator regime (:math:`1 < |m/t| < 3`), a
118
+ thick slab has a state pinned to exactly zero energy at the surface
119
+ Brillouin zone center, localized entirely on one outer layer -- the
120
+ surface Dirac point -- that a topologically trivial slab
121
+ (:math:`|m/t| < 1`) lacks:
122
+
123
+ >>> import numpy as np
124
+ >>> gap = np.linalg.eigvalsh(topological_insulator_3d_slab_hamiltonian(0.0, 0.0, n_layers=40, m=-2.0))
125
+ >>> bool(np.min(np.abs(gap)) < 1e-8)
126
+ True
127
+ >>> gap_trivial = np.linalg.eigvalsh(topological_insulator_3d_slab_hamiltonian(0.0, 0.0, n_layers=40, m=0.0))
128
+ >>> bool(np.min(np.abs(gap_trivial)) > 0.5)
129
+ True
130
+ """
131
+ mass_xy = m + t * (np.cos(kx) + np.cos(ky))
132
+ H0 = np.sin(kx) * _GAMMA1 + np.sin(ky) * _GAMMA2 + mass_xy * _GAMMA0
133
+ Tz = 0.5 * t * _GAMMA0 - 0.5j * _GAMMA3
134
+
135
+ N = n_layers
136
+ H = np.zeros((4 * N, 4 * N), dtype=complex)
137
+ for layer in range(N):
138
+ H[4 * layer : 4 * layer + 4, 4 * layer : 4 * layer + 4] = H0
139
+ for layer in range(N - 1):
140
+ H[4 * layer : 4 * layer + 4, 4 * (layer + 1) : 4 * (layer + 1) + 4] = Tz
141
+ H[4 * (layer + 1) : 4 * (layer + 1) + 4, 4 * layer : 4 * layer + 4] = Tz.conj().T
142
+ return H
143
+
144
+
145
+ def surface_dirac_hamiltonian(kx: float, ky: float, v_f: float = 1.0) -> np.ndarray:
146
+ r"""Low-energy effective Hamiltonian of a single topological-insulator surface Dirac cone.
147
+
148
+ .. math::
149
+
150
+ H_{\text{surf}}(\mathbf{k}) = \hbar v_F\left(k_x\sigma_y - k_y\sigma_x\right),
151
+
152
+ the massless, spin-momentum-locked Dirac fermion measured directly by
153
+ ARPES on the Bi\ :sub:`2`\ Se\ :sub:`3` and Bi\ :sub:`2`\ Te\ :sub:`3`
154
+ surfaces in 2008-2009: spin polarization locked perpendicular to
155
+ momentum, with no Kramers-degenerate partner at the same energy and
156
+ momentum (backscattering off nonmagnetic disorder is forbidden).
157
+
158
+ Parameters
159
+ ----------
160
+ kx, ky : float
161
+ Momentum measured from the surface Dirac point.
162
+ v_f : float, default=1.0
163
+ Surface Fermi velocity.
164
+
165
+ Returns
166
+ -------
167
+ ndarray, shape (2, 2)
168
+ Hermitian Hamiltonian with linear (Dirac) spectrum
169
+ :math:`E_\pm(\mathbf{k}) = \pm v_F|\mathbf{k}|`.
170
+
171
+ Examples
172
+ --------
173
+ >>> import numpy as np
174
+ >>> H = surface_dirac_hamiltonian(0.3, -0.4, v_f=2.0)
175
+ >>> np.round(np.linalg.eigvalsh(H), 8)
176
+ array([-1., 1.])
177
+ """
178
+ return v_f * (kx * _sigma_y - ky * _sigma_x)