.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/superconductivity/plot_kitaev_chain.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_superconductivity_plot_kitaev_chain.py: The Kitaev Chain: Majorana Zero Modes =========================================== A. Kitaev (2001) wrote down the simplest topological superconductor: a chain of spinless fermions with nearest-neighbour hopping :math:`t` and p-wave pairing :math:`\Delta`, .. math:: H = \sum_j\Big[t\,c_j^\dagger c_{j+1} + \Delta\,c_j^\dagger c_{j+1}^\dagger + h.c.\Big] - \mu\sum_j c_j^\dagger c_j\, . In the Bogoliubov-de Gennes form its bulk spectrum is :math:`E(k) = \pm\sqrt{(2t\cos k - \mu)^2 + 4|\Delta|^2\sin^2k}`, gapped except at :math:`|\mu| = 2|t|`. For :math:`|\mu| < 2|t|` the chain is topological: an open chain hosts one *Majorana* zero mode at each end -- a fermion split in two halves, a building block proposed for topological quantum computation, and chased in semiconductor nanowires since 2012. Kitaev's own bulk invariant is the *Majorana number* .. math:: \mathcal{M} = \mathrm{sign}\left[\mathrm{Pf}\,A(0)\,\mathrm{Pf}\,A(\pi)\right]\, , the signs of the Pfaffians of the Hamiltonian written in Majorana operators at the two time-reversal-invariant momenta: :math:`-1` in the topological phase, :math:`+1` otherwise. It needs only particle-hole symmetry (class D). With the extra chiral symmetry of this real chain (class BDI), the Berry (Zak) phase of the occupied BdG band, :math:`\pi` or 0, says the same. :mod:`tbkit.bdg` builds the chain in real space (*bdg_ham*) and in reciprocal space (*bdg_kspace*). .. GENERATED FROM PYTHON SOURCE LINES 36-54 .. code-block:: Python import numpy as np import matplotlib.pyplot as plt import tbkit.lattices as lattices from tbkit.bdg import bdg_ham, bdg_kspace, majorana_number, pairing_bonds, particle_hole from tbkit.kspace import KSpace from tbkit.plot import Plot from tbkit.system import System t, delta = 1., 0.6 def kitaev(mu): chain = KSpace(lattices.chain()) chain.set_hopping([{'i': 0, 'j': 0, 'R': (1,), 't': t}]) return bdg_kspace(chain, [{'i': 0, 'j': 0, 'R': (1,), 'delta': delta}], mu=mu) .. GENERATED FROM PYTHON SOURCE LINES 55-60 The lattice ----------- A chain of spinless fermions, one site per cell. Each nearest-neighbour bond carries both the hopping :math:`t` and the p-wave pairing :math:`\Delta`, which binds fermions on neighbouring sites. .. GENERATED FROM PYTHON SOURCE LINES 60-67 .. code-block:: Python patch = lattices.chain() patch.get_lattice(n1=10) vis = System(patch) vis.set_hopping([{'n': 1, 't': t}]) fig_lat = Plot(vis).lattice(plt_hop=True, ms=12, figsize=(7, 1.2)) .. image-sg:: /api/gallery/superconductivity/images/sphx_glr_plot_kitaev_chain_001.png :alt: plot kitaev chain :srcset: /api/gallery/superconductivity/images/sphx_glr_plot_kitaev_chain_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 68-70 The bulk spectrum and the invariant --------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 70-94 .. code-block:: Python for mu in (0.5, 1.5, 3.): for k in (0.4, 1.3, 2.7): e = np.sqrt((2*t*np.cos(k) - mu)**2 + 4*delta**2*np.sin(k)**2) assert np.allclose(np.linalg.eigvalsh(kitaev(mu).get_ham([k])), [-e, e]) assert kitaev(0.5).symmetry_error(particle_hole(1), antiunitary=True, anti=True) < 1e-12 print('Class:', kitaev(0.5).tenfold_class(time_reversal=np.eye(2), particle_hole=particle_hole(1))) mus = np.linspace(-3.5, 3.5, 29) zak = np.array([abs(kitaev(mu).berry_phase(0, nk=200)) for mu in mus]) topological = np.abs(mus) < 2 * abs(t) assert np.allclose(zak[topological], np.pi) and np.allclose(zak[~topological], 0., atol=1e-8) print('Berry phase pi for |mu| < 2|t|, 0 outside.') # at |mu| = 2|t| the gap closes at k = 0 or pi, and the Majorana number is undefined gapped = ~np.isclose(np.abs(mus), 2 * abs(t)) majorana = np.array([majorana_number(kitaev(mu)) for mu in mus[gapped]]) assert np.all(majorana[topological[gapped]] == -1) and np.all(majorana[~topological[gapped]] == 1) try: majorana_number(kitaev(2 * t)) raise AssertionError('the gap closes at k = 0') except ValueError: pass print('Majorana number -1 for |mu| < 2|t|, +1 outside.') .. rst-class:: sphx-glr-script-out .. code-block:: none Class: BDI Berry phase pi for |mu| < 2|t|, 0 outside. Majorana number -1 for |mu| < 2|t|, +1 outside. .. GENERATED FROM PYTHON SOURCE LINES 95-97 Majorana zero modes at the ends of an open chain ------------------------------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 97-132 .. code-block:: Python n = 40 lat = lattices.chain() lat.get_lattice(n) sys = System(lat) sys.set_hopping([{'n': 1, 't': t}]) sys.get_ham() spectra = {} for mu in (0.5, 3.): en, vec = np.linalg.eigh(bdg_ham(sys.ham, pairing_bonds(sys, delta), mu=mu).toarray()) spectra[mu] = en assert np.allclose(en, -en[::-1]) # particle-hole symmetric zero = np.argsort(np.abs(spectra[0.5]))[:2] print('mu = 0.5: two states at |E| = {:.1e}; next at {:.3f}.' .format(np.max(np.abs(spectra[0.5][zero])), np.sort(np.abs(spectra[0.5]))[2])) assert np.max(np.abs(spectra[0.5][zero])) < 1e-8 and np.min(np.abs(spectra[3.])) > 0.5 # the zero modes live at the ends (particle and hole components summed) en, vec = np.linalg.eigh(bdg_ham(sys.ham, pairing_bonds(sys, delta), mu=0.5).toarray()) weight = np.abs(vec[:n, zero]) ** 2 + np.abs(vec[n:, zero]) ** 2 ends = weight[:5].sum() + weight[-5:].sum() print('Weight of the two zero modes on the outer 5 sites of each end: {:.0%}.'.format(ends / 2)) assert ends / 2 > 0.95 # and the same chain from the Bloch model assert np.allclose(spectra[0.5], np.linalg.eigvalsh(kitaev(0.5).finite_ham(n))) fig, axes = plt.subplots(1, 2, figsize=(10, 4)) axes[0].plot(mus, zak / np.pi, 'o-b', label=r'Berry phase / $\pi$') axes[0].plot(mus[gapped], majorana, 's--r', ms=4, label=r'Majorana number $\mathcal{M}$') axes[0].set_xlabel(r'$\mu/t$') axes[0].legend() axes[1].plot(np.arange(n), weight.sum(axis=1), 'o-r') axes[1].set_xlabel('site') axes[1].set_ylabel('zero-mode weight') axes[1].set_title(r'Majorana end modes, $\mu = 0.5t$') fig.set_layout_engine('tight') .. image-sg:: /api/gallery/superconductivity/images/sphx_glr_plot_kitaev_chain_002.png :alt: Majorana end modes, $\mu = 0.5t$ :srcset: /api/gallery/superconductivity/images/sphx_glr_plot_kitaev_chain_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none mu = 0.5: two states at |E| = 1.2e-12; next at 1.145. Weight of the two zero modes on the outer 5 sites of each end: 100%. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.099 seconds) .. _sphx_glr_download_api_gallery_superconductivity_plot_kitaev_chain.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_kitaev_chain.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_kitaev_chain.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_kitaev_chain.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_