Ce document montre comment faire la résolution numérique de l'équation de Schrödinger dépendante du temps, en suivant une méthode similaire à celle utilisée pour l'équation de diffusion. On verra comment appliquer la méthode à un paquet d'onde diffusé par un potentiel.
Voir aussi la simulation Équation de Schrödinger à une dimension.
On considère l'équation de Schrödinger dépendante du temps pour une fonction d'onde :
On s'intéresse à la diffusion de particules dans un potentiel V(x). La résolution est limitée à l'intervalle fini [0,L]. Sur les bords de cet intervalle, la fonction d'onde est supposée nulle. La condition de normalisation s'écrit :
La fonction d'onde initiale est connue. Elle prendra la forme d'un paquet d'onde localisée à l'intérieur de l'intervalle [0,L].
On cherche à résoudre numériquement l'équation par la méthode des différences finies. La méthode utilisée est similaire à celle développée dans Équation de diffusion à une dimension.
Soit V0 l'échelle du potentiel. La fonction V(x) utilisée sera sans dimensions. On introduit l'échelle de temps :
et l'échelle de longueur :
En utilisant un temps et un x réduits par ces deux échelles, on obtient l'équation :
On utilise l'opérateur hamiltonien :
La solution de l'équation de Schrödinger peut s'écrire formellement à l'aide de l'exponentielle de l'opérateur hamiltonien ([1]) :
La conservation de la condition au cours du temps vient du caractère unitaire de l'opérateur .
Soit N le nombre de points dans l'intervalle [0,L]. On définit le pas d'espace :
Soit Δt le pas de temps. On pose :
où n est un entier positif ou nul repésentant le temps.
La dérivée temporelle est discrétisée de la manière suivante :
La dérivée seconde par rapport à x est discrétisée par :
Le schéma explicite qui en découle est :
Comme pour l'équation de diffusion, ce schéma explicite a une condition de stabilité très contraignante. On lui préfère donc un schéma implicite.
Pour alléger les notations, on introduit l'opérateur hamiltonien discret défini par :
En suivant la démarche adoptée pour l'équation de diffusion à une dimension, on est amené à considérer le schéma implicite suivant :
ou encore :
Ce schéma conduit à la résolution, pour chaque pas de temps, d'un système linéaire tridiagonal, pour lequel il existe une méthode directe efficace. Il a toutefois l'inconvénient de ne pas conserver la norme de la fonction d'onde.
Pour un intervalle de temps, on a :
Le schéma défini ci-dessus revient à utiliser l'approximation au premier ordre suivante :
Cette transformation n'est pas unitaire, c'est pourquoi la norme de la fonction d'onde n'est pas conservée. On la remplace par l'approximation de Cayley ([2]), qui est unitaire :
Le schéma numérique s'écrit alors :
On obtient ainsi le schéma implicite suivant :
avec :
On le met sous la forme générale suivante :
Pour chaque pas de temps, le système tridiagonal est résolu par l'algorithme d'élimination décrit dans Équation de diffusion à une dimension.
Les conditions limites sont de type Dirichlet, puisqu'elles consistent à annuler la fonction d'onde sur les bords de l'intervalle :
Pour obtenir l'évolution d'un paquet d'onde, on considère comme condition initiale un paquet d'onde gaussien défini par :
Le paquet d'onde est initialement en x=x0 et se déplace dans le sens de l'axe x. La densité de propabilité (non normée) associée à ce paquet est :
La variance de cette densité de probabilité est σ0. Le spectre en nombre d'onde de ce paquet a une largeur donnée par :
Considérons l'évolution du paquet d'onde en l'absence de potentiel (particule libre). La largeur Δk reste constante au cours du temps. Notons σ la largeur du paquet à l'instant t. L'inégalité d'Heisenberg s'écrit :
Pour ce paquet gaussien, l'égalité est réalisée à l'instant t=0. On peut calculer précisément la largeur du paquet à l'instant t ([3]) :
Cette relation montre l'étalement du paquet d'onde lorsqu'on s'éloigne de l'origine du temps.
La vitesse du paquet d'onde (la vitesse de groupe) est :
Soit T la durée de la simulation. La distance parcourue par le paquet pendant cette durée doit être de l'ordre de la largeur L. Avec les unités utilisées (m=1/2 et ℏ=1), la condition s'écrit :
Si l'on souhaite que l'étalement du paquet d'onde soit négligeable pendant cette durée, il faut respecter la condition suivante :
qui s'écrit aussi :
Par exemple, pour L=1 et σ0=0.05, il faut que k0>200.
Voyons comment choisir l'échantillonnage spatial et temporel. Le pas d'espace doit vérifier :
La condition de Nyquist-Shannon impose une valeur maximale égale à π, mais il faut prévoir une marge à cause de la dispersion Δk. L'évolution dans le temps de la fonction d'onde se fait à la pulsation moyenne :
Avec les unités utilisées, le pas de temps doit donc vérifier :
Pour fixer les pas de temps et d'espace, on peut adopter la relation suivante :
Il suffit alors de vérifier la relation :
Par exemple, pour k0=200 et L=1, il faut N=2000 points. Le nombre de pas de temps nécessaire est :
Avec les valeurs précédentes P=5000.
On voit donc que la simulation d'un paquet d'onde présentant un faible étalement est très exigeante en terme de quantité de calculs.
import numpy
import math
import cmath
class Schrodinger1D:
def __init__(self,L,N):
self.L = L
self.N = N
self.dx = L/(N-1)
self.b = numpy.zeros(N,dtype=numpy.complex)
self.e = numpy.zeros(N,dtype=numpy.complex)
self.x = numpy.zeros(N,dtype=numpy.complex)
self.beta = numpy.zeros(N,dtype=numpy.complex)
self.gamma = numpy.zeros(N,dtype=numpy.complex)
def config(self,dt,V):
N = self.N
self.dt = dt
dx2 = self.dx*self.dx
alpha = 2*dx2/dt
for k in range(1,self.N-1):
self.b[k] = 1j*alpha-dx2*V[k]-2.0
self.e[k] = 1j*alpha+dx2*V[k]+2.0
self.b[0] = 1.0
self.b[N-1] = 1.0
self.beta[0] = self.b[0]
self.gamma[0] = 1.0/self.beta[0]
for k in range(1,N):
self.beta[k] = self.b[k]-self.gamma[k-1]
if self.beta[k]==0:
raise Exception("Impossible de resoudre le systeme ligne "+str(k))
self.gamma[k] = 1.0/self.beta[k]
def iterations(self,psi0,ti,tf):
if psi0.size!=self.N:
raise Exception("Taille de U incorrecte")
psi = psi0.copy()
t = ti
while t<tf:
self.x[0] = (self.e[0]*psi[0]-psi[1])/self.beta[0]
for k in range(1,self.N-1):
self.x[k] = (-psi[k-1]+self.e[k]*psi[k]-psi[k+1]-self.x[k-1])/self.beta[k]
k = self.N-1
self.x[k] = (-psi[k-1]+self.e[k]*psi[k]-self.x[k-1])/self.beta[k]
psi[self.N-1] = self.x[self.N-1]
for k in range(self.N-2,-1,-1):
psi[k] = self.x[k]-self.gamma[k]*psi[k+1]
t += self.dt
return [psi,t]
def V_marche(self,V0):
V = numpy.zeros(self.N)
P = int(self.N/2)
V[P:self.N-1] = V0
return V
def V_barriere(self,V0,largeur):
q = int(largeur/self.dx/2)
V = numpy.zeros(self.N)
P = int(self.N/2)
V[P-q:P+q] = V0
return V
def paquet(self,x0,k0,sigma0):
psi = numpy.zeros(self.N,dtype=numpy.complex)
for k in range(1,self.N-1):
x = self.dx*k
psi[k] = cmath.exp(1j*k0*x)*math.exp(-(x-x0)*(x-x0)/(4*sigma0**2))
return psi
import numpy
from Schrodinger1D import Schrodinger1D
from matplotlib.pyplot import *
N=2000
L=1.0
dx=L/(N-1)
x = numpy.arange(N)*dx
schrodinger = Schrodinger1D(L,N)
V = schrodinger.V_marche(1.0)
l0 = 2e-2
k0 = numpy.pi*2/l0
E=k0**2
x0 = 0.25
sigma0 = 0.04
psi = schrodinger.paquet(x0,k0,sigma0)
figure(figsize=(12,6))
plot(x,psi*numpy.conj(psi),'r')
plot(x,V,'b')
xlabel("x")
ylabel("|psi|^2")
grid()
figA.pdf
On trace le module de la fonction d'onde (densité de probabilité) pour différents instants.
t=0.0
dt=2*dx*dx
v=2*k0
T = 1.0/v
V0 = E
schrodinger.config(dt,V*V0)
[psi,t] = schrodinger.iterations(psi,t,T*0.2)
figure(figsize=(12,6))
plot(x,psi*numpy.conj(psi),'r')
plot(x,V,'b')
xlabel("x")
ylabel("|psi|^2")
grid()
figB.pdf
[psi,t] = schrodinger.iterations(psi,t,T*0.3)
figure(figsize=(12,6))
plot(x,psi*numpy.conj(psi),'r')
plot(x,V,'b')
xlabel("x")
ylabel("|psi|^2")
grid()
figC.pdf
[psi,t] = schrodinger.iterations(psi,t,T*0.5)
figure(figsize=(12,6))
plot(x,psi*numpy.conj(psi),'r')
plot(x,V,'b')
xlabel("x")
ylabel("|psi|^2")
grid()
figD.pdf
N=2000
L=1.0
dx=L/(N-1)
x = numpy.arange(N)*dx
schrodinger = Schrodinger1D(L,N)
V = schrodinger.V_barriere(1.0,0.05)
l0 = 2e-2
k0 = numpy.pi*2/l0
E=k0*k0
x0 = 0.25
sigma0 = 0.04
psi = schrodinger.paquet(x0,k0,sigma0)
On trace le module de la fonction d'onde (densité de probabilité) pour différents instants.
t=0.0
dt=2*dx*dx
v=2*k0
T = 1.0/v
V0=E
schrodinger.config(dt,V*V0)
[psi,t] = schrodinger.iterations(psi,t,T*0.2)
figure(figsize=(12,6))
plot(x,psi*numpy.conj(psi),'r')
plot(x,V,'b')
xlabel("x")
ylabel("|psi|^2")
grid()
figE.pdf
[psi,t] = schrodinger.iterations(psi,t,T*0.3)
figure(figsize=(12,6))
plot(x,psi*numpy.conj(psi),'r')
plot(x,V,'b')
xlabel("x")
ylabel("|psi|^2")
grid()
figF.pdf
[psi,t] = schrodinger.iterations(psi,t,T*0.5)
figure(figsize=(12,6))
plot(x,psi*numpy.conj(psi),'r')
plot(x,V,'b')
xlabel("x")
ylabel("|psi|^2")
grid()
figG.pdf
[psi,t] = schrodinger.iterations(psi,t,T*0.55)
figure(figsize=(12,6))
plot(x,psi*numpy.conj(psi),'r')
plot(x,V,'b')
xlabel("x")
ylabel("|psi|^2")
grid()
figH.pdf