J'ai quelques questions concernant les points suivants:
J'essaie de résoudre l'équation de Schrodinger en 1D en utilisant la discrétisation de manivelle nicolson suivie de l'inversion de la matrice tridiagonale résultante. Mon problème a maintenant évolué vers un problème avec des conditions aux limites périodiques et j'ai donc modifié mon code pour utiliser l'algorithme Sherman Morrison.
Supposons que v
mon RHS soit à chaque pas de temps lorsque je souhaite inverser la matrice tridiagonale. La taille de v
est le nombre de points de grille que j'ai sur l'espace. Quand je me mets v[0]
et v[-1]
en termes les uns des autres comme cela est requis dans ma situation périodique, mon équation explose. Je ne peux pas dire pourquoi cela se produit. J'utilise python2.7 et le module de résolution intégré de scipy pour résoudre l'équation.
Cela m'amène à ma deuxième question: j'ai utilisé python parce que c'est le langage que je connais le mieux, mais je le trouve plutôt lent (même avec les optimisations offertes par numpy et scipy). J'ai essayé d'utiliser C ++ car je le connais assez bien. J'ai pensé utiliser le GSL qui serait optimisé pour BLAS, mais je n'ai trouvé aucune documentation pour créer des vecteurs complexes ou résoudre la matrice tridiagonale avec des vecteurs de valeur complexes.
Je voudrais des objets dans mon programme car je pense que ce serait le moyen le plus simple pour moi de généraliser plus tard pour inclure le couplage entre les fonctions d'onde, donc je m'en tiens à un langage orienté objet.
Je pouvais essayer d'écrire le solveur de matrice tridiagonale à la main, mais j'ai rencontré des problèmes quand je l'ai fait en python. Alors que j'évoluais sur de grandes périodes avec des pas de temps de plus en plus fins, l'erreur s'est accumulée et m'a donné un non-sens. Gardant cela à l'esprit, j'ai décidé d'utiliser les méthodes intégrées.
Tout conseil est fort apprécié.
EDIT: voici l'extrait de code correspondant. La notation est empruntée à la page de Wikipedia sur l'équation de la matrice tridiagonale (TDM). v est le RHS de l'algorithme crank nicolson à chaque pas de temps. Les vecteurs a, b et c sont les diagonales du TDM. L'algorithme corrigé pour le cas périodique provient du CFD Wiki . J'ai fait un petit changement de nom. Ce qu'ils ont appelé u, v J'ai appelé U, V (en majuscule). J'ai appelé q le complément, y la solution temporaire et la solution réelle self.currentState. L'affectation de v [0] et v [-1] est la cause du problème ici et a donc été commentée. Vous pouvez ignorer les facteurs de gamma. Ce sont des facteurs non linéaires utilisés pour modéliser les condensats de Bose Einstein.
for T in np.arange(self.timeArraySize):
for i in np.arange(0,self.spaceArraySize-1):
v[i] = Y*self.currentState[i+1] + (1-2*Y)*self.currentState[i] + Y*self.currentState[i-1] - 1j*0.5*self.timeStep*potential[i]*self.currentState[i] - self.gamma*1j*0.5*self.timeStep*(abs(self.currentState[i])**2)*self.currentState[i]
b[i] = 1+2*Y + 1j*0.5*self.timeStep*potential[i] + self.gamma*self.timeStep*1j*0.5*(abs(self.currentState[i])**2)
#v[0] = Y*self.currentState[1] + (1-2*Y)*self.currentState[0] + Y*self.currentState[-1] - 1j*0.5*self.timeStep*potential[0]*self.currentState[0]# - self.gamma*1j*0.5*self.timeStep*(abs(self.currentState[0])**2)*self.currentState[0]
#v[-1] = Y*self.currentState[0] + (1-2*Y)*self.currentState[-1] + Y*self.currentState[-2] - 1j*0.5*self.timeStep*potential[-1]*self.currentState[-1]# - self.gamma*1j*0.5*self.timeStep*(abs(self.currentState[-1])**2)*self.currentState[-1]
b[0] = 1+2*Y + 1j*0.5*self.timeStep*potential[0] + self.gamma*self.timeStep*1j*0.5*(abs(self.currentState[0])**2)
b[-1] = 1+2*Y + 1j*0.5*self.timeStep*potential[-1] + self.gamma*self.timeStep*1j*0.5*(abs(self.currentState[-1])**2)
diagCorrection[0], diagCorrection[-1] = - b[0], - c[-1]*a[0]/b[0]
tridiag = np.matrix([
c,
b - diagCorrection,
a,
])
temp = solve_banded((1,1), tridiag, v)
U = np.zeros(self.spaceArraySize, dtype=np.complex64)
U[0], U[-1] = -b[0], c[-1]
V = np.zeros(self.spaceArraySize, dtype=np.complex64)
V[0], V[-1] = 1, -a[0]/b[0]
complement = solve_banded((1,1), tridiag, U)
num = np.dot(V, temp)
den = 1 + np.dot(V, complement)
self.currentState = temp - (num/den)*complement