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.
- physicskit/__init__.py +51 -0
- physicskit/astro/__init__.py +66 -0
- physicskit/astro/cosmic_web.py +395 -0
- physicskit/astro/galactic_dynamics.py +137 -0
- physicskit/astro/nbody.py +208 -0
- physicskit/astro/orbital_mechanics.py +220 -0
- physicskit/astro/stellar_dynamo.py +628 -0
- physicskit/astro/stellar_structure.py +198 -0
- physicskit/astro/tests/__init__.py +0 -0
- physicskit/astro/tests/conftest.py +7 -0
- physicskit/astro/tests/test_cosmic_web.py +159 -0
- physicskit/astro/tests/test_galactic_dynamics.py +46 -0
- physicskit/astro/tests/test_nbody.py +81 -0
- physicskit/astro/tests/test_orbital_mechanics.py +73 -0
- physicskit/astro/tests/test_stellar_dynamo.py +198 -0
- physicskit/astro/tests/test_stellar_structure.py +52 -0
- physicskit/astro/tests/test_visualizers.py +159 -0
- physicskit/astro/visualizers.py +628 -0
- physicskit/chaos/__init__.py +55 -0
- physicskit/chaos/core/__init__.py +3 -0
- physicskit/chaos/core/base_system.py +342 -0
- physicskit/chaos/core/integrators.py +40 -0
- physicskit/chaos/exceptions.py +24 -0
- physicskit/chaos/quantum/__init__.py +38 -0
- physicskit/chaos/quantum/billiards.py +274 -0
- physicskit/chaos/quantum/husimi.py +85 -0
- physicskit/chaos/quantum/maps.py +366 -0
- physicskit/chaos/systems/__init__.py +38 -0
- physicskit/chaos/systems/billiards.py +1131 -0
- physicskit/chaos/systems/continuous.py +1276 -0
- physicskit/chaos/systems/maps.py +557 -0
- physicskit/chaos/tests/__init__.py +0 -0
- physicskit/chaos/tests/test_basins.py +76 -0
- physicskit/chaos/tests/test_bifurcation.py +132 -0
- physicskit/chaos/tests/test_billiards.py +115 -0
- physicskit/chaos/tests/test_continuous.py +224 -0
- physicskit/chaos/tests/test_dimension.py +69 -0
- physicskit/chaos/tests/test_divergence.py +90 -0
- physicskit/chaos/tests/test_dynamic_plots.py +269 -0
- physicskit/chaos/tests/test_integrators.py +96 -0
- physicskit/chaos/tests/test_io.py +41 -0
- physicskit/chaos/tests/test_maps.py +110 -0
- physicskit/chaos/tests/test_metrics.py +115 -0
- physicskit/chaos/tests/test_phase_space.py +73 -0
- physicskit/chaos/tests/test_properties.py +116 -0
- physicskit/chaos/tests/test_quantum_billiards.py +94 -0
- physicskit/chaos/tests/test_quantum_maps.py +144 -0
- physicskit/chaos/tests/test_recurrence.py +51 -0
- physicskit/chaos/tests/test_repr_and_api_consistency.py +134 -0
- physicskit/chaos/tests/test_section.py +49 -0
- physicskit/chaos/tests/test_spectral.py +48 -0
- physicskit/chaos/tests/test_streamlit_app.py +45 -0
- physicskit/chaos/tests/test_timeseries.py +131 -0
- physicskit/chaos/tests/test_viewer3d.py +41 -0
- physicskit/chaos/utils/__init__.py +46 -0
- physicskit/chaos/utils/dimension.py +139 -0
- physicskit/chaos/utils/io.py +95 -0
- physicskit/chaos/utils/metrics.py +304 -0
- physicskit/chaos/utils/recurrence.py +122 -0
- physicskit/chaos/utils/spectral.py +69 -0
- physicskit/chaos/utils/timeseries.py +303 -0
- physicskit/chaos/visualizers/__init__.py +85 -0
- physicskit/chaos/visualizers/basins.py +185 -0
- physicskit/chaos/visualizers/bifurcation.py +273 -0
- physicskit/chaos/visualizers/divergence.py +374 -0
- physicskit/chaos/visualizers/dynamic_plots.py +1372 -0
- physicskit/chaos/visualizers/phase_space.py +133 -0
- physicskit/chaos/visualizers/quantum.py +299 -0
- physicskit/chaos/visualizers/recurrence.py +91 -0
- physicskit/chaos/visualizers/section.py +161 -0
- physicskit/chaos/visualizers/theme.py +31 -0
- physicskit/chaos/visualizers/viewer3d.py +82 -0
- physicskit/classical/__init__.py +55 -0
- physicskit/classical/core/__init__.py +17 -0
- physicskit/classical/core/base_system.py +510 -0
- physicskit/classical/core/integrators.py +397 -0
- physicskit/classical/systems/__init__.py +32 -0
- physicskit/classical/systems/chains.py +334 -0
- physicskit/classical/systems/hamiltonian.py +215 -0
- physicskit/classical/systems/lagrangian.py +308 -0
- physicskit/classical/systems/newtonian.py +536 -0
- physicskit/classical/systems/rotations.py +614 -0
- physicskit/classical/tests/__init__.py +0 -0
- physicskit/classical/tests/conftest.py +7 -0
- physicskit/classical/tests/test_base_system.py +113 -0
- physicskit/classical/tests/test_chains.py +84 -0
- physicskit/classical/tests/test_conservation.py +244 -0
- physicskit/classical/tests/test_conservation_utils.py +47 -0
- physicskit/classical/tests/test_hamiltonian.py +44 -0
- physicskit/classical/tests/test_integrators.py +123 -0
- physicskit/classical/tests/test_lagrangian.py +69 -0
- physicskit/classical/tests/test_newtonian.py +45 -0
- physicskit/classical/tests/test_rotations.py +160 -0
- physicskit/classical/tests/test_stepsize.py +149 -0
- physicskit/classical/tests/test_symbolic.py +125 -0
- physicskit/classical/tests/test_visualizers.py +172 -0
- physicskit/classical/utils/__init__.py +20 -0
- physicskit/classical/utils/conservation.py +126 -0
- physicskit/classical/utils/stepsize.py +187 -0
- physicskit/classical/utils/symbolic.py +235 -0
- physicskit/classical/visualizers/__init__.py +25 -0
- physicskit/classical/visualizers/animations.py +508 -0
- physicskit/classical/visualizers/interactive.py +113 -0
- physicskit/classical/visualizers/modal_analysis.py +97 -0
- physicskit/classical/visualizers/phase_space.py +214 -0
- physicskit/condensed/__init__.py +122 -0
- physicskit/condensed/anderson_localization.py +155 -0
- physicskit/condensed/correlated.py +284 -0
- physicskit/condensed/ginzburg_landau.py +220 -0
- physicskit/condensed/landau_levels.py +246 -0
- physicskit/condensed/laughlin.py +229 -0
- physicskit/condensed/models.py +627 -0
- physicskit/condensed/tests/__init__.py +0 -0
- physicskit/condensed/tests/test_condensed.py +518 -0
- physicskit/condensed/tests/test_visualizers.py +87 -0
- physicskit/condensed/tight_binding.py +445 -0
- physicskit/condensed/topological_insulator_3d.py +178 -0
- physicskit/condensed/topology.py +217 -0
- physicskit/condensed/visualizers.py +296 -0
- physicskit/condensed/weyl.py +180 -0
- physicskit/constants.py +184 -0
- physicskit/fields/__init__.py +111 -0
- physicskit/fields/electrodynamics.py +671 -0
- physicskit/fields/quantum_fields.py +510 -0
- physicskit/fields/solitons.py +527 -0
- physicskit/fields/tests/__init__.py +0 -0
- physicskit/fields/tests/conftest.py +7 -0
- physicskit/fields/tests/test_field_animations.py +154 -0
- physicskit/fields/tests/test_fields.py +439 -0
- physicskit/fields/tests/test_visualizers.py +101 -0
- physicskit/fields/visualizers.py +503 -0
- physicskit/fluids/__init__.py +134 -0
- physicskit/fluids/core/__init__.py +23 -0
- physicskit/fluids/core/grid.py +165 -0
- physicskit/fluids/core/timestepping.py +231 -0
- physicskit/fluids/exceptions.py +26 -0
- physicskit/fluids/systems/__init__.py +70 -0
- physicskit/fluids/systems/compressible_flow.py +281 -0
- physicskit/fluids/systems/instabilities.py +343 -0
- physicskit/fluids/systems/navier_stokes.py +221 -0
- physicskit/fluids/systems/potential_flow.py +440 -0
- physicskit/fluids/systems/viscous_flow.py +425 -0
- physicskit/fluids/systems/vortex_dynamics.py +304 -0
- physicskit/fluids/tests/__init__.py +0 -0
- physicskit/fluids/tests/conftest.py +7 -0
- physicskit/fluids/tests/test_compressible_flow.py +66 -0
- physicskit/fluids/tests/test_instabilities.py +115 -0
- physicskit/fluids/tests/test_navier_stokes.py +67 -0
- physicskit/fluids/tests/test_potential_flow.py +92 -0
- physicskit/fluids/tests/test_static_visualizers.py +91 -0
- physicskit/fluids/tests/test_utils.py +100 -0
- physicskit/fluids/tests/test_viscous_flow.py +110 -0
- physicskit/fluids/tests/test_visualizers.py +34 -0
- physicskit/fluids/tests/test_vortex_dynamics.py +88 -0
- physicskit/fluids/utils/__init__.py +18 -0
- physicskit/fluids/utils/dimensionless.py +239 -0
- physicskit/fluids/utils/spectral_analysis.py +142 -0
- physicskit/fluids/visualizers/__init__.py +14 -0
- physicskit/fluids/visualizers/compressible.py +39 -0
- physicskit/fluids/visualizers/flow_fields.py +252 -0
- physicskit/fluids/visualizers/potential_flow.py +51 -0
- physicskit/fluids/visualizers/spectra.py +62 -0
- physicskit/fluids/visualizers/theme.py +38 -0
- physicskit/integrators/__init__.py +52 -0
- physicskit/integrators/adaptive.py +199 -0
- physicskit/integrators/fixed_step.py +360 -0
- physicskit/integrators/tests/__init__.py +0 -0
- physicskit/integrators/tests/test_integrators.py +101 -0
- physicskit/optics/__init__.py +124 -0
- physicskit/optics/_compat.py +5 -0
- physicskit/optics/gaussian.py +382 -0
- physicskit/optics/quantum_optics.py +428 -0
- physicskit/optics/ray.py +469 -0
- physicskit/optics/tests/__init__.py +0 -0
- physicskit/optics/tests/test_diffraction_animation.py +38 -0
- physicskit/optics/tests/test_gaussian.py +170 -0
- physicskit/optics/tests/test_quantum_optics.py +147 -0
- physicskit/optics/tests/test_ray.py +177 -0
- physicskit/optics/tests/test_visualizers.py +58 -0
- physicskit/optics/tests/test_wave.py +146 -0
- physicskit/optics/visualizers.py +264 -0
- physicskit/optics/wave.py +365 -0
- physicskit/particle/__init__.py +152 -0
- physicskit/particle/collider.py +382 -0
- physicskit/particle/confinement.py +125 -0
- physicskit/particle/decays.py +357 -0
- physicskit/particle/electroweak.py +300 -0
- physicskit/particle/kinematics.py +271 -0
- physicskit/particle/neutrinos.py +84 -0
- physicskit/particle/nuclear.py +100 -0
- physicskit/particle/scattering.py +159 -0
- physicskit/particle/tests/__init__.py +0 -0
- physicskit/particle/tests/conftest.py +7 -0
- physicskit/particle/tests/test_collider.py +119 -0
- physicskit/particle/tests/test_confinement.py +42 -0
- physicskit/particle/tests/test_decays.py +112 -0
- physicskit/particle/tests/test_electroweak.py +97 -0
- physicskit/particle/tests/test_kinematics.py +138 -0
- physicskit/particle/tests/test_neutrinos.py +36 -0
- physicskit/particle/tests/test_nuclear.py +45 -0
- physicskit/particle/tests/test_scattering.py +64 -0
- physicskit/particle/tests/test_visualizers.py +214 -0
- physicskit/particle/visualizers/__init__.py +38 -0
- physicskit/particle/visualizers/animations.py +705 -0
- physicskit/particle/visualizers/static.py +101 -0
- physicskit/plasma/__init__.py +176 -0
- physicskit/plasma/acceleration.py +152 -0
- physicskit/plasma/instabilities.py +417 -0
- physicskit/plasma/kinetic.py +588 -0
- physicskit/plasma/mhd.py +463 -0
- physicskit/plasma/single_particle.py +562 -0
- physicskit/plasma/tests/__init__.py +0 -0
- physicskit/plasma/tests/conftest.py +7 -0
- physicskit/plasma/tests/test_new_time_domain_features.py +222 -0
- physicskit/plasma/tests/test_plasma.py +232 -0
- physicskit/plasma/tests/test_visualizers.py +79 -0
- physicskit/plasma/turbulence.py +219 -0
- physicskit/plasma/visualizers.py +868 -0
- physicskit/plasma/waves.py +549 -0
- physicskit/quantum/__init__.py +180 -0
- physicskit/quantum/_compat.py +20 -0
- physicskit/quantum/chapters/__init__.py +0 -0
- physicskit/quantum/chapters/entanglement.py +489 -0
- physicskit/quantum/chapters/harmonic_spin.py +517 -0
- physicskit/quantum/chapters/hydrogen_am.py +292 -0
- physicskit/quantum/chapters/perturbation.py +350 -0
- physicskit/quantum/chapters/potentials.py +997 -0
- physicskit/quantum/chapters/spin.py +306 -0
- physicskit/quantum/chapters/wave_packets.py +541 -0
- physicskit/quantum/core/__init__.py +0 -0
- physicskit/quantum/core/eigensolvers.py +311 -0
- physicskit/quantum/core/operators.py +296 -0
- physicskit/quantum/core/solvers.py +271 -0
- physicskit/quantum/tests/__init__.py +0 -0
- physicskit/quantum/tests/conftest.py +7 -0
- physicskit/quantum/tests/test_animations.py +225 -0
- physicskit/quantum/tests/test_compat.py +43 -0
- physicskit/quantum/tests/test_eigensolvers.py +24 -0
- physicskit/quantum/tests/test_entanglement.py +127 -0
- physicskit/quantum/tests/test_harmonic_spin.py +140 -0
- physicskit/quantum/tests/test_hydrogen_am.py +48 -0
- physicskit/quantum/tests/test_measure.py +110 -0
- physicskit/quantum/tests/test_operators.py +105 -0
- physicskit/quantum/tests/test_perturbation.py +112 -0
- physicskit/quantum/tests/test_physics_checks.py +131 -0
- physicskit/quantum/tests/test_potentials.py +191 -0
- physicskit/quantum/tests/test_solvers.py +70 -0
- physicskit/quantum/tests/test_spin.py +22 -0
- physicskit/quantum/tests/test_unitarity.py +84 -0
- physicskit/quantum/tests/test_wave_packets.py +53 -0
- physicskit/quantum/utils/__init__.py +0 -0
- physicskit/quantum/utils/measure.py +253 -0
- physicskit/quantum/visualizers/__init__.py +0 -0
- physicskit/quantum/visualizers/bloch_sphere.py +205 -0
- physicskit/quantum/visualizers/entanglement.py +58 -0
- physicskit/quantum/visualizers/orbitals.py +187 -0
- physicskit/quantum/visualizers/phase_space.py +179 -0
- physicskit/quantum/visualizers/wavefunctions.py +230 -0
- physicskit/relativity/__init__.py +61 -0
- physicskit/relativity/chapters/__init__.py +33 -0
- physicskit/relativity/chapters/cosmology.py +190 -0
- physicskit/relativity/chapters/gw_merger.py +399 -0
- physicskit/relativity/chapters/kerr.py +371 -0
- physicskit/relativity/chapters/lensing.py +196 -0
- physicskit/relativity/chapters/neutron_star.py +149 -0
- physicskit/relativity/chapters/schwarzschild.py +412 -0
- physicskit/relativity/chapters/timekeeping.py +133 -0
- physicskit/relativity/core/__init__.py +12 -0
- physicskit/relativity/core/geodesics.py +216 -0
- physicskit/relativity/core/kerr_raytracer.py +259 -0
- physicskit/relativity/core/raytracer.py +241 -0
- physicskit/relativity/core/tensors.py +468 -0
- physicskit/relativity/tests/__init__.py +0 -0
- physicskit/relativity/tests/test_conservations.py +54 -0
- physicskit/relativity/tests/test_constants.py +34 -0
- physicskit/relativity/tests/test_cosmology.py +61 -0
- physicskit/relativity/tests/test_gw_merger.py +117 -0
- physicskit/relativity/tests/test_kerr.py +116 -0
- physicskit/relativity/tests/test_kerr_raytracer.py +103 -0
- physicskit/relativity/tests/test_lensing.py +75 -0
- physicskit/relativity/tests/test_neutron_star.py +48 -0
- physicskit/relativity/tests/test_raytracer.py +67 -0
- physicskit/relativity/tests/test_schwarzschild.py +126 -0
- physicskit/relativity/tests/test_shadow_render.py +81 -0
- physicskit/relativity/tests/test_tensors.py +86 -0
- physicskit/relativity/tests/test_timekeeping.py +51 -0
- physicskit/relativity/tests/test_visualizers_misc.py +115 -0
- physicskit/relativity/utils/__init__.py +1 -0
- physicskit/relativity/utils/constants.py +232 -0
- physicskit/relativity/visualizers/__init__.py +46 -0
- physicskit/relativity/visualizers/interactive.py +127 -0
- physicskit/relativity/visualizers/shadow_render.py +367 -0
- physicskit/relativity/visualizers/spacetime_3d.py +92 -0
- physicskit/relativity/visualizers/spacetime_diagrams.py +198 -0
- physicskit/relativity/visualizers/wave_plots.py +185 -0
- physicskit/rmt/__init__.py +8 -0
- physicskit/rmt/ensembles/__init__.py +108 -0
- physicskit/rmt/ensembles/banded.py +114 -0
- physicskit/rmt/ensembles/base.py +135 -0
- physicskit/rmt/ensembles/bdg.py +218 -0
- physicskit/rmt/ensembles/chiral.py +308 -0
- physicskit/rmt/ensembles/circular.py +104 -0
- physicskit/rmt/ensembles/crossover.py +82 -0
- physicskit/rmt/ensembles/density_matrix.py +148 -0
- physicskit/rmt/ensembles/effective_hamiltonian.py +230 -0
- physicskit/rmt/ensembles/embedded.py +207 -0
- physicskit/rmt/ensembles/gaussian.py +153 -0
- physicskit/rmt/ensembles/ginibre.py +110 -0
- physicskit/rmt/ensembles/girko.py +190 -0
- physicskit/rmt/ensembles/graph_laplacian.py +92 -0
- physicskit/rmt/ensembles/haar.py +57 -0
- physicskit/rmt/ensembles/jacobi.py +182 -0
- physicskit/rmt/ensembles/poisson.py +77 -0
- physicskit/rmt/ensembles/polynomial.py +139 -0
- physicskit/rmt/ensembles/pt_symmetric.py +120 -0
- physicskit/rmt/ensembles/single_ring.py +170 -0
- physicskit/rmt/ensembles/sparse.py +95 -0
- physicskit/rmt/ensembles/syk.py +170 -0
- physicskit/rmt/ensembles/truncated_unitary.py +80 -0
- physicskit/rmt/ensembles/universality.py +92 -0
- physicskit/rmt/ensembles/wishart.py +88 -0
- physicskit/rmt/py.typed +0 -0
- physicskit/rmt/spectrum.py +82 -0
- physicskit/rmt/stats/__init__.py +160 -0
- physicskit/rmt/stats/characteristic_polynomial.py +77 -0
- physicskit/rmt/stats/circular_law.py +54 -0
- physicskit/rmt/stats/correlations.py +162 -0
- physicskit/rmt/stats/density.py +70 -0
- physicskit/rmt/stats/entanglement.py +36 -0
- physicskit/rmt/stats/free_probability.py +202 -0
- physicskit/rmt/stats/localization.py +338 -0
- physicskit/rmt/stats/marchenko_pastur.py +55 -0
- physicskit/rmt/stats/pt_symmetric.py +265 -0
- physicskit/rmt/stats/ratios.py +110 -0
- physicskit/rmt/stats/real_ginibre.py +134 -0
- physicskit/rmt/stats/rigidity.py +272 -0
- physicskit/rmt/stats/single_ring.py +95 -0
- physicskit/rmt/stats/spacing.py +150 -0
- physicskit/rmt/stats/tracy_widom.py +175 -0
- physicskit/rmt/stats/truncated_unitary.py +40 -0
- physicskit/rmt/stats/unfolding.py +37 -0
- physicskit/rmt/stats/wachter.py +67 -0
- physicskit/rmt/tests/__init__.py +0 -0
- physicskit/rmt/tests/cache_utils.py +107 -0
- physicskit/rmt/tests/conftest.py +8 -0
- physicskit/rmt/tests/test_banded.py +86 -0
- physicskit/rmt/tests/test_base.py +29 -0
- physicskit/rmt/tests/test_bdg.py +133 -0
- physicskit/rmt/tests/test_characteristic_polynomial.py +50 -0
- physicskit/rmt/tests/test_chiral.py +273 -0
- physicskit/rmt/tests/test_circular.py +225 -0
- physicskit/rmt/tests/test_crossover.py +72 -0
- physicskit/rmt/tests/test_density.py +23 -0
- physicskit/rmt/tests/test_density_matrix.py +181 -0
- physicskit/rmt/tests/test_effective_hamiltonian.py +140 -0
- physicskit/rmt/tests/test_embedded.py +169 -0
- physicskit/rmt/tests/test_free_probability.py +81 -0
- physicskit/rmt/tests/test_gaussian_ensembles.py +22 -0
- physicskit/rmt/tests/test_gaussian_semicircle.py +127 -0
- physicskit/rmt/tests/test_ginibre_circular_law.py +131 -0
- physicskit/rmt/tests/test_girko.py +178 -0
- physicskit/rmt/tests/test_graph_laplacian.py +102 -0
- physicskit/rmt/tests/test_haar.py +118 -0
- physicskit/rmt/tests/test_jacobi_wachter.py +136 -0
- physicskit/rmt/tests/test_localization.py +240 -0
- physicskit/rmt/tests/test_poisson.py +149 -0
- physicskit/rmt/tests/test_polynomial.py +107 -0
- physicskit/rmt/tests/test_pt_symmetric.py +178 -0
- physicskit/rmt/tests/test_random_state.py +19 -0
- physicskit/rmt/tests/test_real_ginibre.py +112 -0
- physicskit/rmt/tests/test_rigidity_universality.py +167 -0
- physicskit/rmt/tests/test_single_ring.py +132 -0
- physicskit/rmt/tests/test_spacing_and_ratios.py +122 -0
- physicskit/rmt/tests/test_sparse.py +71 -0
- physicskit/rmt/tests/test_spectrum.py +27 -0
- physicskit/rmt/tests/test_syk.py +136 -0
- physicskit/rmt/tests/test_tracy_widom.py +113 -0
- physicskit/rmt/tests/test_tridiagonal.py +41 -0
- physicskit/rmt/tests/test_truncated_unitary.py +80 -0
- physicskit/rmt/tests/test_validation_base.py +25 -0
- physicskit/rmt/tests/test_validation_misc.py +67 -0
- physicskit/rmt/tests/test_wishart_marchenko_pastur.py +120 -0
- physicskit/rmt/utils/__init__.py +0 -0
- physicskit/rmt/utils/haar.py +128 -0
- physicskit/rmt/utils/random_state.py +24 -0
- physicskit/rmt/utils/tridiagonal.py +167 -0
- physicskit/rmt/validation/__init__.py +36 -0
- physicskit/rmt/validation/base.py +126 -0
- physicskit/rmt/validation/circular_law.py +80 -0
- physicskit/rmt/validation/marchenko_pastur.py +53 -0
- physicskit/rmt/validation/ratio_distribution.py +53 -0
- physicskit/rmt/validation/real_ginibre.py +60 -0
- physicskit/rmt/validation/sine_kernel.py +57 -0
- physicskit/rmt/validation/single_ring.py +68 -0
- physicskit/rmt/validation/tracy_widom.py +89 -0
- physicskit/rmt/validation/universality.py +100 -0
- physicskit/rmt/validation/wachter.py +52 -0
- physicskit/rmt/validation/wigner_semicircle.py +40 -0
- physicskit/rmt/validation/wigner_surmise.py +58 -0
- physicskit/semiclassical/__init__.py +94 -0
- physicskit/semiclassical/_compat.py +5 -0
- physicskit/semiclassical/core/__init__.py +41 -0
- physicskit/semiclassical/core/gutzwiller.py +215 -0
- physicskit/semiclassical/core/path_integral.py +594 -0
- physicskit/semiclassical/core/propagators.py +579 -0
- physicskit/semiclassical/core/wkb.py +308 -0
- physicskit/semiclassical/systems/__init__.py +13 -0
- physicskit/semiclassical/systems/scarring.py +278 -0
- physicskit/semiclassical/tests/__init__.py +0 -0
- physicskit/semiclassical/tests/test_gutzwiller.py +35 -0
- physicskit/semiclassical/tests/test_path_integral.py +194 -0
- physicskit/semiclassical/tests/test_propagators.py +82 -0
- physicskit/semiclassical/tests/test_scarring.py +43 -0
- physicskit/semiclassical/tests/test_visualizers.py +89 -0
- physicskit/semiclassical/tests/test_wkb.py +30 -0
- physicskit/semiclassical/visualizers/__init__.py +17 -0
- physicskit/semiclassical/visualizers/gutzwiller.py +55 -0
- physicskit/semiclassical/visualizers/path_integral.py +195 -0
- physicskit/semiclassical/visualizers/propagators.py +89 -0
- physicskit/semiclassical/visualizers/scarring.py +146 -0
- physicskit/semiclassical/visualizers/wkb.py +55 -0
- physicskit/statphys/__init__.py +80 -0
- physicskit/statphys/chapters/__init__.py +43 -0
- physicskit/statphys/chapters/ehrenfest_urn.py +112 -0
- physicskit/statphys/chapters/ising_lattice.py +431 -0
- physicskit/statphys/chapters/kpz_growth.py +129 -0
- physicskit/statphys/chapters/molecular_dynamics.py +258 -0
- physicskit/statphys/chapters/nonequilibrium_work.py +146 -0
- physicskit/statphys/chapters/percolation.py +305 -0
- physicskit/statphys/chapters/random_walk.py +142 -0
- physicskit/statphys/chapters/renormalization.py +148 -0
- physicskit/statphys/chapters/sandpile.py +109 -0
- physicskit/statphys/chapters/spin_glass.py +275 -0
- physicskit/statphys/core/__init__.py +10 -0
- physicskit/statphys/core/kpz_engine.py +53 -0
- physicskit/statphys/core/md_engine.py +157 -0
- physicskit/statphys/core/monte_carlo.py +462 -0
- physicskit/statphys/core/random_walk_engine.py +68 -0
- physicskit/statphys/core/sandpile_engine.py +52 -0
- physicskit/statphys/tests/__init__.py +0 -0
- physicskit/statphys/tests/test_dynamics.py +66 -0
- physicskit/statphys/tests/test_ehrenfest_urn.py +44 -0
- physicskit/statphys/tests/test_finite_size_scaling.py +62 -0
- physicskit/statphys/tests/test_interactive.py +33 -0
- physicskit/statphys/tests/test_ising.py +68 -0
- physicskit/statphys/tests/test_kpz.py +55 -0
- physicskit/statphys/tests/test_landau_theory.py +49 -0
- physicskit/statphys/tests/test_md_engine.py +31 -0
- physicskit/statphys/tests/test_molecular_dynamics.py +72 -0
- physicskit/statphys/tests/test_nonequilibrium_work.py +33 -0
- physicskit/statphys/tests/test_partition_function.py +26 -0
- physicskit/statphys/tests/test_percolation.py +116 -0
- physicskit/statphys/tests/test_potts_model.py +46 -0
- physicskit/statphys/tests/test_random_walk.py +50 -0
- physicskit/statphys/tests/test_renormalization.py +44 -0
- physicskit/statphys/tests/test_sandpile.py +44 -0
- physicskit/statphys/tests/test_spin_glass.py +73 -0
- physicskit/statphys/tests/test_thermodynamics.py +121 -0
- physicskit/statphys/tests/test_xy_model.py +45 -0
- physicskit/statphys/utils/__init__.py +1 -0
- physicskit/statphys/utils/dynamics.py +100 -0
- physicskit/statphys/utils/finite_size_scaling.py +171 -0
- physicskit/statphys/utils/landau_theory.py +151 -0
- physicskit/statphys/utils/partition_function.py +109 -0
- physicskit/statphys/utils/thermodynamics.py +356 -0
- physicskit/statphys/visualizers/__init__.py +87 -0
- physicskit/statphys/visualizers/interactive.py +161 -0
- physicskit/statphys/visualizers/jarzynski_render.py +44 -0
- physicskit/statphys/visualizers/kpz_render.py +65 -0
- physicskit/statphys/visualizers/lattice_render.py +212 -0
- physicskit/statphys/visualizers/particle_render.py +121 -0
- physicskit/statphys/visualizers/random_walk_render.py +106 -0
- physicskit/statphys/visualizers/rg_render.py +45 -0
- physicskit/statphys/visualizers/sandpile_render.py +65 -0
- physicskit/statphys/visualizers/spin_glass_render.py +40 -0
- physicskit/statphys/visualizers/urn_render.py +38 -0
- physicskit/statphys/visualizers/vortex_render.py +84 -0
- physicskit/tests/__init__.py +0 -0
- physicskit/tests/test_constants.py +38 -0
- physicskit-0.1.0.dist-info/METADATA +196 -0
- physicskit-0.1.0.dist-info/RECORD +484 -0
- physicskit-0.1.0.dist-info/WHEEL +5 -0
- physicskit-0.1.0.dist-info/licenses/LICENSE +21 -0
- 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)
|