Ich habe einige Fragen zu folgenden Themen:
Ich versuche, die Schrödinger-Gleichung in 1D unter Verwendung der Kurbel-Nicolson-Diskretisierung zu lösen, gefolgt von der Invertierung der resultierenden tridiagonalen Matrix. Mein Problem hat sich nun zu einem Problem mit periodischen Randbedingungen entwickelt, und deshalb habe ich meinen Code geändert, um den Sherman Morrison-Algorithmus zu verwenden.
Angenommen, v
meine RHS befindet sich zu jedem Zeitpunkt, zu dem ich die tridiagonale Matrix invertieren möchte. Die Größe von v
ist die Anzahl der Gitterpunkte, die ich über dem Raum habe. Wenn ich setze v[0]
und v[-1]
in Bezug aufeinander, wie es in meiner periodischen Situation erforderlich ist, explodiert meine Gleichung. Ich kann nicht sagen, warum das passiert. Ich benutze python2.7 und scipy's eingebautes Solve_Banded, um die Gleichung zu lösen.
Dies führt mich zu meiner zweiten Frage: Ich habe Python verwendet, weil es die Sprache ist, die ich am besten kenne, aber ich finde es ziemlich langsam (selbst mit den Optimierungen, die von numpy und scipy angeboten werden). Ich habe versucht, C ++ zu verwenden, da ich damit einigermaßen vertraut bin. Ich dachte, ich würde die GSL verwenden, die BLAS-optimiert wäre, fand aber keine Dokumentation, um komplexe Vektoren zu erstellen oder die tridiagonale Matrix mit solch komplexen Vektoren zu lösen.
Ich möchte Objekte in meinem Programm haben, da ich der Meinung bin, dass dies für mich der einfachste Weg ist, später zu verallgemeinern, um die Kopplung zwischen Wellenfunktionen einzuschließen, sodass ich mich an eine objektorientierte Sprache halte.
Ich könnte versuchen, den tridiagonalen Matrixlöser von Hand zu schreiben, aber ich hatte Probleme, als ich dies in Python tat. Als ich mich über große Zeiten mit immer feineren Zeitschritten weiterentwickelte, häufte sich der Fehler und gab mir Unsinn. Vor diesem Hintergrund habe ich mich für die integrierten Methoden entschieden.
Jeder Rat wird sehr geschätzt.
EDIT: Hier ist das relevante Code-Snippet. Die Notation stammt von der Wikipedia-Seite zur TDM-Gleichung (Tridiagonal Matrix). v ist die RHS des Kurbel-Nicolson-Algorithmus zu jedem Zeitschritt. Die Vektoren a, b und c sind die Diagonalen des TDM. Der korrigierte Algorithmus für den periodischen Fall stammt aus dem CFD-Wiki . Ich habe ein wenig umbenannt. Was sie u, v genannt haben Ich habe U, V (groß geschrieben) genannt. Ich habe q das Komplement, y die temporäre Lösung und die eigentliche Lösung self.currentState genannt. Die Zuordnung von v [0] und v [-1] verursacht hier das Problem und wurde daher auskommentiert. Sie können die Faktoren von Gamma ignorieren. Sie sind nichtlineare Faktoren, die zur Modellierung von Bose-Einstein-Kondensaten verwendet werden.
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