tbkit 0.4.0__tar.gz → 0.4.2__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 (72) hide show
  1. {tbkit-0.4.0/tbkit.egg-info → tbkit-0.4.2}/PKG-INFO +32 -9
  2. {tbkit-0.4.0 → tbkit-0.4.2}/README.md +31 -8
  3. {tbkit-0.4.0 → tbkit-0.4.2}/pyproject.toml +1 -1
  4. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/__init__.py +15 -1
  5. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/bdg.py +107 -0
  6. tbkit-0.4.2/tbkit/bridges.py +264 -0
  7. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/error_handling.py +601 -0
  8. tbkit-0.4.2/tbkit/higher_order.py +428 -0
  9. tbkit-0.4.2/tbkit/io.py +354 -0
  10. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/kspace.py +121 -2
  11. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/meanfield.py +132 -0
  12. tbkit-0.4.2/tbkit/moire.py +491 -0
  13. tbkit-0.4.2/tbkit/neighbours.py +245 -0
  14. tbkit-0.4.2/tbkit/optics.py +450 -0
  15. tbkit-0.4.2/tbkit/transport.py +717 -0
  16. {tbkit-0.4.0 → tbkit-0.4.2/tbkit.egg-info}/PKG-INFO +32 -9
  17. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit.egg-info/SOURCES.txt +18 -1
  18. tbkit-0.4.2/tests/test_bridges.py +258 -0
  19. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_error_handling.py +111 -0
  20. tbkit-0.4.2/tests/test_error_handling_structures.py +73 -0
  21. tbkit-0.4.2/tests/test_higher_order.py +215 -0
  22. tbkit-0.4.2/tests/test_interactions.py +179 -0
  23. tbkit-0.4.2/tests/test_io.py +144 -0
  24. tbkit-0.4.2/tests/test_moire.py +262 -0
  25. tbkit-0.4.2/tests/test_neighbours.py +233 -0
  26. tbkit-0.4.2/tests/test_optics.py +335 -0
  27. tbkit-0.4.2/tests/test_surface_spectral.py +182 -0
  28. tbkit-0.4.2/tests/test_transport_response.py +257 -0
  29. tbkit-0.4.2/tests/test_wannier90.py +180 -0
  30. tbkit-0.4.0/tbkit/transport.py +0 -225
  31. {tbkit-0.4.0 → tbkit-0.4.2}/LICENSE +0 -0
  32. {tbkit-0.4.0 → tbkit-0.4.2}/setup.cfg +0 -0
  33. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/dos.py +0 -0
  34. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/exceptional.py +0 -0
  35. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/floquet.py +0 -0
  36. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/graphene.py +0 -0
  37. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/kpm.py +0 -0
  38. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/lattice.py +0 -0
  39. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/lattices.py +0 -0
  40. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/occupation.py +0 -0
  41. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/orbital.py +0 -0
  42. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/plot.py +0 -0
  43. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/propagation.py +0 -0
  44. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/save.py +0 -0
  45. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/slater_koster.py +0 -0
  46. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit/system.py +0 -0
  47. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit.egg-info/dependency_links.txt +0 -0
  48. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit.egg-info/requires.txt +0 -0
  49. {tbkit-0.4.0 → tbkit-0.4.2}/tbkit.egg-info/top_level.txt +0 -0
  50. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_correlations.py +0 -0
  51. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_dos.py +0 -0
  52. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_exceptional.py +0 -0
  53. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_floquet.py +0 -0
  54. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_graphene.py +0 -0
  55. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_green_occupation.py +0 -0
  56. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_hall.py +0 -0
  57. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_kpm.py +0 -0
  58. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_kspace.py +0 -0
  59. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_large_lattices.py +0 -0
  60. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_lattice.py +0 -0
  61. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_lattices.py +0 -0
  62. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_magnetic.py +0 -0
  63. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_non_hermitian_bands.py +0 -0
  64. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_orbitals.py +0 -0
  65. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_plot.py +0 -0
  66. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_propagation.py +0 -0
  67. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_regressions.py +0 -0
  68. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_save.py +0 -0
  69. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_system.py +0 -0
  70. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_three_d.py +0 -0
  71. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_topology.py +0 -0
  72. {tbkit-0.4.0 → tbkit-0.4.2}/tests/test_transport.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tbkit
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: A Python package to build and solve Tight-Binding models.
5
5
  Author-email: Charles Poli <cpoli374@gmail.com>
6
6
  Maintainer-email: cpoli <cpoli374@gmail.com>
@@ -97,6 +97,9 @@ topology alongside superconductivity.
97
97
  Kane-Mele) and Zeeman splitting.
98
98
  * **Edge states**: cut a ribbon (periodic in one direction, finite in the
99
99
  other) out of any periodic model, to see edge/surface physics.
100
+ * **Surface spectral functions** of semi-infinite crystals (iterative
101
+ surface Green's function): edge and surface states, e.g. the surface
102
+ Dirac cone of a 3D topological insulator, without a finite slab.
100
103
  * **Density of states**, Gaussian- or Lorentzian-broadened, from either a
101
104
  real-space spectrum or a Brillouin-zone mesh.
102
105
  * A small library of ready-made lattices (chain, square, triangular,
@@ -116,7 +119,7 @@ topology alongside superconductivity.
116
119
  |----------------------------|---------------------------------------------------------|
117
120
  | `tbkit.Lattice` | Define and manipulate site positions and sublattices. |
118
121
  | `tbkit.System` | Build the real-space Hamiltonian from a `Lattice` and solve it. |
119
- | `tbkit.KSpace` | Build and solve the Bloch Hamiltonian of a periodic `Lattice`; bands, Berry curvature/Chern numbers, anomalous and spin Hall conductivities, ribbons, DOS. |
122
+ | `tbkit.KSpace` | Build and solve the Bloch Hamiltonian of a periodic `Lattice`; bands, Berry curvature/Chern numbers, anomalous and spin Hall conductivities, ribbons, surface spectral functions, DOS. |
120
123
  | `tbkit.Plot` | Plot lattices, spectra, eigenstates, and the density of states. |
121
124
  | `tbkit.Propagation` | Time-evolve a wavepacket. |
122
125
  | `tbkit.Save` | Save figures/animations to disk. |
@@ -130,7 +133,12 @@ topology alongside superconductivity.
130
133
  | `tbkit.meanfield` | The Hubbard model in (unrestricted Hartree-Fock) mean field. |
131
134
  | `tbkit.bdg` | Bogoliubov-de Gennes Hamiltonians and pairings. |
132
135
  | `tbkit.exceptional` | Exceptional and diabolical points of 2D bands: vorticity, discriminant winding, EP finder, Fermi arcs, encircling. |
136
+ | `tbkit.higher_order` | Higher-order topology: nested Wilson loops, Wannier-sector polarizations, the BBH quadrupole moment, corner charges. |
137
+ | `tbkit.moire` | Supercells, band unfolding and spectral functions, commensurate twisted bilayers. |
133
138
  | `tbkit.floquet` | Floquet theory; `FloquetKSpace`/`DrivenKSpace` for driven Bloch models, `step_drive`, and the winding number of anomalous Floquet phases. |
139
+ | `tbkit.neighbours` | Neighbour shells of a periodic lattice; `KSpace.set_hopping` by neighbour order, angle and sublattice pair, as in `System`. |
140
+ | `tbkit.bridges` | Move a model between `System` and `KSpace` (open samples and tori). |
141
+ | `tbkit.io` | Save and load `Lattice`/`System`/`KSpace` models (`.npz`); import Wannier90 `_hr.dat` models. |
134
142
 
135
143
  ## Install
136
144
 
@@ -287,6 +295,7 @@ thumbnailed example gallery under `docs/source/api/gallery/`.
287
295
  | [`topology/plot_tknn_hofstadter.py`](examples/topology/plot_tknn_hofstadter.py) | TKNN: Chern numbers of the Hofstadter bands from magnetic supercells, and the Diophantine equation. |
288
296
  | [`topology/plot_kane_mele_z2.py`](examples/topology/plot_kane_mele_z2.py) | The Kane-Mele Z2 invariant from Wannier-centre flow. |
289
297
  | [`topology/plot_fu_kane_parity.py`](examples/topology/plot_fu_kane_parity.py) | The Fu-Kane parity criterion on the BHZ model, checked against the Wannier flow. |
298
+ | [`topology/plot_3d_topological_insulator.py`](examples/topology/plot_3d_topological_insulator.py) | 3D topological insulators: the strong index and the surface Dirac cone, from the surface spectral function of a semi-infinite crystal. |
290
299
  | [`topology/plot_quantum_geometry.py`](examples/topology/plot_quantum_geometry.py) | The quantum metric and Berry curvature of a Bloch band. |
291
300
  | [`topology/plot_tenfold_way.py`](examples/topology/plot_tenfold_way.py) | Symmetry classes of tight-binding models: the tenfold way. |
292
301
  | [`topology/plot_local_chern_marker.py`](examples/topology/plot_local_chern_marker.py) | The local Chern marker of a finite, disordered Haldane flake. |
@@ -309,10 +318,24 @@ thumbnailed example gallery under `docs/source/api/gallery/`.
309
318
  | [`hall_effects/plot_anomalous_hall_effect.py`](examples/hall_effects/plot_anomalous_hall_effect.py) | The anomalous Hall effect: sigma_xy(E_F) of the Haldane model, quantized at C in the gap, not in the bands. |
310
319
  | [`hall_effects/plot_anomalous_hall_disorder.py`](examples/hall_effects/plot_anomalous_hall_disorder.py) | The anomalous Hall plateau of a disordered Haldane torus, by the Kubo-Bastin kernel polynomial method. |
311
320
  | [`hall_effects/plot_intrinsic_spin_hall_effect.py`](examples/hall_effects/plot_intrinsic_spin_hall_effect.py) | The intrinsic spin Hall effect: the Kane-Mele plateau at e/2pi, and its departure from quantization under Rashba coupling. |
312
-
313
- The `examples/` directory also has five older Jupyter notebooks (graphene
314
- flakes, kagome/Lieb/dumbbell lattices, disorder, strain, time propagation)
315
- predating the 0.2 API refresh below.
321
+ | [`models/plot_neighbour_hoppings.py`](examples/models/plot_neighbour_hoppings.py) | Hoppings by neighbour order in k-space: third-nearest-neighbour graphene with overlaps. |
322
+ | [`models/plot_pipeline_bridges.py`](examples/models/plot_pipeline_bridges.py) | From real space to k-space and back: the Haldane model's torus spectrum equals its mesh bands. |
323
+ | [`models/plot_save_load.py`](examples/models/plot_save_load.py) | Saving and reloading models: identical Hamiltonians after a round trip through disk. |
324
+ | [`models/plot_maximally_localized_wannier_functions.py`](examples/models/plot_maximally_localized_wannier_functions.py) | Maximally localized Wannier functions: graphene's pi bands from a Wannier90 `_hr.dat` file. |
325
+ | [`higher_order/plot_quadrupole_insulator.py`](examples/higher_order/plot_quadrupole_insulator.py) | The BBH quadrupole insulator: nested Wilson loop, q_xy = 1/2, four corner states and corner charges +-1/2. |
326
+ | [`moire/plot_band_unfolding.py`](examples/moire/plot_band_unfolding.py) | Band unfolding: exact for a pristine supercell, coherence factors, and A(k, omega) of a disordered graphene supercell. |
327
+ | [`moire/plot_magic_angle_twisted_bilayer.py`](examples/moire/plot_magic_angle_twisted_bilayer.py) | Twisted bilayer graphene: Bistritzer-MacDonald velocity and flat bands at the magic alpha. |
328
+ | [`superconductivity/plot_bcs_gap_equation.py`](examples/superconductivity/plot_bcs_gap_equation.py) | The real-space BCS gap equation: Delta(T), Delta(0)/T_c = 1.764, and the proximity effect. |
329
+ | [`correlations/plot_noncollinear_120_degree_order.py`](examples/correlations/plot_noncollinear_120_degree_order.py) | Non-collinear mean field: the 120-degree order of the half-filled triangular Hubbard model. |
330
+ | [`tight_binding/plot_building_finite_lattices.py`](examples/tight_binding/plot_building_finite_lattices.py) | Building finite lattices: cuts, dangling sites, lattice arithmetic, rotations. |
331
+ | [`tight_binding/plot_defects_and_impurities.py`](examples/tight_binding/plot_defects_and_impurities.py) | A vacancy zero mode and an impurity bound state in a graphene flake. |
332
+ | [`dynamics/plot_wavepacket_interference.py`](examples/dynamics/plot_wavepacket_interference.py) | Wave propagation: Aharonov-Bohm caging on a ring and a state trapped at a domain wall. |
333
+
334
+ The five pre-0.2 Jupyter notebooks were replaced by the gallery scripts
335
+ `tight_binding/plot_building_finite_lattices.py`,
336
+ `tight_binding/plot_defects_and_impurities.py` and
337
+ `dynamics/plot_wavepacket_interference.py` (their other content is covered
338
+ by the strain, correlations and non-Hermitian examples).
316
339
 
317
340
  ## Documentation
318
341
 
@@ -326,6 +349,8 @@ Rendered docs (tutorial, API reference, example gallery): https://cpoli.github.i
326
349
  each one linked to the corresponding **tbkit** functionality and example
327
350
  above.
328
351
  * `docs/source/tbkit.rst` -- the API reference (auto-generated from docstrings).
352
+ * [`ROADMAP.md`](ROADMAP.md) -- what is planned next, and what tbkit
353
+ does not do yet (compared with Kwant and PythTB).
329
354
 
330
355
  Build the HTML docs with `cd docs && make html` (output in `docs/build/html`).
331
356
 
@@ -343,9 +368,7 @@ cleaned up the API:
343
368
 
344
369
  For continuity, the pre-0.2 lowercase class names (`lattice`, `system`,
345
370
  `plot`, `propagation`, `save`) remain available as aliases of the new
346
- classes, so `from tbkit.lattice import lattice` still works. Example
347
- notebooks predating 0.2 still use byte-string tags (`b'a'`) and will need
348
- that one mechanical change to run on the current version.
371
+ classes, so `from tbkit.lattice import lattice` still works.
349
372
 
350
373
  ## License
351
374
 
@@ -69,6 +69,9 @@ topology alongside superconductivity.
69
69
  Kane-Mele) and Zeeman splitting.
70
70
  * **Edge states**: cut a ribbon (periodic in one direction, finite in the
71
71
  other) out of any periodic model, to see edge/surface physics.
72
+ * **Surface spectral functions** of semi-infinite crystals (iterative
73
+ surface Green's function): edge and surface states, e.g. the surface
74
+ Dirac cone of a 3D topological insulator, without a finite slab.
72
75
  * **Density of states**, Gaussian- or Lorentzian-broadened, from either a
73
76
  real-space spectrum or a Brillouin-zone mesh.
74
77
  * A small library of ready-made lattices (chain, square, triangular,
@@ -88,7 +91,7 @@ topology alongside superconductivity.
88
91
  |----------------------------|---------------------------------------------------------|
89
92
  | `tbkit.Lattice` | Define and manipulate site positions and sublattices. |
90
93
  | `tbkit.System` | Build the real-space Hamiltonian from a `Lattice` and solve it. |
91
- | `tbkit.KSpace` | Build and solve the Bloch Hamiltonian of a periodic `Lattice`; bands, Berry curvature/Chern numbers, anomalous and spin Hall conductivities, ribbons, DOS. |
94
+ | `tbkit.KSpace` | Build and solve the Bloch Hamiltonian of a periodic `Lattice`; bands, Berry curvature/Chern numbers, anomalous and spin Hall conductivities, ribbons, surface spectral functions, DOS. |
92
95
  | `tbkit.Plot` | Plot lattices, spectra, eigenstates, and the density of states. |
93
96
  | `tbkit.Propagation` | Time-evolve a wavepacket. |
94
97
  | `tbkit.Save` | Save figures/animations to disk. |
@@ -102,7 +105,12 @@ topology alongside superconductivity.
102
105
  | `tbkit.meanfield` | The Hubbard model in (unrestricted Hartree-Fock) mean field. |
103
106
  | `tbkit.bdg` | Bogoliubov-de Gennes Hamiltonians and pairings. |
104
107
  | `tbkit.exceptional` | Exceptional and diabolical points of 2D bands: vorticity, discriminant winding, EP finder, Fermi arcs, encircling. |
108
+ | `tbkit.higher_order` | Higher-order topology: nested Wilson loops, Wannier-sector polarizations, the BBH quadrupole moment, corner charges. |
109
+ | `tbkit.moire` | Supercells, band unfolding and spectral functions, commensurate twisted bilayers. |
105
110
  | `tbkit.floquet` | Floquet theory; `FloquetKSpace`/`DrivenKSpace` for driven Bloch models, `step_drive`, and the winding number of anomalous Floquet phases. |
111
+ | `tbkit.neighbours` | Neighbour shells of a periodic lattice; `KSpace.set_hopping` by neighbour order, angle and sublattice pair, as in `System`. |
112
+ | `tbkit.bridges` | Move a model between `System` and `KSpace` (open samples and tori). |
113
+ | `tbkit.io` | Save and load `Lattice`/`System`/`KSpace` models (`.npz`); import Wannier90 `_hr.dat` models. |
106
114
 
107
115
  ## Install
108
116
 
@@ -259,6 +267,7 @@ thumbnailed example gallery under `docs/source/api/gallery/`.
259
267
  | [`topology/plot_tknn_hofstadter.py`](examples/topology/plot_tknn_hofstadter.py) | TKNN: Chern numbers of the Hofstadter bands from magnetic supercells, and the Diophantine equation. |
260
268
  | [`topology/plot_kane_mele_z2.py`](examples/topology/plot_kane_mele_z2.py) | The Kane-Mele Z2 invariant from Wannier-centre flow. |
261
269
  | [`topology/plot_fu_kane_parity.py`](examples/topology/plot_fu_kane_parity.py) | The Fu-Kane parity criterion on the BHZ model, checked against the Wannier flow. |
270
+ | [`topology/plot_3d_topological_insulator.py`](examples/topology/plot_3d_topological_insulator.py) | 3D topological insulators: the strong index and the surface Dirac cone, from the surface spectral function of a semi-infinite crystal. |
262
271
  | [`topology/plot_quantum_geometry.py`](examples/topology/plot_quantum_geometry.py) | The quantum metric and Berry curvature of a Bloch band. |
263
272
  | [`topology/plot_tenfold_way.py`](examples/topology/plot_tenfold_way.py) | Symmetry classes of tight-binding models: the tenfold way. |
264
273
  | [`topology/plot_local_chern_marker.py`](examples/topology/plot_local_chern_marker.py) | The local Chern marker of a finite, disordered Haldane flake. |
@@ -281,10 +290,24 @@ thumbnailed example gallery under `docs/source/api/gallery/`.
281
290
  | [`hall_effects/plot_anomalous_hall_effect.py`](examples/hall_effects/plot_anomalous_hall_effect.py) | The anomalous Hall effect: sigma_xy(E_F) of the Haldane model, quantized at C in the gap, not in the bands. |
282
291
  | [`hall_effects/plot_anomalous_hall_disorder.py`](examples/hall_effects/plot_anomalous_hall_disorder.py) | The anomalous Hall plateau of a disordered Haldane torus, by the Kubo-Bastin kernel polynomial method. |
283
292
  | [`hall_effects/plot_intrinsic_spin_hall_effect.py`](examples/hall_effects/plot_intrinsic_spin_hall_effect.py) | The intrinsic spin Hall effect: the Kane-Mele plateau at e/2pi, and its departure from quantization under Rashba coupling. |
284
-
285
- The `examples/` directory also has five older Jupyter notebooks (graphene
286
- flakes, kagome/Lieb/dumbbell lattices, disorder, strain, time propagation)
287
- predating the 0.2 API refresh below.
293
+ | [`models/plot_neighbour_hoppings.py`](examples/models/plot_neighbour_hoppings.py) | Hoppings by neighbour order in k-space: third-nearest-neighbour graphene with overlaps. |
294
+ | [`models/plot_pipeline_bridges.py`](examples/models/plot_pipeline_bridges.py) | From real space to k-space and back: the Haldane model's torus spectrum equals its mesh bands. |
295
+ | [`models/plot_save_load.py`](examples/models/plot_save_load.py) | Saving and reloading models: identical Hamiltonians after a round trip through disk. |
296
+ | [`models/plot_maximally_localized_wannier_functions.py`](examples/models/plot_maximally_localized_wannier_functions.py) | Maximally localized Wannier functions: graphene's pi bands from a Wannier90 `_hr.dat` file. |
297
+ | [`higher_order/plot_quadrupole_insulator.py`](examples/higher_order/plot_quadrupole_insulator.py) | The BBH quadrupole insulator: nested Wilson loop, q_xy = 1/2, four corner states and corner charges +-1/2. |
298
+ | [`moire/plot_band_unfolding.py`](examples/moire/plot_band_unfolding.py) | Band unfolding: exact for a pristine supercell, coherence factors, and A(k, omega) of a disordered graphene supercell. |
299
+ | [`moire/plot_magic_angle_twisted_bilayer.py`](examples/moire/plot_magic_angle_twisted_bilayer.py) | Twisted bilayer graphene: Bistritzer-MacDonald velocity and flat bands at the magic alpha. |
300
+ | [`superconductivity/plot_bcs_gap_equation.py`](examples/superconductivity/plot_bcs_gap_equation.py) | The real-space BCS gap equation: Delta(T), Delta(0)/T_c = 1.764, and the proximity effect. |
301
+ | [`correlations/plot_noncollinear_120_degree_order.py`](examples/correlations/plot_noncollinear_120_degree_order.py) | Non-collinear mean field: the 120-degree order of the half-filled triangular Hubbard model. |
302
+ | [`tight_binding/plot_building_finite_lattices.py`](examples/tight_binding/plot_building_finite_lattices.py) | Building finite lattices: cuts, dangling sites, lattice arithmetic, rotations. |
303
+ | [`tight_binding/plot_defects_and_impurities.py`](examples/tight_binding/plot_defects_and_impurities.py) | A vacancy zero mode and an impurity bound state in a graphene flake. |
304
+ | [`dynamics/plot_wavepacket_interference.py`](examples/dynamics/plot_wavepacket_interference.py) | Wave propagation: Aharonov-Bohm caging on a ring and a state trapped at a domain wall. |
305
+
306
+ The five pre-0.2 Jupyter notebooks were replaced by the gallery scripts
307
+ `tight_binding/plot_building_finite_lattices.py`,
308
+ `tight_binding/plot_defects_and_impurities.py` and
309
+ `dynamics/plot_wavepacket_interference.py` (their other content is covered
310
+ by the strain, correlations and non-Hermitian examples).
288
311
 
289
312
  ## Documentation
290
313
 
@@ -298,6 +321,8 @@ Rendered docs (tutorial, API reference, example gallery): https://cpoli.github.i
298
321
  each one linked to the corresponding **tbkit** functionality and example
299
322
  above.
300
323
  * `docs/source/tbkit.rst` -- the API reference (auto-generated from docstrings).
324
+ * [`ROADMAP.md`](ROADMAP.md) -- what is planned next, and what tbkit
325
+ does not do yet (compared with Kwant and PythTB).
301
326
 
302
327
  Build the HTML docs with `cd docs && make html` (output in `docs/build/html`).
303
328
 
@@ -315,9 +340,7 @@ cleaned up the API:
315
340
 
316
341
  For continuity, the pre-0.2 lowercase class names (`lattice`, `system`,
317
342
  `plot`, `propagation`, `save`) remain available as aliases of the new
318
- classes, so `from tbkit.lattice import lattice` still works. Example
319
- notebooks predating 0.2 still use byte-string tags (`b'a'`) and will need
320
- that one mechanical change to run on the current version.
343
+ classes, so `from tbkit.lattice import lattice` still works.
321
344
 
322
345
  ## License
323
346
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tbkit"
7
- version = "0.4.0"
7
+ version = "0.4.2"
8
8
  description = "A Python package to build and solve Tight-Binding models."
9
9
  readme = "README.md"
10
10
  license = "BSD-3-Clause"
@@ -6,7 +6,7 @@
6
6
 
7
7
  """tbkit: build and solve Tight-Binding models."""
8
8
 
9
- __version__ = "0.4.0"
9
+ __version__ = "0.4.2"
10
10
 
11
11
  __all__ = [
12
12
  "Lattice", "System", "Plot", "Propagation", "Save", "KSpace",
@@ -33,3 +33,17 @@ from tbkit.floquet import FloquetKSpace, DrivenKSpace, StepDrive, step_drive
33
33
  from tbkit.meanfield import MeanFieldResult, hubbard_mean_field
34
34
  from tbkit.exceptional import ExceptionalPoints, Encircling, find_exceptional_points
35
35
  import tbkit.error_handling
36
+ # Model I/O (tbkit.io): appended here to keep the list above untouched.
37
+ from tbkit.io import save_model, load_model, read_wannier90
38
+ __all__ += ["save_model", "load_model", "read_wannier90"]
39
+
40
+ # Higher-order topology, moire supercells, self-consistent interactions
41
+ from tbkit.higher_order import CornerCharges, quadrupole_moment, corner_charges
42
+ __all__ += ["CornerCharges", "quadrupole_moment", "corner_charges"]
43
+ from tbkit.moire import SupercellKSpace, MoireKSpace, supercell, twisted_bilayer
44
+ __all__ += ["SupercellKSpace", "MoireKSpace", "supercell", "twisted_bilayer"]
45
+ from tbkit.meanfield import NonCollinearResult, hubbard_mean_field_noncollinear
46
+ from tbkit.bdg import GapResult, s_wave_gap
47
+ __all__ += ["NonCollinearResult", "hubbard_mean_field_noncollinear", "GapResult", "s_wave_gap"]
48
+ from tbkit.transport import RecursiveTransport
49
+ __all__ += ["RecursiveTransport"]
@@ -161,3 +161,110 @@ def particle_hole(n: int) -> NDArray[np.float64]:
161
161
  '''
162
162
  error_handling.positive_int(n, 'n')
163
163
  return np.kron(np.array([[0., 1.], [1., 0.]]), np.eye(n))
164
+
165
+
166
+ class GapResult():
167
+ r'''
168
+ Self-consistent s-wave pairing of *s_wave_gap*.
169
+
170
+ :ivar delta: Complex ndarray. Gap :math:`\Delta_i` on every site.
171
+ :ivar energies: Real ndarray, shape (2N,). Spectrum of the reduced BdG
172
+ Hamiltonian (symmetric, :math:`\pm E_n`).
173
+ :ivar states: Complex ndarray, shape (2N, 2N). Its eigenvectors
174
+ :math:`(u_n, v_n)` (columns).
175
+ :ivar iterations: Integer. Number of iterations.
176
+ '''
177
+
178
+ def __init__(self, delta, energies, states, iterations) -> None:
179
+ self.delta = delta
180
+ self.energies = energies
181
+ self.states = states
182
+ self.iterations = iterations
183
+
184
+ @property
185
+ def mean_gap(self) -> float:
186
+ r'''
187
+ Average :math:`|\Delta_i|` over the sites.
188
+ '''
189
+ return float(np.mean(np.abs(self.delta)))
190
+
191
+
192
+ def s_wave_gap(
193
+ ham, V: float | NDArray, mu: float = 0., temperature: float = 0., delta0: complex | NDArray = 0.1,
194
+ mixing: float = 1., tol: float = 1e-8, max_iter: int = 10000,
195
+ ) -> GapResult:
196
+ r'''
197
+ Solve the real-space gap equation of an s-wave superconductor
198
+ self-consistently (the attractive Hubbard model
199
+ :math:`-\sum_iV_in_{i\uparrow}n_{i\downarrow}` in the BCS mean-field
200
+ approximation, de Gennes 1966). For a spin-independent *ham* the singlet
201
+ BdG Hamiltonian reduces to the Nambu basis
202
+ :math:`(c_{i\uparrow}, c^\dagger_{i\downarrow})`,
203
+
204
+ .. math::
205
+
206
+ H = \begin{pmatrix} h-\mu & \Delta\\ \Delta^* & -(h-\mu)^*\end{pmatrix}\, ,
207
+ \qquad \Delta = \mathrm{diag}(\Delta_i)\, ,
208
+
209
+ whose eigenvectors :math:`(u_n, v_n)`, :math:`E_n > 0`, give the gap
210
+ equation
211
+
212
+ .. math::
213
+
214
+ \Delta_i = V_i\,\langle c_{i\downarrow}c_{i\uparrow}\rangle
215
+ = V_i\sum_{E_n>0}u_n(i)\,v_n^*(i)\tanh\frac{E_n}{2T}\, ,
216
+
217
+ iterated (with linear mixing) until self-consistent. On a clean lattice
218
+ it is the BCS gap equation :math:`1 = \frac{V}{N}\sum_{\mathbf{k}}
219
+ \tanh(E_{\mathbf{k}}/2T)/2E_{\mathbf{k}}`, with
220
+ :math:`\Delta(T_c) = 0` at :math:`T_c \approx \Delta(0)/1.764` at weak
221
+ coupling. The chemical potential is fixed (the Hartree shift
222
+ :math:`-V_in_i/2` is left out, i.e. absorbed in :math:`\mu`). Near
223
+ :math:`T_c` the iteration slows down (the linearized map has an
224
+ eigenvalue close to 1): raise *max_iter* there.
225
+
226
+ :param ham: Square Hermitian matrix, (N, N), spin independent (e.g. *System.ham*).
227
+ :param V: Positive real, or array of N non-negative reals. Attraction.
228
+ :param mu: Real number. Default value 0. Chemical potential.
229
+ :param temperature: Positive real or zero. Default value 0.
230
+ :param delta0: Number, or array of N numbers. Default value 0.1.
231
+ Initial gap.
232
+ :param mixing: Real in (0, 1]. Default value 1 (plain iteration).
233
+ :param tol: Positive real. Default value 1e-8. Convergence threshold
234
+ on the largest change of :math:`\Delta_i`.
235
+ :param max_iter: Positive integer. Default value 10000.
236
+
237
+ :returns:
238
+ * **result** -- :class:`GapResult`.
239
+ '''
240
+ h = ham.toarray() if hasattr(ham, 'toarray') else np.asarray(ham)
241
+ error_handling.square_matrix(h, 'ham')
242
+ error_handling.hermitian_dense(h)
243
+ n = len(h)
244
+ error_handling.interaction(V, n)
245
+ error_handling.real_number(mu, 'mu')
246
+ error_handling.positive_real_zero(temperature, 'temperature')
247
+ error_handling.pairing_amplitudes(delta0, n)
248
+ error_handling.mixing(mixing)
249
+ error_handling.positive_real(tol, 'tol')
250
+ error_handling.positive_int(max_iter, 'max_iter')
251
+ V = np.broadcast_to(np.asarray(V, dtype='f8'), (n,))
252
+ delta = np.broadcast_to(np.asarray(delta0, dtype='c16'), (n,)).copy()
253
+ xi = h.astype('c16') - mu * np.eye(n)
254
+ big = np.zeros((2 * n, 2 * n), 'c16')
255
+ big[:n, :n], big[n:, n:] = xi, -xi.conj()
256
+ diag = np.arange(n)
257
+ for it in range(1, max_iter + 1):
258
+ big[diag, diag + n] = delta
259
+ big[diag + n, diag] = delta.conj()
260
+ en, vec = np.linalg.eigh(big)
261
+ pos = en > 0
262
+ weight = np.tanh(en[pos] / (2 * temperature)) if temperature > 0 else np.ones(pos.sum())
263
+ new = V * np.einsum('in,in,n->i', vec[:n, pos], vec[n:, pos].conj(), weight)
264
+ change = np.max(np.abs(new - delta))
265
+ delta = (1 - mixing) * delta + mixing * new
266
+ if change < tol:
267
+ break
268
+ else:
269
+ error_handling.converged(False, 's_wave_gap')
270
+ return GapResult(new, en, vec, it)
@@ -0,0 +1,264 @@
1
+ r'''
2
+ Bridges between the two pipelines of tbkit: the real-space *System* (a
3
+ finite lattice, its sparse Hamiltonian) and the reciprocal-space *KSpace*
4
+ (the Bloch Hamiltonian :math:`H(\mathbf{k})` of the infinite lattice).
5
+
6
+ * *kspace_from_system* reads the Bloch model off a translation-invariant
7
+ *System* built the real-space way (*get_lattice*, *set_hopping* by
8
+ neighbour order, *set_onsite*, ...).
9
+ * *finite_model* and *finite_system* cut a finite sample (open boundaries,
10
+ or a torus) out of a *KSpace* model: its sparse Hamiltonian with the site
11
+ positions, or a ready-to-use *System*.
12
+
13
+ Both use the convention of *KSpace.finite_ham*: the hopping
14
+ :math:`t_{ij}(\mathbf{R}) = \langle i,\mathbf{0}|H|j,\mathbf{R}\rangle`
15
+ joins orbital *i* of every cell to orbital *j* of the cell :math:`\mathbf{R}`
16
+ further. So, for the same model, the spectrum of a System on an
17
+ :math:`N_1\times N_2` torus is the set of KSpace bands on the
18
+ :math:`N_1\times N_2` Brillouin-zone mesh.
19
+ '''
20
+ from __future__ import annotations
21
+
22
+ import numpy as np
23
+ from numpy.typing import NDArray
24
+ import scipy.sparse as sp
25
+
26
+ import tbkit.error_handling as error_handling
27
+ import tbkit.neighbours as neighbours
28
+ from tbkit.kspace import KSpace
29
+ from tbkit.lattice import Lattice
30
+ from tbkit.orbital import OrbitalSystem
31
+ from tbkit.system import System, HOP_DTYPE, ATOL, _upper
32
+
33
+
34
+ def _coords(lat: Lattice) -> NDArray[np.float64]:
35
+ '''
36
+ Private function. Site coordinates of a finite lattice, shape (sites, space_dim).
37
+ '''
38
+ return np.stack([lat.coor[f] for f in ('x', 'y', 'z')[:lat.space_dim]], axis=1)
39
+
40
+
41
+ def cell_orbitals(lat: Lattice) -> tuple[NDArray[np.int64], NDArray[np.int64]]:
42
+ r'''
43
+ Get, for every site of a finite lattice (*lat.coor*), the unit-cell
44
+ orbital it is a copy of and its cell: site *s* sits at
45
+ :math:`\boldsymbol\tau_{o_s} + \sum_k n_{s,k}\mathbf{a}_k`, with the tag
46
+ of orbital :math:`o_s` (within ``ATOL``).
47
+
48
+ :param lat: **Lattice** instance, after *get_lattice* (sites may have
49
+ been removed, but not moved).
50
+
51
+ :returns:
52
+ * **cells** -- Integer ndarray, shape (sites, dim). :math:`n_{s,k}`.
53
+ * **orbitals** -- Integer ndarray, shape (sites,). :math:`o_s`.
54
+ '''
55
+ error_handling.lat(lat)
56
+ error_handling.empty_coor(lat.coor)
57
+ a, tau, tags = neighbours._geometry(lat)
58
+ pos = _coords(lat)
59
+ pinv = np.linalg.pinv(a)
60
+ match = np.zeros((lat.sites, len(tau)), bool)
61
+ cells = np.zeros((lat.sites, len(tau), len(a)), int)
62
+ for o in range(len(tau)):
63
+ rel = pos - tau[o]
64
+ n = np.rint(rel @ pinv).astype(int)
65
+ match[:, o] = (np.linalg.norm(n @ a - rel, axis=1) < ATOL) & (lat.coor['tag'] == tags[o])
66
+ cells[:, o] = n
67
+ error_handling.lattice_sites(match.sum(axis=1))
68
+ orb = np.argmax(match, axis=1)
69
+ return cells[np.arange(lat.sites), orb], orb
70
+
71
+
72
+ def kspace_from_system(sys: System, periodic: bool = False, tol: float = 1e-9) -> KSpace:
73
+ r'''
74
+ Get the Bloch Hamiltonian of a periodic model defined the real-space
75
+ way: every matrix element :math:`H_{ab}` of the finite *System* (built
76
+ by *get_ham*) joins orbital :math:`o_a` of cell :math:`\mathbf{n}_a` to
77
+ orbital :math:`o_b` of cell :math:`\mathbf{n}_b` (see *cell_orbitals*),
78
+ i.e. is the hopping :math:`t_{o_ao_b}(\mathbf{n}_b-\mathbf{n}_a)` of the
79
+ infinite lattice. Each such hopping must take the same value in every
80
+ cell where it appears (bonds cut by the boundary are simply missing).
81
+ The lattice must be large enough to hold every bond of the model.
82
+
83
+ A System on a torus (*periodic*, e.g. from *finite_system*) has bonds
84
+ that wrap around: their lattice vectors are then taken modulo the
85
+ :math:`N_1\times N_2\times\dots` cells of *get_lattice*, as the shortest
86
+ image (so the model's range must stay below half the torus).
87
+
88
+ A Hermitian hopping matrix gives a Hermitian model (one representative
89
+ per bond, *set_hopping* adding the conjugate); otherwise every matrix
90
+ element is kept, with ``hermitian=False``. Onsite energies are taken
91
+ orbital by orbital.
92
+
93
+ :param sys: **System** instance with its hoppings set (one orbital per site).
94
+ :param periodic: Boolean. Default value False. The System is a torus
95
+ of the *lat.n1* x *lat.n2* (x *lat.n3*) cells of *get_lattice*.
96
+ :param tol: Positive real number. Default value 1e-9. Largest allowed
97
+ difference between equivalent matrix elements.
98
+
99
+ :returns:
100
+ * **ks** -- **KSpace** instance (spinless), on a new **Lattice**
101
+ with the *unit_cell* and *prim_vec* of *sys.lat*.
102
+
103
+ Example usage::
104
+
105
+ lat = lattices.honeycomb()
106
+ lat.get_lattice(6, 6)
107
+ sys = System(lat)
108
+ sys.set_hopping([{'n': 1, 't': -1.}, {'n': 2, 't': 0.1}])
109
+ gra = kspace_from_system(sys) # the Bloch model of the same graphene
110
+ '''
111
+ error_handling.sys(sys)
112
+ error_handling.not_orbital_system(sys, OrbitalSystem)
113
+ error_handling.boolean(periodic, 'periodic')
114
+ error_handling.positive_real(tol, 'tol')
115
+ sys.get_ham()
116
+ cells, orb = cell_orbitals(sys.lat)
117
+ ham = sys.ham.tocoo()
118
+ rows, cols, vals = ham.row, ham.col, ham.data.astype('c16')
119
+ R = cells[cols] - cells[rows]
120
+ if periodic:
121
+ sizes = np.array((sys.lat.n1, sys.lat.n2, sys.lat.n3)[:R.shape[1]])
122
+ R = (R + sizes // 2) % sizes - sizes // 2 # shortest image, in [-N/2, N/2)
123
+ error_handling.torus_range(R, sizes)
124
+ keys = np.column_stack([orb[rows], orb[cols], R])
125
+ uniq, first, inv = np.unique(keys, axis=0, return_index=True, return_inverse=True)
126
+ inv = inv.ravel()
127
+ values = vals[first]
128
+ error_handling.translation_invariant(float(np.abs(vals - values[inv]).max()), tol)
129
+ off = ham - sp.diags(ham.diagonal())
130
+ hermitian = bool(abs(off - off.conj().T).max() <= tol)
131
+ lat = Lattice(unit_cell=list(sys.lat.unit_cell), prim_vec=list(sys.lat.prim_vec))
132
+ ks = KSpace(lat)
133
+ list_hop = []
134
+ for key, t in zip(uniq, values):
135
+ i, j, R = int(key[0]), int(key[1]), tuple(int(n) for n in key[2:])
136
+ if i == j and not any(R):
137
+ ks.onsite[i] = t
138
+ continue
139
+ nonzero = [n for n in R if n != 0]
140
+ if hermitian and not ((nonzero and nonzero[0] > 0) or (not nonzero and i < j)):
141
+ continue # the conjugate of a kept representative
142
+ list_hop.append({'i': i, 'j': j, 'R': R, 't': complex(t)})
143
+ ks.set_hopping(list_hop, hermitian=hermitian)
144
+ return ks
145
+
146
+
147
+ def _finite_sites(ks: KSpace, n_cells: tuple[int, ...]) -> tuple[NDArray[np.float64], NDArray]:
148
+ '''
149
+ Private function. Positions and tags of the rows of *ks.finite_ham(n_cells)*.
150
+ '''
151
+ n_tot = int(np.prod(n_cells))
152
+ cells = np.array(np.unravel_index(np.arange(n_tot), n_cells, order='F')).T
153
+ a = np.array(ks.lat.prim_vec, dtype='f8')
154
+ pos = (cells @ a)[:, None, :] + ks.orbital_positions()[None, :, :]
155
+ tags = np.repeat(ks.tags, 2) if ks.spin else ks.tags
156
+ return pos.reshape(n_tot * ks.norb, ks.space_dim), np.tile(tags, n_tot)
157
+
158
+
159
+ def finite_model(
160
+ ks: KSpace, n_cells: int | tuple[int, ...], periodic: bool = False,
161
+ ) -> tuple[sp.csr_matrix, NDArray[np.float64], NDArray]:
162
+ r'''
163
+ Get a finite sample of a *KSpace* model: its sparse Hamiltonian (that of
164
+ *KSpace.finite_ham*, open or periodic boundaries), with the position
165
+ and tag of every row. Spinful models are supported (the two spin
166
+ components of a site share its position).
167
+
168
+ :param ks: **KSpace** instance.
169
+ :param n_cells: Positive integer, or tuple of *dim* positive integers.
170
+ Number of unit cells along each primitive vector.
171
+ :param periodic: Boolean. Default value False. Periodic boundaries (a torus).
172
+
173
+ :returns:
174
+ * **ham** -- Complex CSR matrix, shape (N*norb, N*norb).
175
+ * **positions** -- Real ndarray, shape (N*norb, space_dim). Row
176
+ :math:`c\,\mathrm{norb}+o` sits at :math:`\boldsymbol\tau_o + \sum_k n_k\mathbf{a}_k`
177
+ (cell *c* has :math:`c = n_1 + N_1 n_2 + N_1N_2 n_3`).
178
+ * **tags** -- String ndarray, shape (N*norb,). Sublattice tags.
179
+ '''
180
+ error_handling.kspace(ks, KSpace)
181
+ error_handling.nk(n_cells, ks.dim)
182
+ error_handling.boolean(periodic, 'periodic')
183
+ n_cells = (n_cells,) * ks.dim if isinstance(n_cells, int) else n_cells
184
+ pos, tags = _finite_sites(ks, n_cells)
185
+ return ks.finite_ham(n_cells, periodic=periodic, sparse=True), pos, tags
186
+
187
+
188
+ def finite_system(ks: KSpace, n_cells: int | tuple[int, ...], periodic: bool = False) -> System:
189
+ r'''
190
+ Build a finite *System* out of a (spinless) *KSpace* model: *lat.coor*
191
+ holds the sites of :math:`N_1\times N_2\times\dots` unit cells (in the
192
+ order of *finite_model*), and *sys.hop* / *sys.onsite* the model's
193
+ hoppings and onsite energies, so that *sys.get_ham()* gives
194
+ *ks.finite_ham(n_cells, periodic)*. Every real-space tool (*get_eig*,
195
+ *get_ldos*, *Plot*, disorder, ...) then applies.
196
+
197
+ In *sys.hop*, each bond is stored with the conventions of
198
+ *System.set_hopping*: a Hermitian model keeps one orientation per bond
199
+ (angle in [0, 180), *get_ham* adds the conjugate); a non-reciprocal
200
+ one keeps both, the missing direction with a zero amplitude. 'n' is the
201
+ neighbour order of the bond (0 for coinciding orbitals), 'tag' the
202
+ sublattice pair. On a torus, a bond that wraps around keeps its short
203
+ bond vector for its angle, and a hopping that wraps onto its own site
204
+ is added to the onsite energy.
205
+
206
+ :param ks: **KSpace** instance, with ``spin=False``.
207
+ :param n_cells: Positive integer, or tuple of *dim* positive integers.
208
+ :param periodic: Boolean. Default value False. Periodic boundaries (a torus).
209
+
210
+ :returns:
211
+ * **sys** -- **System** instance, with its hoppings set.
212
+
213
+ Example usage::
214
+
215
+ sys = finite_system(gra, (30, 30), periodic=True)
216
+ sys.get_ham()
217
+ sys.get_eig() # = gra.mesh_bands((30, 30)), sorted
218
+ '''
219
+ error_handling.kspace(ks, KSpace)
220
+ error_handling.nk(n_cells, ks.dim)
221
+ error_handling.boolean(periodic, 'periodic')
222
+ error_handling.spinless(ks.spin)
223
+ n_cells = (n_cells,) * ks.dim if isinstance(n_cells, int) else n_cells
224
+ pos, tags = _finite_sites(ks, n_cells)
225
+ lat = Lattice(unit_cell=list(ks.lat.unit_cell), prim_vec=list(ks.lat.prim_vec))
226
+ coor = np.zeros(len(pos), dtype=lat.dtype)
227
+ for c, f in enumerate(('x', 'y', 'z')[:ks.space_dim]):
228
+ coor[f] = pos[:, c]
229
+ coor['tag'] = tags
230
+ lat.coor, lat.sites = coor, len(coor)
231
+ lat.n1, lat.n2, lat.n3 = (tuple(n_cells) + (1, 1))[:3]
232
+ sys = System(lat)
233
+ _, n_tot, entries = ks._finite_entries(n_cells, periodic)
234
+ tau = ks.orbital_positions()
235
+ rows = np.concatenate([np.zeros(0, int)] + [e[0] for e in entries])
236
+ cols = np.concatenate([np.zeros(0, int)] + [e[1] for e in entries])
237
+ t = np.concatenate([np.zeros(0, 'c16')] + [np.full(len(e[0]), e[6], 'c16') for e in entries])
238
+ d = np.concatenate([np.zeros((0, ks.space_dim))]
239
+ + [np.repeat((e[5] + tau[e[3]] - tau[e[2]])[None], len(e[0]), axis=0)
240
+ for e in entries])
241
+ n_sites = len(pos)
242
+ diag = rows == cols
243
+ sys.onsite = np.tile(ks.onsite, n_tot) + (np.bincount(rows[diag], t[diag].real, n_sites)
244
+ + 1j * np.bincount(rows[diag], t[diag].imag, n_sites))
245
+ rows, cols, t, d = rows[~diag], cols[~diag], t[~diag], d[~diag]
246
+ dist = np.linalg.norm(d, axis=1)
247
+ zero = dist <= ATOL
248
+ ang = neighbours._bond_angles(d)
249
+ up = np.where(zero, rows < cols, _upper(ang))
250
+ ang_up = np.where(zero, 0., np.maximum(np.where(up, ang, neighbours._bond_angles(-d)), 0.))
251
+ if ks._nonreciprocal:
252
+ i = np.concatenate([rows, cols])
253
+ j = np.concatenate([cols, rows])
254
+ t = np.concatenate([t, np.zeros(len(t), 'c16')])
255
+ ang = np.concatenate([np.where(up, ang_up, ang_up - 180.), np.where(up, ang_up - 180., ang_up)])
256
+ dist = np.concatenate([dist, dist])
257
+ else:
258
+ i, j, t, ang, dist = rows[up], cols[up], t[up], ang_up[up], dist[up]
259
+ hop = np.zeros(len(i), dtype=HOP_DTYPE)
260
+ hop['n'] = neighbours.shell_index(ks.lat, dist)
261
+ hop['i'], hop['j'], hop['t'], hop['ang'] = i, j, t, ang
262
+ hop['tag'] = np.char.add(tags[i], tags[j])
263
+ sys.hop = hop
264
+ return sys