"""
""" #! /usr/bin/python # -*- coding: utf-8 -*- doc = """ # Simple Harmonic Oscillator (SHO) # English : # interest of this program : numerical experiment of schrodinger equation # static solution of Harmonic Oscillator # e > v : sinus # e < v : exponential decreasing first but finally diverging. # we can detect the energy of transition # between positive and negative divergence. # Français : # résolution numérique de l'équation de Schroedinger # recherche des états propres (e, phi) # Solution indépendante du temps de l'oscillateur harmonique # La partie e > v : oscille # La partie e < v : décroît exponentiellement mais finit toujours par diverger # l'énergie propre est comprise entre 2 énergies voisines qui divergent en sens contraires """ import math import matplotlib.pyplot def data( ) : # usage : (k, f0, df0, dx, xmin, xmax, ymin, ymax) = data() # point de départ de l'intégration numérique k = 1 # potentiel : v = k x² # solution paire : f0 > 0 et df0 = df0/dx = 0 f0 = 1 df0 = 0 dx = 0.01 # pas d'espace # bornes du graphique (xmin, xmax, ymin, ymax) = (0, 5, -3, 3) return (k, f0, df0, dx, xmin, xmax, ymin, ymax) def normalization_real(phi) : # normalisation de la fonction phi (sous forme de tableau) n = len(phi) phi_integral = 0 for i in range(n) : phi_integral += phi[i] * phi[i] phi_integral = math.sqrt(phi_integral) for i in range(n) : phi[i] /= phi_integral phi[i] /= phi_integral return def schroedinger_step(x0, fx0, dfx0, k, e, dx) : """ # intégration d'un pas d'espace de l'équation de Schroedinger # i hbar part f / part t = - i hbar part^2 f / part x^2 + (V - E) f # on pose toutes les constantes = 1 # on résoud : f''(x) = (V - E) f(x) # avec V(x) = k x^2 # schéma numérique à "vitesse" décalée # comme : f''(x) = [ f'(x+dx) - f'(x) ] / dx # f'(x+dx/2) = f'(x) + (dx/2) f''(x) # comme : f'(x+dx/2) = [ f(x+dx) - f(x) ] / dx # f(x+dx) = f(x) + dx f'(x+dx/2) """ # print("x0, fx0, dfx0, k, e, dx =", (x0, fx0, dfx0, k, e, dx) ) x1 = x0 + dx vx = k * x0**2 d2fx0 = (vx - e) * fx0 dfx1 = dfx0 + dx * d2fx0 fx1 = fx0 + dx * 0.5 * (dfx0 + dfx1) return (x1, fx1, dfx1) def plot_phi(x, phi, divergence, e) : # displays phi(x) matplotlib.pyplot.plot(x, phi) if divergence > 0 : matplotlib.pyplot.text(x[-2], phi[-2]-0.2, f"${e}$") else : matplotlib.pyplot.text(x[-2], phi[-2]-0.2, f"${e}$") return def plot_potential( x, k ) : n = len(x) v = [ None for i in range(n) ] for i in range(n) : v[i] = k * x[i]**2 matplotlib.pyplot.plot(x, v, color="black") matplotlib.pyplot.text(1, 2.5, r"$V=kx^2$") return def schroedinger_real(e, n) : """ # la fonction phi(x) finit toujours par diverger # quand elle est presque nulle, très en dessous du potentiel # (exponentielle divergente) """ # state at x=0 (k, f0, df0, dx, xmin, xmax, ymin, ymax) = data() x0 = 0 divergence = 0 # print("énergie testée : e=", e) (x, phi, dphi) = ([0], [f0], [df0]) for i in range(n) : (x1, f1, df1) = schroedinger_step(x0, f0, df0, k, e, dx) # storage of i+1 for next schroedinger_step x.append( x1 ) phi.append( f1 ) dphi.append( df1 ) # bascule : (x0, f0, df0) = (x1, f1, df1) if abs(f1) > ymax : print(f" e = {e} : divergence de phi pour x={x1}") if f1 > 0 : divergence = 1 else : divergence = -1 # fx1 < 0 break # for i return (x, phi, dphi, divergence) def schroedinger_dichotomie( ): """ # Dans l'équation de Schroedinger pour l'oscillateur harmonique, # on teste différentes énergies de l'intervalle [e_min, e_max] : # la fonction phi diverge plus ou moins vite # Pour encadrer la valeur propre, il faut des divergences de sens opposées """ # state at x=0 (k, f0, df0, dx, xmin, xmax, ymin, ymax) = data() n = int(xmax / dx) print("nombre de pas d'intégration : n=", n) # static schroedinger : matplotlib.pyplot.title("Harmonic Oscillator") matplotlib.pyplot.text(2, 1.1*f0, r"$E$") matplotlib.pyplot.text(2, 0.3*f0, r"$\phi_E(x)$") matplotlib.pyplot.axhline(0, 0, 4.5, color="black") divergence = 0 e_min = 0.95 e_max = 1.05 print("# Test des énergies dans l'intervalle [", e_min, ",", e_max, "]") (x, phi, dphi, divergence_min) = schroedinger_real(e_min, n) plot_phi(x, phi, divergence_min, e_min) (x, phi, dphi, divergence_max) = schroedinger_real(e_max, n) plot_phi(x, phi, divergence_max, e_max) if divergence_min * divergence_max >= 0 : print(" Mauvais encadrement : mêmes divergences") print(f" e_min = {e_min} ; e_max = {e_max}") return e0 = e_min for j in range(10) : e = (e_min + e_max) / 2 divergence_precedente = divergence (x, phi, dphi, divergence) = schroedinger_real(e, n) plot_phi(x, phi, divergence, e) # tracé de l'énergie (droite horizontale ) comparer au potentiel matplotlib.pyplot.plot( [x[0], x[len(x)-1]], [e, e] ) if divergence == divergence_min : e_min = e elif divergence == divergence_max : e_max = e else : # divergence = 0 print(f" e = {e} : pas de divergence avant xmax={xmax}") break print(f" l'énergie e est dans [ {e_min}, {e_max} ]") plot_potential( x, k ) # normalization_real(phi) matplotlib.pyplot.axis( [xmin, xmax, ymin, ymax] ) matplotlib.pyplot.show( ) return schroedinger_dichotomie( ) """"""