周期的な境界条件を持つシュレディンガー方程式


9

以下について、いくつか質問があります。

私は、クランクニコルソンの離散化を使用して1Dでシュレディンガー方程式を解き、続いて結果の三重対角行列を反転させようとしています。私の問題は周期的な境界条件の問題に発展したため、シャーマンモリソンアルゴリズムを使用するようにコードを変更しました。

仮定しv、私は三重対角行列を反転したいとき、各時間ステップでの私のRHSです。のサイズvは、スペース上にあるグリッドポイントの数です。私が設定するv[0]v[-1]、私の定期的な状況で必要とされるように、お互いに関して、私の方程式は爆発します。なぜこれが起こっているのかわかりません。私はpython2.7とscipyの組み込みのsolve_bandedを使用して方程式を解いています。

これは私の2番目の質問につながります。Pythonは私が最もよく知っている言語であるため使用しましたが、(numpyとscipyによって提供される最適化を使用しても)かなり遅いと感じます。C ++に慣れているので、C ++を使用してみました。BLAS最適化されるGSLを使用すると思いましたが、複雑なベクトルを作成したり、そのような複雑な値のベクトルで三重対角行列を解いたりするためのドキュメントが見つかりませんでした。

私は、波動関数間の結合を含めるために後で一般化する最も簡単な方法であり、したがってオブジェクト指向言語に固執していると思うので、プログラムにオブジェクトを入れたいと思います。

三重対角行列ソルバーを手動で作成することもできましたが、Pythonで作成すると問題が発生しました。細かく細かいタイムステップで長い時間をかけて進化していくと、エラーが蓄積し、無意味なものになってしまいました。これを念頭に置いて、組み込みのメソッドを使用することにしました。

アドバイスは大歓迎です。

編集:関連するコードスニペットは次のとおりです。この表記法は、Wikipediaのページの三重対角行列(TDM)方程式から借用したものです。vは、各タイムステップでのクランクニコルソンアルゴリズムのRHSです。ベクトルa、b、cはTDMの対角線です。定期的なケースの修正されたアルゴリズムは、CFD Wikiからのものです。少し名前を変更しました。彼らがu、vと呼んでいるものをU、V(大文字)と呼んでいます。私はqを補数、yを一時的なソリューション、実際のソリューションをself.currentStateと呼んでいます。ここでv [0]とv [-1]の割り当てが問題を引き起こしているため、コメント化されています。ガンマの要素は無視してかまいません。これらは、ボーズアインシュタイン凝縮のモデル化に使用される非線形因子です。

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

3
(一見すると)周期的な境界条件のバグのように聞こえます。コードスニペットを投稿しますか?
David Ketcheson、2012年

2
Stack Exchangeへようこそ!今後、複数の質問がある場合は、個別に質問することをお勧めします。
Dan

また、「v [0]とv [-1]を互いに関して設定する」とはどういう意味ですか?ソルバの後でベクトル要素を互いに等しく設定していますか、それとも非対角要素を使用してそれらを結合していますか?
Dan

上記のコードを追加しました。不明な点がありましたらお知らせください。次回は別の質問を投稿することを忘れないでください。
WiFO215 2012年

ありがとう!書式設定(非常に長い行)のため、コードを読み取るのが少し難しいです。また、注目してもらいたい部分をコメントアウトするのはややこしいです。コードと同じ表記法を使用して(MathJaxで)解く方程式を書き留めますか?
David Ketcheson、2012年

回答:


2

二番目の質問

Scipy / Numpyを呼び出すコードは通常、ベクトル化できる場合にのみ高速です。Pythonループの内部に「遅い」ものはありません。それでも、コンパイルされた言語で同様のライブラリを使用する場合よりも少なくとも少し遅くなることは避けられません。

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] + ...

これは、「Pythonループで遅い」という意味です。forほとんどの数値アプリケーションではPythonの速度が許容できないほど遅く、Scipy / Numpyはこれにまったく影響しません。Pythonを使用する場合、この内部ループは、1つまたは2つのNumpy / Scipy関数として表現する必要があります。これらのライブラリは、これらのライブラリによって提供される場合と提供されない場合があります。このような配列を繰り返し処理して隣接する要素にアクセスできるような機能を提供しない場合、Pythonは目的のツールとして不適切です。

また、行列とベクトルの解決ではなく、反転を行っています。行列の反転とそれに続く行列とベクトルの乗算は、行列とベクトルの解決よりもはるかに低速です。これはほぼ間違いなく、コードの速度が何よりも遅くなることです。

C / C ++を使用したい場合、GSLは複雑な線形代数に関しては足りません。BLASまたはLAPACKを直接使用するか、PETScやTrilinosなどのライブラリを使用することをお勧めします。MKLがインストールされている場合は、それも使用できます。オブジェクト指向のFortran 2008も調べてみてください。

行列はスパースなので、スパースライブラリを使用していることを確認する必要があります。

また、あなたがここで行っていることは、オブジェクト指向がおそらくあなたの主な関心事ではないように十分に低レベルであるように思われます。Fortran 90+配列は、おそらく必要なものにかなり一致し、F90コンパイラは一部のループを自動並列化できます。

また、sparse()機能を備えたOctaveまたはMatlabをチェックアウトすることもできます。これらを適切に使用すれば、かなり高速に実行できるはずです。


私は確かにFortran 2008を調べます。私はすでに「ほぼ三重対角」行列を得ています。シャーマンモリソンアルゴリズムを使用していることを前述しました。
WiFO215 2012年

更新:ScaLAPACKは非常に興味深く見えるので、それを読み進めようと試みています。これは、私が「並行して」よく聞いている話題の単語を使用して行列を反転させることができます。私が知っているのは、すべてのプロセッサを使用しているため高速に動作するということだけですが、それを超えると、それが何であるかがわかりません。物理学の背景から来て、私が持っているコンピューティングへの唯一の露出は、PythonとCの101コースです。これを使用する方法を学ぶには時間がかかります。ドキュメント自体は、きれいに読むには向いていません。
WiFO215 2012年

更新2:男!このScaLAPACKは本当に複雑に見えます。ウェブサイトに何が表示されているのかよく分からない。私は単にすべての情報を泳いでいます。
WiFO215 2012年

更新3:さて、私は他の推奨事項PETScとTrilinosを通過しました。私の最後の呼びかけは、これらは非常に複雑に見えるので、今は使用しないと思います。それは私がそれらを読まないという意味ではありません。今から読み始めますが、理解して実装できるようになるまでには、数か月は過ぎていたでしょう。上の問題については、問題が発生しているため、別のスレッドを開いて説明しますが、それは後で説明します。今、私は質問1への取り組みに戻っています
WiFO215

回答を更新しました。
Dan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.