다음과 관련하여 몇 가지 질문이 있습니다.
크랭크 nicolson discretization을 사용하여 Schrodinger 방정식을 1D로 풀고 그 결과로 얻은 3 각형 행렬을 뒤집으려고합니다. 내 문제는 이제 주기적 경계 조건과 관련된 문제로 발전했으며 Sherman Morrison 알고리즘을 사용하도록 코드를 수정했습니다.
3 v
각형 행렬을 반전시키고 싶을 때 각 시간 단계에서 RHS가 있다고 가정하십시오 . 의 크기는 v
공간에 대한 격자 점 수입니다. 정기적 인 상황에서 필요에 따라 서로를 설정 v[0]
하고 설정하면 v[-1]
방정식이 폭발합니다. 왜 이런 일이 일어나고 있는지 말할 수 없습니다. 나는 python2.7과 scipy의 내장 solve_banded를 사용하여 방정식을 풀고 있습니다.
이것은 두 번째 질문으로 이어집니다. 파이썬은 내가 가장 잘 알고있는 언어이기 때문에 사용했지만 다소 느립니다 (numpy와 scipy가 제공하는 최적화조차도). 나는 C ++을 합리적으로 익숙해 봤다. BLAS 최적화 된 GSL을 사용한다고 생각했지만 복잡한 벡터를 만들거나 복잡한 값을 가진 벡터로 3 각형 행렬을 해결할 수있는 문서를 찾지 못했습니다.
프로그램에서 객체를 원하고 나중에 파형 함수 사이의 커플 링을 포함하도록 일반화하는 가장 쉬운 방법이라고 생각하므로 객체 지향 언어를 고수하고 있습니다.
나는 tridiagonal matrix solver를 직접 작성해 볼 수는 있지만 파이썬에서 그렇게 할 때 문제가 발생했습니다. 더 세밀하고 세밀한 시간 간격으로 여러 번 진화함에 따라 오류가 누적되어 말도 안됩니다. 이를 염두에두고 내장 된 방법을 사용하기로 결정했습니다.
모든 조언을 부탁드립니다.
편집 : 다음은 관련 코드 스 니펫입니다. 이 표기법은 TDM (Tridiagonal Matrix) 방정식에 대한 Wikipedia의 페이지에서 차용되었습니다. v는 각 시간 단계에서 크랭크 니콜슨 알고리즘의 RHS이다. 벡터 a, b 및 c는 TDM의 대각선입니다. 정기 사건에 대한 올바른 알고리즘 은 CFD Wiki 입니다. 나는 약간의 이름을 변경했습니다. 그들이 U라고 부르는 것, v 나는 U, V (자본)라고 불렀습니다. 나는 임시 솔루션과 실제 솔루션 self.currentState를 보완이라고 불렀다. v [0] 및 v [-1]의 할당은 여기서 문제를 일으키는 원인이므로 주석 처리되었습니다. 감마 요인을 무시할 수 있습니다. 이들은 Bose Einstein Condensates를 모델링하는 데 사용되는 비선형 요인입니다.
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