.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/hall_effects/plot_anomalous_hall_disorder.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_hall_effects_plot_anomalous_hall_disorder.py: The Anomalous Hall Effect in Real Space: a Disordered Chern Insulator ======================================================================== The Berry-phase theory of the anomalous Hall effect is a statement about Bloch bands, but a real sample has impurities, and no Brillouin zone. The Kubo-Bastin formula needs neither: it is a trace over the whole sample, .. math:: \sigma_{xy}(\mu) \propto \int d\varepsilon\, f(\varepsilon)\, \mathrm{Tr}\left[v_x\,\delta(\varepsilon-H)\,v_y\,\frac{dG^+}{d\varepsilon} - v_x\,\frac{dG^-}{d\varepsilon}\,v_y\,\delta(\varepsilon-H)\right], which Garcia, Covaci and Rappoport (2015) expanded in Chebyshev polynomials with the kernel polynomial method: :func:`tbkit.kpm.hall_conductivity`, with a cost linear in the number of sites. Here: a Haldane model on a torus of 100 x 100 cells (20,000 orbitals), with random onsite energies in :math:`[-W/2, W/2]`. The trace runs over a torus -- an open flake would not do, as its edge currents cancel the bulk and the whole trace vanishes in the gap -- so the velocities :math:`v = i[H, \mathbf{r}]` come from the bond vectors (:meth:`~tbkit.kspace.KSpace.finite_velocity`), which stay short across the periodic boundary. The quantized anomalous Hall plateau survives disorder stronger than the clean gap, and dies when the disorder is strong enough. A caveat of the method: its random-vector trace, cheap and accurate in a (mobility) gap, is noisy inside clean bands, where its error falls only as :math:`1/\sqrt{RN}` (:math:`R` random vectors, :math:`N` orbitals). The plateaus are the reliable part of the curves below. .. GENERATED FROM PYTHON SOURCE LINES 33-63 .. code-block:: Python import numpy as np import matplotlib.pyplot as plt import scipy.sparse as sparse import tbkit.kpm as kpm import tbkit.lattices as lattices from tbkit.bridges import finite_system from tbkit.kspace import KSpace from tbkit.plot import Plot def haldane(M, t2=0.2): '''Haldane model: nearest-neighbour t = 1, i t2 on the second neighbours, mass +-M.''' hal = KSpace(lattices.honeycomb()) hal.set_hopping([{'i': 0, 'j': 1, 'R': R, 't': 1.} for R in [(0, 0), (-1, 0), (0, -1)]]) for R in [(0, 1), (-1, 0), (1, -1)]: # a2, -a1, a1 - a2: 120 degrees apart hal.set_hopping([{'i': 0, 'j': 0, 'R': R, 't': 1j*t2}, {'i': 1, 'j': 1, 'R': R, 't': -1j*t2}]) hal.set_onsite({'a': M, 'b': -M}) return hal hal = haldane(0.3) n = 100 ham_clean = hal.finite_ham(n, periodic=True, sparse=True) vx, vy = hal.finite_velocity(n, periodic=True, sparse=True) area = n * n * abs(np.linalg.det(np.array(hal.lat.prim_vec))) n_orb = ham_clean.shape[0] e_f = np.linspace(-2., 2., 81) n_moments, n_random = 256, 6 .. GENERATED FROM PYTHON SOURCE LINES 64-72 The lattice ----------- The Haldane model on a patch of :math:`5\times4` cells (:func:`~tbkit.bridges.finite_system`), each bond drawn with a width proportional to its amplitude: the honeycomb lattice's two sublattices ('a' and 'b', in two colours), the nearest-neighbour hopping :math:`t` (thick) and the complex second-neighbour hoppings :math:`\pm it_2` within each sublattice (thin), which break time-reversal symmetry. .. GENERATED FROM PYTHON SOURCE LINES 72-75 .. code-block:: Python fig_lat = Plot(finite_system(haldane(0.3), (5, 4))).lattice(plt_hop=True, ms=12, figsize=(5.5, 4.5)) .. image-sg:: /api/gallery/hall_effects/images/sphx_glr_plot_anomalous_hall_disorder_001.png :alt: plot anomalous hall disorder :srcset: /api/gallery/hall_effects/images/sphx_glr_plot_anomalous_hall_disorder_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 76-83 The clean torus ------------------ Without disorder, the torus is the Bloch problem on a 100 x 100 k-mesh, and in the gap :math:`(-0.74, 0.74)` the KPM value is the Chern number. In the bands it scatters about the Bloch result (:meth:`~tbkit.kspace.KSpace.hall_conductivity`, dotted) by the noise of the random-vector trace. .. GENERATED FROM PYTHON SOURCE LINES 83-93 .. code-block:: Python _, sigma_clean = kpm.hall_conductivity(ham_clean, vx, vy, n_moments, n_random, e_grid=e_f, area=area, seed=0) bloch = hal.hall_conductivity(e_f, temperature=0.05, nk=n) chern = hal.chern_number([0], 60) gap = np.abs(e_f) < 0.5 print('Chern number {:.4f}; clean KPM plateau {:.4f} +- {:.4f}'.format( chern, sigma_clean[gap].mean(), sigma_clean[gap].std())) assert np.allclose(sigma_clean[gap], chern, atol=0.02) .. rst-class:: sphx-glr-script-out .. code-block:: none Chern number 1.0000; clean KPM plateau 1.0003 +- 0.0000 .. GENERATED FROM PYTHON SOURCE LINES 94-102 Adding disorder ------------------ One disorder realization per strength (seeded). At :math:`W = 2`, wider than the clean gap (1.48), the plateau is intact. At :math:`W = 4` the random potential fills the gap with states -- the density of states at :math:`E = 0` is no longer zero -- but these states are localized and carry no current: the plateau survives in a *mobility* gap. At :math:`W = 8`, the disorder has destroyed it. .. GENERATED FROM PYTHON SOURCE LINES 102-131 .. code-block:: Python rng = np.random.default_rng(1) strengths = [0., 2., 4., 8.] sigma = {0.: sigma_clean} dos0 = {} for W in strengths: ham = ham_clean + sparse.diags(rng.uniform(-W / 2, W / 2, n_orb)) if W > 0: sigma[W] = kpm.hall_conductivity(ham, vx, vy, n_moments, n_random, e_grid=e_f, area=area, seed=0)[1] dos0[W] = kpm.dos(ham, n_moments, n_random, e_grid=[0.], seed=0)[1][0] / n_orb print('W = {:.0f}: sigma_xy(0) = {:.3f} e^2/h, DOS(0) = {:.4f} per orbital'.format( W, sigma[W][np.argmin(np.abs(e_f))], dos0[W])) centre = np.argmin(np.abs(e_f)) assert abs(sigma[2.][centre] - chern) < 0.03 # the plateau survives W = 2 assert abs(sigma[4.][centre] - chern) < 0.05 # and W = 4... assert dos0[4.] > 0.01 and dos0[4.] > 100 * dos0[0.] # ...although states now fill the gap assert sigma[8.][centre] < 0.5 # strong disorder destroys it fig, ax = plt.subplots(figsize=(7, 4.5)) for W in strengths: ax.plot(e_f, sigma[W], label='$W = {:.0f}$'.format(W)) ax.plot(e_f, bloch, 'k:', lw=1, label='Bloch, clean') ax.axhline(chern, color='k', lw=0.5) ax.set_xlabel(r'$\mu$') ax.set_ylabel(r'$\sigma_{xy}$ ($e^2/h$)') ax.set_title('Haldane torus, 20,000 orbitals: Kubo-Bastin (KPM)') ax.legend() .. image-sg:: /api/gallery/hall_effects/images/sphx_glr_plot_anomalous_hall_disorder_002.png :alt: Haldane torus, 20,000 orbitals: Kubo-Bastin (KPM) :srcset: /api/gallery/hall_effects/images/sphx_glr_plot_anomalous_hall_disorder_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none W = 0: sigma_xy(0) = 1.000 e^2/h, DOS(0) = 0.0000 per orbital W = 2: sigma_xy(0) = 1.005 e^2/h, DOS(0) = 0.0001 per orbital W = 4: sigma_xy(0) = 0.989 e^2/h, DOS(0) = 0.0366 per orbital W = 8: sigma_xy(0) = 0.107 e^2/h, DOS(0) = 0.0973 per orbital .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 5.758 seconds) .. _sphx_glr_download_api_gallery_hall_effects_plot_anomalous_hall_disorder.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_anomalous_hall_disorder.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_anomalous_hall_disorder.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_anomalous_hall_disorder.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_