Ho un paio di domande su quanto segue:
Sto provando a risolvere l'equazione di Schrodinger in 1D usando la discretizzazione a pedivella nicolson seguita da invertire la matrice tridiagonale risultante. Il mio problema si è ora evoluto in un problema con condizioni al contorno periodiche e quindi ho modificato il mio codice per utilizzare l'algoritmo Sherman Morrison.
Supponiamo che v
sia il mio RHS in ogni momento quando desidero invertire la matrice tridiagonale. La dimensione di v
è il numero di punti della griglia che ho nello spazio. Quando ho impostato v[0]
e v[-1]
in termini reciproci, come richiesto dalla mia situazione periodica, la mia equazione esplode. Non so dire perché stia succedendo. Sto usando python2.7 e scipy integrato di risolto_bandato per risolvere l'equazione.
Questo mi porta alla mia seconda domanda: ho usato Python perché è la lingua che conosco meglio, ma la trovo piuttosto lenta (anche con le ottimizzazioni offerte da numpy e scipy). Ho provato ad usare il C ++ perché ne ho ragionevolmente familiarità. Ho pensato di usare la GSL che sarebbe stata ottimizzata per BLAS, ma non ho trovato documentazione per creare vettori complessi o risolvere la matrice tridiagonale con vettori così complessi.
Vorrei oggetti nel mio programma poiché ritengo che sarebbe il modo più semplice per me generalizzare in seguito per includere l'accoppiamento tra funzioni d'onda, quindi mi attengo a un linguaggio orientato agli oggetti.
Potrei provare a scrivere a mano il risolutore di matrici tridiagonali, ma ho riscontrato problemi quando l'ho fatto in Python. Man mano che mi sono evoluto in grandi periodi con fasi temporali sempre più precise, l'errore si è accumulato e mi ha dato sciocchezze. Tenendo presente questo, ho deciso di utilizzare i metodi integrati.
Qualsiasi consiglio è molto apprezzato.
EDIT: ecco lo snippet di codice pertinente. La notazione è presa in prestito dalla pagina di Wikipedia sull'equazione della matrice tridiagonale (TDM). v è l'RHS dell'algoritmo a pedale nicolson in ogni fase temporale. I vettori a, bec sono le diagonali del TDM. L'algoritmo corretto per il caso periodico proviene dal Wiki CFD . Ho fatto un piccolo cambio di nome. Quello che hanno chiamato u, v Ho chiamato U, V (in maiuscolo). Ho chiamato q il complemento y la soluzione temporanea e la soluzione effettiva self.currentState. L'assegnazione di v [0] e v [-1] è ciò che sta causando il problema qui e quindi è stato commentato. È possibile ignorare i fattori di gamma. Sono fattori non lineari utilizzati per modellare i condensati di 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