tbkit 0.4.2__tar.gz → 0.5.0__tar.gz

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 (89) hide show
  1. tbkit-0.5.0/PKG-INFO +259 -0
  2. tbkit-0.5.0/README.md +226 -0
  3. {tbkit-0.4.2 → tbkit-0.5.0}/pyproject.toml +32 -4
  4. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/__init__.py +13 -1
  5. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/bdg.py +82 -0
  6. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/bridges.py +12 -5
  7. tbkit-0.5.0/tbkit/continuum.py +273 -0
  8. tbkit-0.5.0/tbkit/dos.py +238 -0
  9. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/error_handling.py +778 -9
  10. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/graphene.py +48 -0
  11. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/io.py +32 -6
  12. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/kpm.py +2 -1
  13. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/kspace.py +1666 -102
  14. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/neighbours.py +10 -2
  15. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/orbital.py +34 -11
  16. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/plot.py +8 -7
  17. tbkit-0.5.0/tbkit/py.typed +0 -0
  18. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/system.py +282 -32
  19. tbkit-0.5.0/tbkit/topology.py +316 -0
  20. tbkit-0.5.0/tbkit/transport.py +1337 -0
  21. tbkit-0.5.0/tbkit/values.py +77 -0
  22. tbkit-0.5.0/tbkit/wannier.py +554 -0
  23. tbkit-0.5.0/tbkit.egg-info/PKG-INFO +259 -0
  24. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit.egg-info/SOURCES.txt +14 -1
  25. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit.egg-info/requires.txt +5 -0
  26. tbkit-0.5.0/tests/test_analysis.py +451 -0
  27. tbkit-0.5.0/tests/test_berry_response.py +240 -0
  28. tbkit-0.5.0/tests/test_continuum.py +134 -0
  29. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_dos.py +3 -2
  30. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_error_handling.py +128 -0
  31. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_exceptional.py +1 -1
  32. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_green_occupation.py +2 -1
  33. tbkit-0.5.0/tests/test_invariants.py +315 -0
  34. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_kpm.py +2 -1
  35. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_kspace.py +50 -0
  36. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_moire.py +2 -1
  37. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_optics.py +3 -3
  38. tbkit-0.5.0/tests/test_periodic.py +254 -0
  39. tbkit-0.5.0/tests/test_smatrix.py +289 -0
  40. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_transport.py +57 -0
  41. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_transport_response.py +3 -3
  42. tbkit-0.5.0/tests/test_values.py +316 -0
  43. tbkit-0.5.0/tests/test_wannier_functions.py +341 -0
  44. tbkit-0.4.2/PKG-INFO +0 -375
  45. tbkit-0.4.2/README.md +0 -347
  46. tbkit-0.4.2/tbkit/dos.py +0 -98
  47. tbkit-0.4.2/tbkit/transport.py +0 -717
  48. tbkit-0.4.2/tbkit.egg-info/PKG-INFO +0 -375
  49. {tbkit-0.4.2 → tbkit-0.5.0}/LICENSE +0 -0
  50. {tbkit-0.4.2 → tbkit-0.5.0}/setup.cfg +0 -0
  51. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/exceptional.py +0 -0
  52. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/floquet.py +0 -0
  53. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/higher_order.py +0 -0
  54. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/lattice.py +0 -0
  55. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/lattices.py +0 -0
  56. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/meanfield.py +0 -0
  57. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/moire.py +0 -0
  58. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/occupation.py +0 -0
  59. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/optics.py +0 -0
  60. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/propagation.py +0 -0
  61. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/save.py +0 -0
  62. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit/slater_koster.py +0 -0
  63. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit.egg-info/dependency_links.txt +0 -0
  64. {tbkit-0.4.2 → tbkit-0.5.0}/tbkit.egg-info/top_level.txt +0 -0
  65. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_bridges.py +0 -0
  66. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_correlations.py +0 -0
  67. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_error_handling_structures.py +0 -0
  68. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_floquet.py +0 -0
  69. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_graphene.py +0 -0
  70. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_hall.py +0 -0
  71. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_higher_order.py +0 -0
  72. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_interactions.py +0 -0
  73. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_io.py +0 -0
  74. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_large_lattices.py +0 -0
  75. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_lattice.py +0 -0
  76. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_lattices.py +0 -0
  77. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_magnetic.py +0 -0
  78. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_neighbours.py +0 -0
  79. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_non_hermitian_bands.py +0 -0
  80. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_orbitals.py +0 -0
  81. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_plot.py +0 -0
  82. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_propagation.py +0 -0
  83. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_regressions.py +0 -0
  84. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_save.py +0 -0
  85. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_surface_spectral.py +0 -0
  86. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_system.py +0 -0
  87. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_three_d.py +0 -0
  88. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_topology.py +0 -0
  89. {tbkit-0.4.2 → tbkit-0.5.0}/tests/test_wannier90.py +0 -0
tbkit-0.5.0/PKG-INFO ADDED
@@ -0,0 +1,259 @@
1
+ Metadata-Version: 2.4
2
+ Name: tbkit
3
+ Version: 0.5.0
4
+ Summary: A Python package to build and solve Tight-Binding models.
5
+ Author-email: Charles Poli <cpoli374@gmail.com>
6
+ Maintainer-email: Charles Poli <cpoli374@gmail.com>
7
+ License-Expression: BSD-3-Clause
8
+ Project-URL: Homepage, https://github.com/cpoli/tbkit
9
+ Classifier: Intended Audience :: Education
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Topic :: Scientific/Engineering :: Physics
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Typing :: Typed
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: numpy>=1.24
18
+ Requires-Dist: scipy>=1.10
19
+ Requires-Dist: matplotlib>=3.7
20
+ Provides-Extra: continuum
21
+ Requires-Dist: sympy>=1.12; extra == "continuum"
22
+ Provides-Extra: test
23
+ Requires-Dist: pytest>=7; extra == "test"
24
+ Requires-Dist: pytest-cov>=4; extra == "test"
25
+ Requires-Dist: pytest-xdist>=3.2; extra == "test"
26
+ Requires-Dist: sympy>=1.12; extra == "test"
27
+ Provides-Extra: docs
28
+ Requires-Dist: sphinx>=7; extra == "docs"
29
+ Requires-Dist: pydata-sphinx-theme>=0.15; extra == "docs"
30
+ Requires-Dist: sphinx-gallery>=0.15; extra == "docs"
31
+ Requires-Dist: sympy>=1.12; extra == "docs"
32
+ Dynamic: license-file
33
+
34
+ # tbkit — a Tight-Binding package
35
+
36
+ | | |
37
+ |:--|:-:|
38
+ | Package | [![PyPI version](https://img.shields.io/pypi/v/tbkit)](https://pypi.org/project/tbkit/) [![Python versions](https://img.shields.io/pypi/pyversions/tbkit)](https://pypi.org/project/tbkit/) [![DOI](https://zenodo.org/badge/1381398706.svg)](https://zenodo.org/badge/latestdoi/1381398706) |
39
+ | Quality | [![License](https://img.shields.io/github/license/cpoli/tbkit)](https://github.com/cpoli/tbkit/blob/master/LICENSE) [![CI](https://github.com/cpoli/tbkit/actions/workflows/tests.yml/badge.svg)](https://github.com/cpoli/tbkit/actions/workflows/tests.yml) [![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen)](https://cpoli.github.io/tbkit/coverage/) |
40
+ | Documentation | [![Docs](https://img.shields.io/badge/docs-cpoli.github.io%2Ftbkit-blue)](https://cpoli.github.io/tbkit/) |
41
+ | Downloads | [![Downloads](https://static.pepy.tech/badge/tbkit)](https://pepy.tech/project/tbkit) [![Downloads/Month](https://static.pepy.tech/badge/tbkit/month)](https://pepy.tech/project/tbkit) |
42
+ | Community | [![GitHub Stars](https://img.shields.io/github/stars/cpoli/tbkit?style=social)](https://github.com/cpoli/tbkit) [![GitHub Forks](https://img.shields.io/github/forks/cpoli/tbkit?style=social)](https://github.com/cpoli/tbkit) [![Contributors](https://img.shields.io/github/contributors/cpoli/tbkit)](https://github.com/cpoli/tbkit/graphs/contributors) [![Last Commit](https://img.shields.io/github/last-commit/cpoli/tbkit)](https://github.com/cpoli/tbkit/commits/master) |
43
+
44
+ ![tbkit logo](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/image/tbkit_logo.png)
45
+
46
+ **tbkit** is a Python package to build and solve Tight-Binding models, written
47
+ in vectorized NumPy/SciPy. It aims to make the mechanics of Tight-Binding
48
+ models — lattices, hoppings, Hamiltonians, spectra, band structures —
49
+ explicit and easy to inspect, so it works as well for teaching as for
50
+ research prototyping.
51
+
52
+ ![Graphene's Dirac cone, Hofstadter's butterfly, and helical edge states of a Kane-Mele ribbon, all computed with tbkit](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_hero.png)
53
+
54
+ For computational physics beyond tight-binding — quantum mechanics,
55
+ classical mechanics, statistical physics, general relativity, and more —
56
+ see [physicskit](https://github.com/cpoli/physicskit), whose
57
+ `physicskit.condensed` subpackage covers tight-binding band theory and
58
+ topology alongside superconductivity.
59
+
60
+ ## Examples
61
+
62
+ ### Building and solving models
63
+
64
+ Finite lattices, defects, several orbitals per site, real space to k-space and back, k·p models discretized into lattice models, saved models and Wannier90 imports, maximally localized Wannier functions, and solvers for very large lattices.
65
+
66
+ ![An impurity bound state, Slater-Koster sp3 graphene bands with overlaps, and the kernel polynomial method on 45,000 sites](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_models.png)
67
+
68
+ ### Fields, strain and disorder
69
+
70
+ What happens to a lattice under a magnetic field (Peierls substitution), under strain, and with disorder.
71
+
72
+ ![Graphene's sqrt(n) Landau ladder, triaxial strain as a pseudo-magnetic field, and Anderson localization](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_fields.png)
73
+
74
+ ### Band topology
75
+
76
+ Chern numbers, Berry phases, the Z2 invariant (and the four 3D indices), spin and mirror Chern numbers, the Bott index and entanglement spectrum, Weyl points and their chirality, Kitaev's Majorana number, quantum geometry, symmetry classes, higher-order and 3D topological phases.
77
+
78
+ ![Berry curvature of the Haldane model, the Kane-Mele Z2 Wannier flow, and the four corner states of a quadrupole insulator](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_topology.png)
79
+
80
+ ### Response and transport
81
+
82
+ Hall conductivities at any Fermi level (with the orbital magnetization, Nernst and thermal Hall responses), Landauer transport between leads, and linear and nonlinear optical response.
83
+
84
+ ![The anomalous Hall conductivity of the Haldane model, the conductance steps of a quantum point contact, and graphene's universal absorption](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_response.png)
85
+
86
+ ### Flat bands and interactions
87
+
88
+ Flat bands from lattice geometry and from a moiré twist, the Hubbard model in mean field, and superconductivity.
89
+
90
+ ![The flat bands of twisted bilayer graphene, magnetic zigzag edges in Hubbard mean field, and the Majorana end modes of a Kitaev chain](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_interactions.png)
91
+
92
+ ### Driven and open systems
93
+
94
+ Wavepacket dynamics, periodically driven (Floquet) lattices, and non-Hermitian bands with exceptional points.
95
+
96
+ ![Bloch oscillations in a tilted chain, the Floquet bands of graphene in circularly polarized light, and the non-Hermitian skin effect](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_driven.png)
97
+
98
+ ## Install
99
+
100
+ Requires Python >= 3.10.
101
+
102
+ ```bash
103
+ pip install tbkit
104
+ ```
105
+
106
+ `tbkit.continuum` (k·p models to tight-binding) also needs sympy:
107
+
108
+ ```bash
109
+ pip install "tbkit[continuum]"
110
+ ```
111
+
112
+ or, for an editable install from a clone (e.g. to run the test suite or
113
+ work on tbkit itself):
114
+
115
+ ```bash
116
+ git clone https://github.com/cpoli/tbkit
117
+ cd tbkit
118
+ pip install -e .
119
+ ```
120
+
121
+ or, to also install the tools needed to run the test suite:
122
+
123
+ ```bash
124
+ pip install -e ".[test]"
125
+ pytest tests/
126
+ ```
127
+
128
+ The test suite has 100% line coverage of the `tbkit` package; see the
129
+ [HTML coverage report](https://cpoli.github.io/tbkit/coverage/).
130
+
131
+ ## Quick start
132
+
133
+ Real-space flake, nearest-neighbor square lattice:
134
+
135
+ ```python
136
+ from tbkit.lattice import Lattice
137
+ from tbkit.system import System
138
+
139
+ lat = Lattice(unit_cell=[{'tag': 'a', 'r0': (0., 0.)}],
140
+ prim_vec=[(1., 0.), (0., 1.)])
141
+ lat.get_lattice(n1=10, n2=10)
142
+
143
+ sys = System(lat)
144
+ sys.set_hopping([{'n': 1, 't': 1.}])
145
+ sys.get_ham()
146
+ sys.get_eig()
147
+ print(sys.en)
148
+ ```
149
+
150
+ Graphene band structure (reciprocal space):
151
+
152
+ ```python
153
+ import numpy as np
154
+ from tbkit.lattice import Lattice
155
+ from tbkit.kspace import KSpace, reciprocal_vectors
156
+
157
+ DX, DY = 0.5 * 3 ** 0.5, 0.5
158
+ unit_cell = [{'tag': 'a', 'r0': (0., 0.)}, {'tag': 'b', 'r0': (DX, DY)}]
159
+ prim_vec = [(2 * DX, 0.), (DX, 1.5)]
160
+ lat = Lattice(unit_cell=unit_cell, prim_vec=prim_vec)
161
+
162
+ gra = KSpace(lat)
163
+ gra.set_hopping([{'i': 0, 'j': 1, 'R': (0, 0), 't': 1.},
164
+ {'i': 0, 'j': 1, 'R': (-1, 0), 't': 1.},
165
+ {'i': 0, 'j': 1, 'R': (0, -1), 't': 1.}])
166
+
167
+ b1, b2 = (np.array(v) for v in reciprocal_vectors(prim_vec))
168
+ Gamma, K, M = np.zeros(2), (b1 - b2) / 3, b1 / 2
169
+ gra.k_path([Gamma, K, M, Gamma], nk=60)
170
+ fig = gra.plot_bands(node_labels=[r'$\Gamma$', 'K', 'M', r'$\Gamma$'])
171
+ fig.savefig('graphene_bands.png')
172
+ ```
173
+
174
+ A magnetic field is added with `System.set_magnetic_field` (uniform field) or
175
+ `System.set_peierls_phase` (arbitrary vector potential), applied to the
176
+ hoppings *after* `set_hopping`/`set_hopping_manual`:
177
+
178
+ ```python
179
+ sys.set_hopping_manual(hop_dict)
180
+ sys.set_magnetic_field(alpha=0.01) # flux quanta per unit area
181
+ sys.get_ham()
182
+ ```
183
+
184
+ See [`examples/magnetic_field/plot_magnetic_field.py`](examples/magnetic_field/plot_magnetic_field.py) for a full
185
+ worked example (an Aharonov-Bohm ring, reproducing the textbook result that
186
+ the spectrum is periodic in the enclosed flux with period one flux quantum).
187
+
188
+ A Chern number is the Berry curvature of a group of bands, integrated over
189
+ the Brillouin zone:
190
+
191
+ ```python
192
+ chern = gra.chern_number(bands=[0], nk=40) # ~0 for plain graphene
193
+ ```
194
+
195
+ See [`examples/topology/plot_haldane_topology.py`](examples/topology/plot_haldane_topology.py) for the
196
+ Haldane model (the first Chern insulator), reproducing its topological
197
+ phase transition (Chern number 1 -> 0) and Berry-curvature map.
198
+
199
+ A spin-1/2 degree of freedom is added with `KSpace(lat, spin=True)`; onsite
200
+ values and hoppings then also accept 2x2 (Pauli) matrices:
201
+
202
+ ```python
203
+ from tbkit.kspace import KSpace, PAULI
204
+
205
+ kmele = KSpace(lat, spin=True)
206
+ kmele.set_hopping([{'i': 0, 'j': 0, 'R': (1, 0), 't': 1j*lam*PAULI['z']}]) # intrinsic SOC
207
+ ```
208
+
209
+ A ribbon -- periodic in one direction, finite in the other, the standard
210
+ way to see edge states -- is cut out of a periodic model with
211
+ `tbkit.kspace.ribbon`:
212
+
213
+ ```python
214
+ from tbkit.kspace import ribbon
215
+
216
+ rib = ribbon(lat, list_hop, width=30, direction=1) # 30 unit cells wide
217
+ fig = rib.plot_bands()
218
+ ```
219
+
220
+ See [`examples/topology/plot_edge_states.py`](examples/topology/plot_edge_states.py) for the zigzag
221
+ graphene ribbon's zero-energy edge band, and the Kane-Mele ribbon's helical
222
+ edge states crossing a spin-orbit gap.
223
+
224
+ ## Documentation
225
+
226
+ Rendered docs (tutorial, API reference, example gallery): https://cpoli.github.io/tbkit/
227
+
228
+ * [`docs/source/tutorial.rst`](docs/source/tutorial.rst) -- a narrative walkthrough of the
229
+ package, from building a lattice through topology, spin-orbit coupling,
230
+ and edge states.
231
+ * [`docs/source/history.rst`](docs/source/history.rst) -- a chronology of the breakthroughs
232
+ behind Tight-Binding theory (Bloch's theorem through the Kane-Mele model),
233
+ each one linked to the corresponding **tbkit** functionality and example
234
+ above.
235
+ * `docs/source/tbkit.rst` -- the API reference (auto-generated from docstrings).
236
+ * [`ROADMAP.md`](ROADMAP.md) -- what is planned next, and what tbkit
237
+ does not do yet (compared with Kwant and PythTB).
238
+
239
+ Build the HTML docs with `cd docs && make html` (output in `docs/build/html`).
240
+
241
+ ## A note on the API
242
+
243
+ Version 0.2 modernized the package to run on current Python/NumPy/SciPy and
244
+ cleaned up the API:
245
+
246
+ * Sublattice tags are plain one-character **strings** (`'a'`) rather than
247
+ byte strings (`b'a'`).
248
+ * Classes are named in `PascalCase` (`Lattice`, `System`, ...) rather than
249
+ lowercase names identical to their module (`lattice.lattice`,
250
+ `system.system`, ...), which used to make `import tbkit.lattice as lattice`
251
+ silently bind the wrong object.
252
+
253
+ For continuity, the pre-0.2 lowercase class names (`lattice`, `system`,
254
+ `plot`, `propagation`, `save`) remain available as aliases of the new
255
+ classes, so `from tbkit.lattice import lattice` still works.
256
+
257
+ ## License
258
+
259
+ BSD 3-Clause, see [LICENSE](LICENSE).
tbkit-0.5.0/README.md ADDED
@@ -0,0 +1,226 @@
1
+ # tbkit — a Tight-Binding package
2
+
3
+ | | |
4
+ |:--|:-:|
5
+ | Package | [![PyPI version](https://img.shields.io/pypi/v/tbkit)](https://pypi.org/project/tbkit/) [![Python versions](https://img.shields.io/pypi/pyversions/tbkit)](https://pypi.org/project/tbkit/) [![DOI](https://zenodo.org/badge/1381398706.svg)](https://zenodo.org/badge/latestdoi/1381398706) |
6
+ | Quality | [![License](https://img.shields.io/github/license/cpoli/tbkit)](https://github.com/cpoli/tbkit/blob/master/LICENSE) [![CI](https://github.com/cpoli/tbkit/actions/workflows/tests.yml/badge.svg)](https://github.com/cpoli/tbkit/actions/workflows/tests.yml) [![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen)](https://cpoli.github.io/tbkit/coverage/) |
7
+ | Documentation | [![Docs](https://img.shields.io/badge/docs-cpoli.github.io%2Ftbkit-blue)](https://cpoli.github.io/tbkit/) |
8
+ | Downloads | [![Downloads](https://static.pepy.tech/badge/tbkit)](https://pepy.tech/project/tbkit) [![Downloads/Month](https://static.pepy.tech/badge/tbkit/month)](https://pepy.tech/project/tbkit) |
9
+ | Community | [![GitHub Stars](https://img.shields.io/github/stars/cpoli/tbkit?style=social)](https://github.com/cpoli/tbkit) [![GitHub Forks](https://img.shields.io/github/forks/cpoli/tbkit?style=social)](https://github.com/cpoli/tbkit) [![Contributors](https://img.shields.io/github/contributors/cpoli/tbkit)](https://github.com/cpoli/tbkit/graphs/contributors) [![Last Commit](https://img.shields.io/github/last-commit/cpoli/tbkit)](https://github.com/cpoli/tbkit/commits/master) |
10
+
11
+ ![tbkit logo](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/image/tbkit_logo.png)
12
+
13
+ **tbkit** is a Python package to build and solve Tight-Binding models, written
14
+ in vectorized NumPy/SciPy. It aims to make the mechanics of Tight-Binding
15
+ models — lattices, hoppings, Hamiltonians, spectra, band structures —
16
+ explicit and easy to inspect, so it works as well for teaching as for
17
+ research prototyping.
18
+
19
+ ![Graphene's Dirac cone, Hofstadter's butterfly, and helical edge states of a Kane-Mele ribbon, all computed with tbkit](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_hero.png)
20
+
21
+ For computational physics beyond tight-binding — quantum mechanics,
22
+ classical mechanics, statistical physics, general relativity, and more —
23
+ see [physicskit](https://github.com/cpoli/physicskit), whose
24
+ `physicskit.condensed` subpackage covers tight-binding band theory and
25
+ topology alongside superconductivity.
26
+
27
+ ## Examples
28
+
29
+ ### Building and solving models
30
+
31
+ Finite lattices, defects, several orbitals per site, real space to k-space and back, k·p models discretized into lattice models, saved models and Wannier90 imports, maximally localized Wannier functions, and solvers for very large lattices.
32
+
33
+ ![An impurity bound state, Slater-Koster sp3 graphene bands with overlaps, and the kernel polynomial method on 45,000 sites](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_models.png)
34
+
35
+ ### Fields, strain and disorder
36
+
37
+ What happens to a lattice under a magnetic field (Peierls substitution), under strain, and with disorder.
38
+
39
+ ![Graphene's sqrt(n) Landau ladder, triaxial strain as a pseudo-magnetic field, and Anderson localization](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_fields.png)
40
+
41
+ ### Band topology
42
+
43
+ Chern numbers, Berry phases, the Z2 invariant (and the four 3D indices), spin and mirror Chern numbers, the Bott index and entanglement spectrum, Weyl points and their chirality, Kitaev's Majorana number, quantum geometry, symmetry classes, higher-order and 3D topological phases.
44
+
45
+ ![Berry curvature of the Haldane model, the Kane-Mele Z2 Wannier flow, and the four corner states of a quadrupole insulator](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_topology.png)
46
+
47
+ ### Response and transport
48
+
49
+ Hall conductivities at any Fermi level (with the orbital magnetization, Nernst and thermal Hall responses), Landauer transport between leads, and linear and nonlinear optical response.
50
+
51
+ ![The anomalous Hall conductivity of the Haldane model, the conductance steps of a quantum point contact, and graphene's universal absorption](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_response.png)
52
+
53
+ ### Flat bands and interactions
54
+
55
+ Flat bands from lattice geometry and from a moiré twist, the Hubbard model in mean field, and superconductivity.
56
+
57
+ ![The flat bands of twisted bilayer graphene, magnetic zigzag edges in Hubbard mean field, and the Majorana end modes of a Kitaev chain](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_interactions.png)
58
+
59
+ ### Driven and open systems
60
+
61
+ Wavepacket dynamics, periodically driven (Floquet) lattices, and non-Hermitian bands with exceptional points.
62
+
63
+ ![Bloch oscillations in a tilted chain, the Floquet bands of graphene in circularly polarized light, and the non-Hermitian skin effect](https://raw.githubusercontent.com/cpoli/tbkit/master/docs/source/_static/images/readme_driven.png)
64
+
65
+ ## Install
66
+
67
+ Requires Python >= 3.10.
68
+
69
+ ```bash
70
+ pip install tbkit
71
+ ```
72
+
73
+ `tbkit.continuum` (k·p models to tight-binding) also needs sympy:
74
+
75
+ ```bash
76
+ pip install "tbkit[continuum]"
77
+ ```
78
+
79
+ or, for an editable install from a clone (e.g. to run the test suite or
80
+ work on tbkit itself):
81
+
82
+ ```bash
83
+ git clone https://github.com/cpoli/tbkit
84
+ cd tbkit
85
+ pip install -e .
86
+ ```
87
+
88
+ or, to also install the tools needed to run the test suite:
89
+
90
+ ```bash
91
+ pip install -e ".[test]"
92
+ pytest tests/
93
+ ```
94
+
95
+ The test suite has 100% line coverage of the `tbkit` package; see the
96
+ [HTML coverage report](https://cpoli.github.io/tbkit/coverage/).
97
+
98
+ ## Quick start
99
+
100
+ Real-space flake, nearest-neighbor square lattice:
101
+
102
+ ```python
103
+ from tbkit.lattice import Lattice
104
+ from tbkit.system import System
105
+
106
+ lat = Lattice(unit_cell=[{'tag': 'a', 'r0': (0., 0.)}],
107
+ prim_vec=[(1., 0.), (0., 1.)])
108
+ lat.get_lattice(n1=10, n2=10)
109
+
110
+ sys = System(lat)
111
+ sys.set_hopping([{'n': 1, 't': 1.}])
112
+ sys.get_ham()
113
+ sys.get_eig()
114
+ print(sys.en)
115
+ ```
116
+
117
+ Graphene band structure (reciprocal space):
118
+
119
+ ```python
120
+ import numpy as np
121
+ from tbkit.lattice import Lattice
122
+ from tbkit.kspace import KSpace, reciprocal_vectors
123
+
124
+ DX, DY = 0.5 * 3 ** 0.5, 0.5
125
+ unit_cell = [{'tag': 'a', 'r0': (0., 0.)}, {'tag': 'b', 'r0': (DX, DY)}]
126
+ prim_vec = [(2 * DX, 0.), (DX, 1.5)]
127
+ lat = Lattice(unit_cell=unit_cell, prim_vec=prim_vec)
128
+
129
+ gra = KSpace(lat)
130
+ gra.set_hopping([{'i': 0, 'j': 1, 'R': (0, 0), 't': 1.},
131
+ {'i': 0, 'j': 1, 'R': (-1, 0), 't': 1.},
132
+ {'i': 0, 'j': 1, 'R': (0, -1), 't': 1.}])
133
+
134
+ b1, b2 = (np.array(v) for v in reciprocal_vectors(prim_vec))
135
+ Gamma, K, M = np.zeros(2), (b1 - b2) / 3, b1 / 2
136
+ gra.k_path([Gamma, K, M, Gamma], nk=60)
137
+ fig = gra.plot_bands(node_labels=[r'$\Gamma$', 'K', 'M', r'$\Gamma$'])
138
+ fig.savefig('graphene_bands.png')
139
+ ```
140
+
141
+ A magnetic field is added with `System.set_magnetic_field` (uniform field) or
142
+ `System.set_peierls_phase` (arbitrary vector potential), applied to the
143
+ hoppings *after* `set_hopping`/`set_hopping_manual`:
144
+
145
+ ```python
146
+ sys.set_hopping_manual(hop_dict)
147
+ sys.set_magnetic_field(alpha=0.01) # flux quanta per unit area
148
+ sys.get_ham()
149
+ ```
150
+
151
+ See [`examples/magnetic_field/plot_magnetic_field.py`](examples/magnetic_field/plot_magnetic_field.py) for a full
152
+ worked example (an Aharonov-Bohm ring, reproducing the textbook result that
153
+ the spectrum is periodic in the enclosed flux with period one flux quantum).
154
+
155
+ A Chern number is the Berry curvature of a group of bands, integrated over
156
+ the Brillouin zone:
157
+
158
+ ```python
159
+ chern = gra.chern_number(bands=[0], nk=40) # ~0 for plain graphene
160
+ ```
161
+
162
+ See [`examples/topology/plot_haldane_topology.py`](examples/topology/plot_haldane_topology.py) for the
163
+ Haldane model (the first Chern insulator), reproducing its topological
164
+ phase transition (Chern number 1 -> 0) and Berry-curvature map.
165
+
166
+ A spin-1/2 degree of freedom is added with `KSpace(lat, spin=True)`; onsite
167
+ values and hoppings then also accept 2x2 (Pauli) matrices:
168
+
169
+ ```python
170
+ from tbkit.kspace import KSpace, PAULI
171
+
172
+ kmele = KSpace(lat, spin=True)
173
+ kmele.set_hopping([{'i': 0, 'j': 0, 'R': (1, 0), 't': 1j*lam*PAULI['z']}]) # intrinsic SOC
174
+ ```
175
+
176
+ A ribbon -- periodic in one direction, finite in the other, the standard
177
+ way to see edge states -- is cut out of a periodic model with
178
+ `tbkit.kspace.ribbon`:
179
+
180
+ ```python
181
+ from tbkit.kspace import ribbon
182
+
183
+ rib = ribbon(lat, list_hop, width=30, direction=1) # 30 unit cells wide
184
+ fig = rib.plot_bands()
185
+ ```
186
+
187
+ See [`examples/topology/plot_edge_states.py`](examples/topology/plot_edge_states.py) for the zigzag
188
+ graphene ribbon's zero-energy edge band, and the Kane-Mele ribbon's helical
189
+ edge states crossing a spin-orbit gap.
190
+
191
+ ## Documentation
192
+
193
+ Rendered docs (tutorial, API reference, example gallery): https://cpoli.github.io/tbkit/
194
+
195
+ * [`docs/source/tutorial.rst`](docs/source/tutorial.rst) -- a narrative walkthrough of the
196
+ package, from building a lattice through topology, spin-orbit coupling,
197
+ and edge states.
198
+ * [`docs/source/history.rst`](docs/source/history.rst) -- a chronology of the breakthroughs
199
+ behind Tight-Binding theory (Bloch's theorem through the Kane-Mele model),
200
+ each one linked to the corresponding **tbkit** functionality and example
201
+ above.
202
+ * `docs/source/tbkit.rst` -- the API reference (auto-generated from docstrings).
203
+ * [`ROADMAP.md`](ROADMAP.md) -- what is planned next, and what tbkit
204
+ does not do yet (compared with Kwant and PythTB).
205
+
206
+ Build the HTML docs with `cd docs && make html` (output in `docs/build/html`).
207
+
208
+ ## A note on the API
209
+
210
+ Version 0.2 modernized the package to run on current Python/NumPy/SciPy and
211
+ cleaned up the API:
212
+
213
+ * Sublattice tags are plain one-character **strings** (`'a'`) rather than
214
+ byte strings (`b'a'`).
215
+ * Classes are named in `PascalCase` (`Lattice`, `System`, ...) rather than
216
+ lowercase names identical to their module (`lattice.lattice`,
217
+ `system.system`, ...), which used to make `import tbkit.lattice as lattice`
218
+ silently bind the wrong object.
219
+
220
+ For continuity, the pre-0.2 lowercase class names (`lattice`, `system`,
221
+ `plot`, `propagation`, `save`) remain available as aliases of the new
222
+ classes, so `from tbkit.lattice import lattice` still works.
223
+
224
+ ## License
225
+
226
+ BSD 3-Clause, see [LICENSE](LICENSE).
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tbkit"
7
- version = "0.4.2"
7
+ version = "0.5.0"
8
8
  description = "A Python package to build and solve Tight-Binding models."
9
9
  readme = "README.md"
10
10
  license = "BSD-3-Clause"
11
11
  authors = [{ name = "Charles Poli", email = "cpoli374@gmail.com" }]
12
- maintainers = [{ name = "cpoli", email = "cpoli374@gmail.com" }]
12
+ maintainers = [{ name = "Charles Poli", email = "cpoli374@gmail.com" }]
13
13
  requires-python = ">=3.10"
14
14
  dependencies = [
15
15
  "numpy>=1.24",
@@ -21,14 +21,16 @@ classifiers = [
21
21
  "Intended Audience :: Science/Research",
22
22
  "Topic :: Scientific/Engineering :: Physics",
23
23
  "Programming Language :: Python :: 3",
24
+ "Typing :: Typed",
24
25
  ]
25
26
 
26
27
  [project.urls]
27
28
  Homepage = "https://github.com/cpoli/tbkit"
28
29
 
29
30
  [project.optional-dependencies]
30
- test = ["pytest>=7", "pytest-cov>=4", "pytest-xdist>=3.2"]
31
- docs = ["sphinx>=7", "pydata-sphinx-theme>=0.15", "sphinx-gallery>=0.15"]
31
+ continuum = ["sympy>=1.12"]
32
+ test = ["pytest>=7", "pytest-cov>=4", "pytest-xdist>=3.2", "sympy>=1.12"]
33
+ docs = ["sphinx>=7", "pydata-sphinx-theme>=0.15", "sphinx-gallery>=0.15", "sympy>=1.12"]
32
34
 
33
35
  [tool.pytest.ini_options]
34
36
  # The suite is warning-free; keep it that way. A warning from tbkit itself is
@@ -40,8 +42,34 @@ filterwarnings = ["error"]
40
42
  # Pass -n0 to run a single test without the worker startup cost.
41
43
  addopts = "-n auto --dist worksteal"
42
44
 
45
+ [tool.ruff.lint]
46
+ # Pyflakes and the pycodestyle errors (ruff's classic defaults, named so a
47
+ # ruff upgrade does not change them), minus two that clash with the physics
48
+ # notation: `l` is the angular momentum or a length, and short local lambdas
49
+ # stand for formulas.
50
+ select = ["E4", "E7", "E9", "F"]
51
+ ignore = ["E741", "E731"]
52
+
53
+ [tool.ruff.lint.per-file-ignores]
54
+ # Imports grouped by feature, each followed by its `__all__` entry.
55
+ "tbkit/__init__.py" = ["E402", "F401"]
56
+ # `npc = np.char` has to sit between the imports.
57
+ "tbkit/system.py" = ["E402"]
58
+ # Pre-0.2 module built on star imports.
59
+ "tbkit/graphene.py" = ["F403", "F405"]
60
+
61
+ [tool.mypy]
62
+ python_version = "3.10"
63
+ ignore_missing_imports = true
64
+ # The type hints are documentation first: check what is annotated, and
65
+ # skip the bodies of unannotated functions.
66
+ check_untyped_defs = false
67
+
43
68
  [tool.setuptools.packages.find]
44
69
  include = ["tbkit*"]
45
70
 
71
+ [tool.setuptools.package-data]
72
+ tbkit = ["py.typed"]
73
+
46
74
  [tool.coverage.run]
47
75
  source = ["tbkit"]
@@ -6,7 +6,7 @@
6
6
 
7
7
  """tbkit: build and solve Tight-Binding models."""
8
8
 
9
- __version__ = "0.4.2"
9
+ __version__ = "0.5.0"
10
10
 
11
11
  __all__ = [
12
12
  "Lattice", "System", "Plot", "Propagation", "Save", "KSpace",
@@ -47,3 +47,15 @@ from tbkit.bdg import GapResult, s_wave_gap
47
47
  __all__ += ["NonCollinearResult", "hubbard_mean_field_noncollinear", "GapResult", "s_wave_gap"]
48
48
  from tbkit.transport import RecursiveTransport
49
49
  __all__ += ["RecursiveTransport"]
50
+ # Real-space and 3D topological diagnostics
51
+ from tbkit.topology import WeylPoints, find_weyl_points, bott_index
52
+ __all__ += ["WeylPoints", "find_weyl_points", "bott_index"]
53
+ # Analysis and plotting: standard k-paths
54
+ from tbkit.kspace import high_symmetry_path
55
+ __all__ += ["high_symmetry_path"]
56
+ # Continuum (k.p) models discretized on a grid; sympy is imported on first use
57
+ from tbkit.continuum import discretize, discretize_symbolic
58
+ __all__ += ["discretize", "discretize_symbolic"]
59
+ # Wannier functions: projection and maximal localization
60
+ from tbkit.wannier import WannierFunctions, wannierize
61
+ __all__ += ["WannierFunctions", "wannierize"]
@@ -163,6 +163,88 @@ def particle_hole(n: int) -> NDArray[np.float64]:
163
163
  return np.kron(np.array([[0., 1.], [1., 0.]]), np.eye(n))
164
164
 
165
165
 
166
+ def pfaffian(a) -> complex:
167
+ r'''
168
+ Get the Pfaffian of an antisymmetric matrix,
169
+ :math:`\mathrm{Pf}(A)^2 = \det A`, by the Parlett-Reid reduction to
170
+ tridiagonal form with pivoting (Wimmer, ACM Trans. Math. Softw. 38, 30
171
+ (2012)). For a 2x2 block :math:`\begin{pmatrix}0 & a\\ -a & 0\end{pmatrix}`
172
+ it is :math:`a`; it is 0 for an odd dimension.
173
+
174
+ :param a: Square antisymmetric matrix, shape (n, n).
175
+
176
+ :returns:
177
+ * **pf** -- Complex number (a float for a real matrix).
178
+ '''
179
+ real = not np.iscomplexobj(a)
180
+ a = np.array(a, dtype='c16')
181
+ error_handling.square_matrix(a, 'a')
182
+ error_handling.antisymmetric(a)
183
+ n = len(a)
184
+ if n % 2:
185
+ return 0.
186
+ pf = 1. + 0j
187
+ for k in range(0, n - 1, 2):
188
+ # bring the largest entry of column k below the diagonal to row k + 1
189
+ p = k + 1 + int(np.argmax(np.abs(a[k + 1:, k])))
190
+ if p != k + 1:
191
+ a[[k + 1, p], :] = a[[p, k + 1], :]
192
+ a[:, [k + 1, p]] = a[:, [p, k + 1]]
193
+ pf = -pf
194
+ if a[k + 1, k] == 0.:
195
+ return 0.
196
+ pf *= a[k, k + 1]
197
+ if k + 2 < n:
198
+ tau = a[k, k + 2:] / a[k, k + 1]
199
+ a[k + 2:, k + 2:] += np.outer(tau, a[k + 2:, k + 1]) - np.outer(a[k + 2:, k + 1], tau)
200
+ return float(pf.real) if real else complex(pf)
201
+
202
+
203
+ def majorana_number(ks) -> int:
204
+ r'''
205
+ Get Kitaev's Majorana number of a BdG model (Kitaev, Physics-Uspekhi
206
+ 44, 131 (2001)): the product, over the time-reversal-invariant momenta
207
+ :math:`\Gamma_i`, of the signs of the Pfaffians of the Hamiltonian in
208
+ the Majorana basis,
209
+
210
+ .. math::
211
+
212
+ \mathcal{M} = \prod_i \mathrm{sign}\,\mathrm{Pf}\,A(\Gamma_i)\, ,\qquad
213
+ A = -i\,U H_{BdG} U^\dagger\, ,\qquad
214
+ U = \frac{1}{\sqrt2}\begin{pmatrix}1 & 1\\ -i & i\end{pmatrix}\, ,
215
+
216
+ :math:`U` taking the Nambu spinor :math:`(c, c^\dagger)` to the Majorana
217
+ operators :math:`(c + c^\dagger, -i(c - c^\dagger))`. Particle-hole
218
+ symmetry makes :math:`A(\Gamma_i)` real and antisymmetric. In 1D,
219
+ :math:`\mathcal{M} = \mathrm{sign}\,\mathrm{Pf}A(0)\,\mathrm{Pf}A(\pi) = -1`
220
+ in the topological phase (a Majorana zero mode at each end of an open
221
+ chain), +1 in the trivial one: the :math:`\mathbb{Z}_2` invariant of
222
+ class D. In 2D the product over the four momenta is
223
+ :math:`(-1)^C`, the parity of the Chern number (Ghosh et al., Phys. Rev.
224
+ B 82, 184525 (2010)). The invariant changes only where the gap closes
225
+ at one of the :math:`\Gamma_i`.
226
+
227
+ :param ks: **KSpace** instance of a BdG model, 2n orbitals: n particles
228
+ then their n holes (see *bdg_kspace*).
229
+
230
+ :returns:
231
+ * **m** -- Integer, -1 (topological) or +1 (trivial).
232
+ '''
233
+ from tbkit.kspace import KSpace
234
+ error_handling.kspace(ks, KSpace)
235
+ error_handling.bdg_orbitals(ks.norb)
236
+ n = ks.norb // 2
237
+ u = np.kron(np.array([[1., 1.], [-1j, 1j]]) / np.sqrt(2), np.eye(n))
238
+ sign = 1
239
+ for k in ks._trims():
240
+ a = -1j * u @ ks.get_ham(k) @ u.conj().T
241
+ error_handling.majorana_form(a)
242
+ pf = pfaffian(a.real)
243
+ error_handling.gapped_trim(pf)
244
+ sign *= int(np.sign(pf))
245
+ return sign
246
+
247
+
166
248
  class GapResult():
167
249
  r'''
168
250
  Self-consistent s-wave pairing of *s_wave_gap*.