L'examen des propriétés d'une substance en donnant un stimulus (par exemple, un champ électrique) à la substance et en observant la réponse (par exemple, un courant) est la base de la physique des propriétés physiques, mais il est assez difficile d'effectuer des simulations et des calculs numériques.
Par conséquent, je présenterai le module python open source "Kwant" qui peut facilement analyser le phénomène de transport quantique.
Kwant est un solveur de modèle à liaison étroite qui est toujours activement développé par des chercheurs du Centre de recherche sur l'énergie atomique de Grenoble et de l'Institut de technologie de Delft. C'est aussi Paper. Le document HP original est très riche et vous pouvez facilement reproduire et développer des exemples de calcul physiquement intéressants à portée de main en cliquant simplement en fonction. S'il s'agit d'un système qui peut être écrit avec un modèle de liaison serrée, il peut être défini très facilement, y compris les bornes d'électrode, et il couvre complètement la fonction d'onde, la densité d'état, le calcul de transport en utilisant la formule de Landauer-Buttiker et la formule de Kubo.
J'avais déjà pensé à utiliser Kwant dans le cadre de mes recherches, mais j'ai dû reporter l'introduction car il n'y avait presque pas d'articles ou de communautés en japonais et je ne savais rien sur python à ce moment-là. C'était. Je ne sais même pas comment le prononcer. Maintenant que j'ai du temps libre et que je me suis habitué à python, j'ai finalement essayé de l'utiliser, alors j'aimerais vous présenter à quoi il ressemble.
Kwant analyse principalement les systèmes physiques appelés systèmes mésoscopiques. L'intérêt de la mésoscopie est que si l'appareil est petit au niveau atomique, les effets quantiques tels que le confinement et les interférences dominent le transport. Il est particulièrement intéressant que les terminaux affectent l'état quantique et le transport.
Quant à la revue de physique, si vous lisez la série «Transport électronique dans les systèmes mésoscopiques» de Supriyo Datta ou «Édition de base du transport quantique Bases sur les propriétés physiques à l'échelle nanométrique», qui est également recommandée par la famille principale, je ne vais pas y entrer ici, mais me concentrer sur la mise en œuvre placer. Essayez-le d'abord. Alors réfléchissez.
On suppose que l'environnement pour python a été construit. Si vous créez un environnement python à l'aide d'Anaconda
conda install -c conda-forge kwant
Vous pouvez l'installer en une seule fois. La dernière version actuelle est la v1.4. Il semble que pip aura du mal, alors veuillez vous référer à la Procédure de la famille principale.
Tout d'abord, comme exemple le plus simple, fixez des bornes aux deux extrémités d'un dispositif rectangulaire bidimensionnel et calculez la conductivité entre elles. Je renvoie à ici et aux chapitres 2.2.2 et 2.2.3 du document original.
Kwant définit d'abord (construit) la forme et le système de la grille.
#Importer le module de base
import kwant
import numpy as np
import scipy as sp
import math
import matplotlib.pyplot as plt
%matplotlib inline
#Paramètres
W=10 #Largeur de l'appareil
L=30 #Longueur de l'appareil
t=1 #Saut récent
a=1 #Constante de réseau
#Forme de la grille et définition du système
lat = kwant.lattice.square(a)
syst = kwant.Builder()
Ceci définit la forme du treillis
lat et le système `` syst
. Tel quel, `` syst``` est un état vide dans lequel seul Gawa est défini, nous allons donc remplir le contenu. Le contenu ici est le hamiltonien contraignant du système.
#Potentiel sur place
syst[(lat(x, y) for x in range(L) for y in range(W))] = 0
#Saut récent(direction y)
syst[((lat(x, y),lat(x,y-1)) for x in range(L) for y in range(1,W))] = -t
#(direction x)
syst[((lat(x, y),lat(x-1,y)) for x in range(1,L) for y in range(W))] = -t
Cela stockera le hamiltonien de liaison serrée avec une largeur de W et une longueur de L en syst. Si vous définissez le saut dans une seule direction, il définira également le saut dans la direction opposée afin que l'hamiltonien devienne Elmeet.
for x in range (L) '' est une notation inclusive de python.
Ensuite, définissez les fils (bornes d'électrode). En supposant que la dérivation s'étend dans une direction à l'infini, spécifiez cette direction. Ici, nous définissons d'abord le terminal à attacher au côté gauche du système, spécifiez donc la direction (-1,0). Le potentiel et le saut sur site des leads peuvent être définis de la même manière que syst```, mais si vous ne définissez que des points avec les coordonnées x 0 et 1,
`` TranslationalSymmetry ((-a, 0)) ` Par '', il se répète périodiquement vers la gauche.
#Définition du lead
lead = kwant.Builder(kwant.TranslationalSymmetry((-a, 0)))
#Potentiel sur place
lead[(lat(0, j) for j in range(W))] = 0
#Saut récent
lead[((lat(0, j), lat(0, j - 1) ) for j in range(1,W))] = -t
lead[((lat(1, j), lat(0, j ) ) for j in range(0,W))] = -t
Maintenant, nous avons défini une avance qui s'étend indéfiniment vers la gauche, mais elle est toujours indépendante de `` syst```, alors collez-la ensemble.
syst.attach_lead(lead)
Seulement ça.
Ensuite, attachez également le câble au côté droit opposé. Pour retourner le plomb une fois défini et le fixer de l'autre côté
syst.attach_lead(lead.reversed())
Seulement ça. c'est simple.
À présent, l'état dans lequel l'échantillon rectangulaire et les deux fils plomb '' sont attachés doit être stocké dans
syst```. Kwant est également excellent dans la visualisation du système, et vous pouvez voir d'un coup d'œil quel type de système est conçu.
kwant.plot(syst)
Le saut est défini où les points bleus sont les points de grille d'échantillon, les points rouges sont les points de grille de départ et les lignes le sont. Vous pouvez voir que les fils sont parfaitement attachés aux deux extrémités de l'échantillon. Lorsque vous êtes satisfait, terminez la conception.
syst = syst.finalized()
Ceci complète la conception du système, y compris les terminaux.
Ensuite, calculons la conductivité entre les bornes du système créé. Selon la formule de Landauer, la conductivité inter-terminale est de $ e ^ 2 / h en termes de probabilité de transmission mécanique quantique entre les bornes (qui est obtenue en incident une onde plane et en connectant une fonction d'onde au milieu). C'est égal à multiplier par $, alors calculez la transparence. La transparence peut être calculée en donnant le syst``` finalisé et l'énergie de l'onde incidente à la classe
`` kwant.smatrix () ''.
conductance = []
energies = np.linspace(-4,-3,50)
for energy in energies:
#Matrice de dispersion(Matrice S)Définition de
smatrix = kwant.smatrix(syst, energy)
#Calcule et stocke la probabilité de transparence de 0 à 1.
conductance.append(smatrix.transmission(1, 0))
#terrain
plt.plot(energies, conductance)
plt.grid()
plt.xlabel("energy/t")
plt.ylabel("conductance($e^2/h$)")
plt.show()
c'est simple. Les leads sont numérotés 0, 1, 2 ... dans l'ordre de attach_lead
, donc 1 et 0 sont spécifiés cette fois. En regardant les résultats obtenus, on peut voir que lorsque l'énergie de l'onde incidente augmente, la conductivité augmente progressivement. Il s'agit d'un effet propre au système mésoscopique appelé quantification de conduction, et son origine est l'effet de confinement mécanique quantique dans la direction y.
Avec le recul, j'ai pu effectuer la définition hamiltonienne de l'échantillon, la définition hamiltonienne du plomb, l'adhérence du plomb et le calcul de la conductivité avec environ 20 lignes de code. Il est agréable et facile de faire un calcul similaire à partir de zéro, étant donné qu'il faut beaucoup d'efforts physiques et de codage pour calculer la fonction verte de surface des dérivations et définir le saut de l'échantillon de plomb.
La matrice unitaire de l'espace de spin est définie comme
s0 = np.array ([[1,0], [0,1]])
et écrite comme
t``` dans cet exemple. En remplaçant par `` t * s0 '', la réduction de spin peut être exprimée et la conductance est doublée. De même, en définissant la matrice de Pauli, les interactions orbitales de spin et les champs magnétiques Zeeman peuvent être donnés.
Comme exemple de traitement du potentiel non uniforme sur site et du saut en plus de l'exemple 1, considérons l'effet de trou quantique d'un système perturbé. À propos, vous devez être prudent lorsque vous manipulez un grand nombre de terminaux. Je me réfère à différentes parties du document original (idem ci-dessous)
En supposant une situation où un champ magnétique est appliqué verticalement dans le plan bidimensionnel où le dispositif existe, nous allons attacher 6 bornes selon la disposition des barres de trous que nous voyons souvent dans les expériences. L'importation de kwant et numpy est identique à l'exemple ci-dessus, elle sera donc omise. La première est la définition de la forme de l'appareil. Seuls les paramètres supplémentaires sont commentés.
W=15
L_lead=6 #Largeur du fil du trou
M_lead=6 #Distance du bord de la tête de trou
L=30
t=1
a=1
V=0.05 #Force potentielle aléatoire
lat = kwant.lattice.square(a)
syst = kwant.Builder()
Ensuite, nous définissons l'hamiltonien de la partie échantillon. Le potentiel sur site est donné de manière appropriée en utilisant des nombres aléatoires normaux. Là encore, nous allons considérer le saut le plus proche et prendre en compte la phase de Piels due au champ magnétique vertical.
#Potentiel aléatoire sur site
for x in range(L):
for y in range(W):
syst[lat(x, y)] = np.random.randn()*V
#(xi, yi)De(xj, yj)Fonction qui donne du saut à
def hopping(site_i, site_j, phi):
xi, yi = site_i.pos
xj, yj = site_j.pos
return -t*np.exp(-0.5j * phi * (xi - xj) * (yi + yj))
#Saut récent
syst[lat.neighbors()] = hopping
J'ai essayé d'utiliser `` lat.neighbors () '' comme méthode de spécification de l'hamiltonien du plomb, contrairement à l'exemple 1. Ceci est utile lors de la définition du saut le plus proche d'un point de site qui a déjà été défini, car vous n'avez pas à vous soucier de spécifier les coordonnées. Par ailleurs, si n = 2 est donné comme paramètre, le prochain saut de proximité peut être défini de la même manière.
La fonction saut '' qui définit le saut contient les informations de site de la source et de la destination du déplacement dans les premier et deuxième arguments, et les arguments suivants sont interprétés comme des paramètres donnés de l'extérieur. Ici, le paramètre
ph i '' qui représente l'amplitude du champ magnétique n'a pas de valeur à ce stade, et peut recevoir une valeur de l'extérieur après avoir finalisé syst ''. Si vous souhaitez voir la dépendance des paramètres d'une réponse, telle que la conductivité, vous n'avez pas à redéfinir
`` syst``` pour chaque valeur de paramètre et à la finaliser (voir ci-dessous).
Définissez ensuite les 6 dérivations dans l'ordre. Notez que les quatre terminaux autres que les deux terminaux attachés aux deux extrémités sont kwant.TranslationalSymmetry ((0, a)) '' car ils s'étendent dans la direction y. Le code de chaque
lat.neighbors () '' écrit de manière simple est également commenté.
lead = kwant.Builder(kwant.TranslationalSymmetry((-a, 0)))
lead[(lat(0, j) for j in range(W))] = 0
# lead[((lat(0, j), lat(0, j - 1) ) for j in range(1,W))] = hopping
# lead[((lat(1, j), lat(0, j ) ) for j in range(0,W))] = hopping
lead[lat.neighbors()] = hopping
lead_hall24 = kwant.Builder(kwant.TranslationalSymmetry((0, a)))
lead_hall24[(lat(j, 0) for j in range(M_lead,M_lead+L_lead))] = 0
# lead_hall24[((lat(j,0), lat(j-1,0) ) for j in range(M_lead+1,M_lead+L_lead))] = hopping
# lead_hall24[((lat(j,1), lat(j ,0) ) for j in range(M_lead,M_lead+L_lead))] = hopping
lead_hall24[lat.neighbors()] = hopping
lead_hall35 = kwant.Builder(kwant.TranslationalSymmetry((0, a)))
lead_hall35[(lat(j, 0) for j in range(L-M_lead-L_lead,L-M_lead))] = 0
# lead_hall35[((lat(j,0), lat(j-1,0) ) for j in range(L-M_lead-L_lead+1,L-M_lead))] = hopping
# lead_hall35[((lat(j,1), lat(j ,0) ) for j in range(L-M_lead-L_lead,L-M_lead))] = hopping
lead_hall35[lat.neighbors()] = hopping
#Installation des 6 fils. Faites attention à la commande.
syst.attach_lead(lead)
syst.attach_lead(lead.reversed())
syst.attach_lead(lead_hall24)
syst.attach_lead(lead_hall35)
syst.attach_lead(lead_hall24.reversed())
syst.attach_lead(lead_hall35.reversed())
Jusqu'à présent, l'ensemble du dispositif a été défini. Visualisez et finalisez
kwant.plot(syst)
syst = syst.finalized()
J'ai numéroté les pistes à la main.
À partir de là, nous calculerons des valeurs telles que la conductivité Hall et la résistance Hall. La fonction de base est `` smatrix.conductance_matrix () ''. Il peut être utilisé pour calculer $ G $ dans la relation proportionnelle $ I = GV $ entre le courant $ I $ et la tension $ V $ de la matrice S. Puisque $ I et V $ sont définis pour chacun des 6 terminaux, ils sont chacun un vecteur de dimension $ 6 $, donc $ G $ est une matrice $ 6 \ times 6 $. Lorsque l'état où le courant est passé uniquement entre les bornes 0 et 1 est exprimé comme $ I_0 = -I_1 = I, \ \ I_2 = I_3 = I_4 = I_5 = 0 $, la résistance verticale et la résistance de hall sont respectivement $ R_ {long}. Vous pouvez écrire = \ frac {V_4-V_5} {I}, \ R_ {Hall} = \ frac {V_3-V_5} {I} $, donc il semble que vous devriez d'abord trouver l'inverse de la matrice $ G $.
Cependant, la matrice $ G $ est connue pour être déclassée en raison de la loi de conservation actuelle et de l'indétermination de l'origine de la tension. Donc ici nous supposons $ V_5 = 0 $ et ignorons la colonne la plus à droite de $ G $. Alors $ G $ devient une matrice $ 6 \ fois 5 $, et le problème de matrice inverse est surdéterminé. Je vais donc ignorer la ligne du bas et traiter $ G $ comme une matrice $ 5 \ times 5 $.
Le paramètre mentionné ci-dessus phi``` peut être donné comme dictionnaire lors de la définition de la matrice S (dans l'exemple ici, il n'était pas nécessaire d'attribuer
`` phi```, il est donc nécessaire de sortir. Je ne l'avais pas ...)
#Une fonction pour obtenir la résistance verticale, la résistance Hall, la conductivité et la conductivité Hall à partir de la matrice S.
from numpy.linalg import LinAlgError
def calc_conductances2(smatrix):
#Calculer la matrice de conductance G
gmat = smatrix.conductance_matrix()
#Traitement des exceptions lorsque la matrice est accidentellement singulière
try:
Rmat = np.linalg.inv(gmat[:5,:5])
except LinAlgError:
R_long = np.nan
R_Hall = np.nan
sigma_xx = 0
sigma_xy = 0
else:
#V_5=Je l'ai mis à 0, donc R_long=V_4/I
R_long = Rmat[4,0]-Rmat[4,1]
R_Hall = Rmat[3,0]-Rmat[3,1]
sigma_xx = R_long/(R_long**2+R_Hall**2)
sigma_xy =-R_Hall/(R_long**2+R_Hall**2)
return R_long , R_Hall , sigma_xx ,sigma_xy
phi=2*np.pi*1/11 #La valeur du paramètre phi.
R_Halls =[]
R_longs =[]
sigma_xxs =[]
sigma_xys =[]
doss=[]
energies = np.linspace(-4,0,50)
for energy in energies:
#Calcul de la matrice S. Donnez les paramètres sous forme de dictionnaire.
smatrix = kwant.smatrix(syst, energy, params=dict(phi=phi) )
R_long, R_Hall, sigma_xx, sigma_xy = calc_conductances(smatrix)
R_Halls.append(R_Hall)
R_longs.append(R_long)
sigma_xxs.append(sigma_xx)
sigma_xys.append(sigma_xy)
#Calculez également la densité d'état.
dos = kwant.ldos(syst, energy, params=dict(phi=phi) ).mean()
doss.append(dos)
Si vous tracez la conductivité et la conductivité du hall en fonction de l'énergie
plt.plot(energies, doss, label="dos")
plt.plot(energies, sigma_xxs, label="sigma_xx")
plt.plot(energies, sigma_xys, label="sigma_xy")
plt.grid()
plt.ylim(-1,5)
plt.xlim(-4,-0.8)
plt.xlabel("energy/t")
plt.legend()
plt.show()
Il peut être confirmé que la conductivité de Hall est quantifiée à un multiple entier de $ e ^ 2 / h $, et que la densité d'état et la conductivité longitudinale sont similaires au niveau de Landau.
Désormais, vous pouvez rendre le potentiel sur site et les sauts non uniformes, donner des paramètres de l'extérieur et ajouter de nombreux terminaux.
Vous pouvez calculer la conductivité Hall plus facilement en utilisant la formule de Kubo sans attacher de bornes avec le code suivant. Seule la fonction `` sautiller '' est empruntée au dessus, mais elle peut être calculée en environ 10 lignes. Hou la la!
W=100
L=W
t=1
a=1
lat = kwant.lattice.square(a)
syst = kwant.Builder()
syst[(lat(x, y) for x in range(L) for y in range(W))] = 0
syst[lat.neighbors()] = hopping
syst = syst.finalized()
sigma_xy = kwant.kpm.conductivity(syst, alpha='x', beta='y',params=dict(phi=2*np.pi/11))
conductivities = [sigma_xy(mu=mu, temperature=0)/L/W for mu in np.linspace(-4,0,50)]
plt.plot(np.linspace(-4,0,50),conductivities)
plt.grid()
Cependant, si les paramètres par défaut sont utilisés, la quantification sera lâche et la précision du calcul sera difficile. Il semble que la méthode polynomiale du noyau (KPM) soit utilisée pour le calcul ici, et la précision peut être améliorée en ajustant finement les paramètres de calcul. Vous pouvez augmenter la taille de l'appareil, mais cela prendra beaucoup de temps. Dans cet article, en raison des connaissances et des limites de motivation de l'auteur, je laisserai les détails au document original ...
Dans la v1.4, une fonction a été ajoutée pour calculer la phase de Peierls du champ de jauge et le saut provoqué par celui-ci lorsqu'un champ magnétique est appliqué. Consultez la documentation pour plus de détails.
Comme dernier exemple, regardons l'effet anormal de trou quantique dans le modèle Haldane (dans un cas particulier). Lorsque le fermion sans spin en forme de réseau en nid d'abeille effectue un saut de proximité imaginaire pur, la conductivité du hall est quantifiée sans champ magnétique externe.
Jusqu'à présent, nous n'avons considéré que des appareils rectangulaires avec des grilles carrées disposées, mais ici nous allons créer un appareil avec des grilles en nid d'abeille disposées en cercle. Tout d'abord, celui avec une forme de treillis différente est défini comme `` lat ''. c'est simple.
#Paramètres
a=1
t=1.0
tt=0.5 #Prochain saut de proximité
L_lead=10
#Définissez un treillis en nid d'abeille. norbs est un paramètre qui représente le nombre d'orbitales par site (autre que la distribution actuelle finale, cela fonctionne sans elle). A dans le sous-réseau,Nommez-le b.
lat = kwant.lattice.honeycomb(a, norbs=1, name=['a', 'b'])
#Ici ensemble
syst = kwant.Builder()
Ensuite, définissons la forme de l'appareil. Pour définir la forme, utilisez une fonction qui renvoie une valeur booléenne pour les coordonnées. En spécifiant un point à l'intérieur de la forme définie, vous pouvez remplir la seule zone connectée avec le site.
#Définir la forme
def circle(pos):
x, y = pos
return x**2 + y**2 < 100
#Spécifiez un point à l'intérieur de la forme. ici(0,0).. Le potentiel sur place est de 0
syst[lat.shape(circle, (0, 0))] = 0
Le saut peut être défini de la même manière. Puisque les sous-réseaux a et b sont définis, le contact le plus proche (= prochaine proximité du réseau en nid d'abeilles) peut être facilement spécifié uniquement sur celui-ci. Ici, le prochain saut de proximité est un pur nombre imaginaire.
syst[lat.neighbors()] = -t
syst[lat.a.neighbors()] = -1j*tt
syst[lat.b.neighbors()] = 1j*tt
La définition du plomb est similaire
lead = kwant.Builder(kwant.TranslationalSymmetry((-a, 0)))
def lead_shape(pos):
x, y = pos
return (-L_lead/2 < y < L_lead/2)
lead[lat.shape(lead_shape,(0,0))] = 0
lead[lat.neighbors()] = -t
lead[lat.a.neighbors()] = -1j*tt
lead[lat.b.neighbors()] = 1j*tt
syst.attach_lead(lead)
syst.attach_lead(lead.reversed())
Jetons un coup d'œil à la forme de l'appareil.
kwant.plot(syst)
syst = syst.finalized()
J'ai certainement pu attacher des fils aux deux extrémités du dispositif circulaire en nid d'abeille. Si vous regardez attentivement, vous pouvez également voir la ligne noire qui représente le prochain saut de proximité. Le roseau a une forme légèrement étrange car il est capable de satisfaire la symétrie de translation semi-infinie à gauche et à droite, mais la forme de ce côté est susceptible de changer dans la direction du fauteuil et la direction du zigzag. (Je n'ai pas essayé)
Vous pouvez également essayer de calculer la quantification de la conductivité Hall en attachant plusieurs terminaux, mais comme c'est un gros problème, je vais essayer de visualiser l'état de Hall quantique par une autre méthode. Tout d'abord, calculons la transparence et la densité d'état entre les deux terminaux. Le code est presque le même que dans l'exemple 1.
trans=[]
doss=[]
energies = np.linspace(-4,4,100,endpoint=False)
for energy in energies:
smatrix = kwant.smatrix(syst, energy )
trans.append(smatrix.transmission(0,1))
dos = kwant.ldos(syst,energy ).mean()
doss.append(dos)
plt.plot(energies, trans, label="conductance")
#Il est grossièrement multiplié par 10 pour une bonne apparence.
plt.plot(energies, [d*10 for d in doss], label="dos")
plt.grid()
plt.legend()
plt.xlabel("energy/t")
plt.show()
En regardant cela, nous pouvons voir que la conductance est quantifiée lorsque l'énergie incidente est proche de 0. En d'autres termes, cela signifie qu'il n'y a qu'un seul canal de conduction sans diffusion.
Ensuite, en regardant la densité d'état, elle devient plus petite dans cette région d'énergie. J'ai utilisé la moyenne spatiale de la fonction `` kwant.ldos () '' pour calculer la densité d'état, mais traçons la distribution (densité d'état local) dans l'espace réel avant de faire la moyenne. ..
local_dos = kwant.ldos(syst,energy=0.1 )
kwant.plotter.map(syst,local_dos)
Ensuite, vous pouvez voir que la densité d'état n'est finie qu'aux bords de l'appareil. En d'autres termes, le courant ne peut circuler qu'au bord de l'appareil, et l'intérieur est isolant. Cela représente la conduction de bord due à l'état de bord propre à l'état de trou quantique.
Vous pouvez également tracer la distribution actuelle.
psi = kwant.wave_function(syst,energy=0.1)(0)
J = kwant.operator.Current(syst)
current=sum(J(p) for p in psi)
kwant.plotter.current(syst,current,min_linewidth=.01,density=0.3)
Il s'agit d'une représentation vectorielle en champ de la façon dont les électrons incidents du plomb 0 circulent. Certes, il a atteint le fil 1 à l'extrémité droite tout en étant localisé sur le bord de l'appareil.
Vous savez maintenant que vous pouvez concevoir des appareils de forme étrange et des appareils en forme de grille.
J'ai regardé le calcul de conduction quantique de Kwant en me concentrant sur le système bidimensionnel. Il y a de nombreuses fonctions dont je n'ai pas encore compris le comportement, et de nombreuses fonctions que je n'ai pas maîtrisées, il semble donc que je puisse faire plus si je lis le document. En plus de la documentation, vous pouvez trouver une liste de diffusion pour discussion et un exemple de notebook jupyter sur la page d'accueil de Kwant, alors jouez avec.
En plus de celles illustrées ici, il y a d'autres choses intéressantes qui peuvent être faites.
Recommended Posts