Równanie Schrodingera z okresowymi warunkami brzegowymi

9

Mam kilka pytań dotyczących następujących kwestii:

Próbuję rozwiązać równanie Schrodingera w 1D, używając dyskretyzacji korbowego nicolsonu, a następnie odwracając otrzymaną macierz tridiagonalną. Mój problem przekształcił się teraz w problem z okresowymi warunkami brzegowymi, dlatego zmodyfikowałem swój kod, aby używać algorytmu Shermana Morrisona.

Załóżmy, że vjest mój RHS na każdym etapie, kiedy chcę odwrócić matrycę tridiagonal. Rozmiar vto liczba punktów siatki, które mam nad przestrzenią. Kiedy ustawiam v[0]i v[-1]pod względem siebie nawzajem, jak jest to wymagane w mojej okresowej sytuacji, moje równanie wybuchnie. Nie umiem powiedzieć, dlaczego tak się dzieje. Korzystam z Python2.7 i wbudowanego rozwiązania Scipy Soln_banded, aby rozwiązać równanie.

To prowadzi mnie do drugiego pytania: użyłem Pythona, ponieważ jest to język, który znam najlepiej, ale uważam, że jest on raczej powolny (nawet w przypadku optymalizacji oferowanych przez Numpy i Scipy). Próbowałem używać C ++, ponieważ znam go dość dobrze. Pomyślałem, że użyję GSL, który byłby zoptymalizowany za pomocą BLAS, ale nie znalazłem dokumentacji do tworzenia złożonych wektorów lub rozwiązywania macierzy tridiagonalnej za pomocą wektorów o złożonych wartościach.

Chciałbym mieć obiekty w moim programie, ponieważ uważam, że byłby to dla mnie najłatwiejszy sposób na uogólnienie w celu włączenia sprzężenia między funkcjami falowymi, dlatego trzymam się języka zorientowanego obiektowo.

Mógłbym spróbować napisać trójwymiarowy solver macierzy ręcznie, ale napotkałem problemy, kiedy to zrobiłem w Pythonie. Gdy ewoluowałem przez długi czas z coraz to krótszymi krokami czasowymi, błąd narastał i dał mi bzdury. Mając to na uwadze, postanowiłem skorzystać z wbudowanych metod.

Wszelkie porady są mile widziane.

EDYCJA: Oto odpowiedni fragment kodu. Notacja została zapożyczona ze strony Wikipedii na równaniu macierzy tridiagonal (TDM). v jest RHS algorytmu korbowego nicolsona na każdym etapie. Wektory a, b i c są przekątnymi TDM. Poprawiony algorytm dla przypadku okresowego pochodzi z Wiki CFD . Zmieniłem trochę nazwę. To, co nazwali u, v Nazwałem U, V (wielką literą). Nazwałem q uzupełnienie, y rozwiązanie tymczasowe i rzeczywiste rozwiązanie self.currentState. Przypisanie v [0] i v [-1] jest przyczyną problemu i dlatego zostało skomentowane. Możesz zignorować czynniki gamma. Są to czynniki nieliniowe stosowane do modelowania kondensatów Bosego Einsteina.

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
WiFO215
źródło
3
Brzmi (na pierwszy rzut oka) jak błąd w twoich okresowych warunkach brzegowych. Chcesz opublikować fragment kodu?
David Ketcheson
2
Witamy w Stack Exchange! W przyszłości, jeśli masz kilka pytań, możesz zadać je osobno.
Dan
Ponadto: Co dokładnie masz na myśli mówiąc „ustaw v [0] i v [-1] pod względem siebie nawzajem”? Czy ustawiasz elementy wektorowe równe sobie po ułożeniu, czy też używasz elementu nietypowego do łączenia ich?
Dan
Dodałem swój kod powyżej. Jeśli coś jest niejasne, daj mi znać. Będę pamiętać, aby następnym razem zamieścić osobne pytania.
WiFO215,
Dzięki! Odczytywanie kodu jest nieco trudne ze względu na formatowanie (bardzo długie linie). Również komentowanie tej części, na którą chcesz zwrócić uwagę, jest mylące. Cod zapisujesz rozwiązywane równania (z MathJax) przy użyciu tej samej notacji co kod?
David Ketcheson

Odpowiedzi:

2

Drugie Pytanie

Kod wywołujący Scipy / Numpy jest zwykle szybki tylko wtedy, gdy można go wektoryzować; nie powinieneś mieć nic „powolnego” w pętli pytona. Nawet wtedy jest prawie nieuniknione, że będzie co najmniej trochę wolniejsze niż coś używającego podobnej biblioteki w skompilowanym języku.

for i in np.arange(0,self.spaceArraySize-1):
            v[i] = Y*self.currentState[i+1] + (1-2*Y)*self.currentState[i]   ...
            b[i] = 1+2*Y + 1j*0.5*self.timeStep*potential[i] + ...

To mam na myśli przez „powolne w pętli pytona”. Python forjest niedopuszczalnie wolny dla większości aplikacji numerycznych, a Scipy / Numpy w ogóle na to nie wpływają. Jeśli zamierzasz używać Pythona, ta wewnętrzna pętla powinna być wyrażona jako jedna lub dwie funkcje Numpy / Scipy, które te biblioteki mogą, ale nie muszą, zapewniać. Jeśli nie zapewniają czegoś, co pozwala na iterację po takich tablicach i dostęp do sąsiednich elementów, python jest niewłaściwym narzędziem do tego, co chcesz zrobić.

Robisz też inwersję zamiast rozwiązania wektor macierzowy. Inwersja macierzy, po której następuje mnożenie macierz-wektor, jest znacznie wolniejsza niż rozwiązanie macierz-wektor. To prawie na pewno spowalnia Twój kod bardziej niż cokolwiek innego.

Jeśli chcesz używać C / C ++, GSL jest trochę brakuje, jeśli chodzi o złożoną algebrę liniową. Polecam albo użyć bezpośrednio BLAS lub LAPACK, albo biblioteki takiej jak PETSc lub Trilinos. Jeśli masz zainstalowany MKL, możesz go również użyć. Możesz także sprawdzić Fortran 2008, który jest zorientowany obiektowo.

Twoje macierze są rzadkie, więc upewnij się, że używasz rzadkich bibliotek.

Powiedziałbym również, że to, co tu robisz, wydaje się na tyle niskie, że orientacja obiektowa prawdopodobnie nie powinna być twoim głównym zmartwieniem. Macierz Fortran 90+ jest prawdopodobnie całkiem dobrym dopasowaniem do tego, czego potrzebujesz, a kompilatory F90 mogą automatycznie zrównoleglać niektóre pętle.

Możesz także wypróbować Octave lub Matlab, które mają tę sparse()funkcję. Przy prawidłowym użyciu powinny one działać dość szybko.

Dan
źródło
Z pewnością przyjrzę się Fortranowi 2008. Mam już matrycę „prawie tridiagonalną”. Wspomniałem powyżej, że korzystam z algorytmu Shermana Morrisona.
WiFO215,
AKTUALIZACJA: Próbowałem przeczytać na ScaLAPACK, ponieważ wygląda bardzo interesująco. Pozwala na odwrócenie macierzy za pomocą bzyczącego słowa, które słyszałem dużo „równolegle”. Wiem tylko, że używa wszystkich moich procesorów i dlatego działa szybciej, ale poza tym nie rozumiem, o co chodzi. Biorąc pod uwagę podstawy fizyki, jedyną ekspozycją na informatykę, jaką mam, jest 101 kursów w języku Python i C. Nauka korzystania z tego zajmie trochę czasu. Sama dokumentacja nie nadaje się do czytania.
WiFO215,
AKTUALIZACJA 2: Człowieku! Ta gra ScaLAPACK wygląda na bardzo skomplikowaną. Nie rozumiem głowy ani ogona tego, co jest na stronie. Po prostu płynę z wszystkimi informacjami.
WiFO215,
AKTUALIZACJA 3: W porządku, przejrzałem inne rekomendacje PETSc i Trilinos. Moje ostatnie wezwanie jest takie, że nie sądzę, że będę ich teraz używać, ponieważ wyglądają na bardzo skomplikowane. To nie znaczy, że ich nie przeczytam. Zacznę je teraz czytać, ale zanim zrozumiem i będę w stanie je wdrożyć, miną miesiące. Otworzę osobny wątek na moje pytania na powyższe pytania, ponieważ mam z tym trudności, ale to na później. Teraz wracam do odpowiedzi tylko na pytanie 1.
WiFO215,
Zaktualizowałem swoją odpowiedź.
Dan