时间依赖的1D薛定谔方程C ++

时间:2018-01-09 21:56:55

标签: c++ physics pde

我用C ++编写了代码,用Thomas算法解决了非调和势V = x ^ 2/2 + lambda * x ^ 4的时间相关1D薛定谔方程。我的代码正在运行,我在Mathematica中对结果进行动画处理,以检查发生了什么。我根据已知的谐波电位解决方案测试代码(我把lambda = 0),但动画显示abs(Psi)随时间变化,我知道这对于谐波电位是不正确的。实际上,我看到它在一个点上它变得不变,但在此之前它是振荡的。

所以我理解我需要在时间间隔内保持波函数的恒定幅度,但我不知道该怎么做,或者我在哪里做错了。 这是我的代码和100个时间步的动画和网格上的100个点。

#include <iostream>
#include <iomanip>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <complex>
#include <fstream>

using namespace std;

// Mandatory parameters
const int L = 1; //length of domain in x direction
const int tmax = 10; //end time
const int nx = 100, nt = 100; //number of the grid points and time steps respectively
double lambda; //dictates the shape of the potential (we can use lambda = 0.0 
               // to test the code against the known solution for the harmonic 
               // oscillator)
complex<double> I(0.0, 1.0); //imaginary unit

// Derived parameters
double delta_x = 1. / (nx - 1);

//spacing between the grid points
double delta_t = 1. / (nt - 1);

//the time step
double r = delta_t / (delta_x * delta_x); //used to simplify expressions for 
                                          // the coefficients of the lhs and 
                                          // rhs of the matrix eqn

// Algorithm for solving the tridiagonal matrix system
vector<complex<double> > thomas_algorithm(vector<double>& a,
                                          vector<complex<double> >& b,
                                          vector<double>& c,
                                          vector<complex<double> >& d)
{

// Temporary wave function
    vector<complex<double> > y(nx + 1, 0.0);

// Modified matrix coefficients
    vector<complex<double> > c_prime(nx + 1, 0.0);
    vector<complex<double> > d_prime(nx + 1, 0.0);

// This updates the coefficients in the first row
    c_prime[0] = c[0] / b[0];
    d_prime[0] = d[0] / b[0];

// Create the c_prime and d_prime coefficients in the forward sweep
    for (int i = 1; i < nx + 1; i++)
    {
        complex<double> m = 1.0 / (b[i] - a[i] * c_prime[i - 1]);
        c_prime[i] = c[i] * m;
        d_prime[i] = (d[i] - a[i] * d_prime[i - 1]) * m;
    }

// This gives the value of the last equation in the system
    y[nx] = d_prime[nx];

// This is the reverse sweep, used to update the solution vector
    for (int i = nx - 1; i > 0; i--)
    {
        y[i] = d_prime[i] - c_prime[i] * y[i + 1];
    }
    return y;
}

void calc()
{

// First create the vectors to store the coefficients
    vector<double> a(nx + 1, 1.0);
    vector<complex<double> > b(nx + 1, 0.0);
    vector<double> c(nx + 1, 1.0);
    vector<complex<double> > d(nx + 1, 0.0);
    vector<complex<double> > psi(nx + 1, 0.0);
    vector<complex<double> > phi(nx + 1, 0.0);
    vector<double> V(nx + 1, 0.0);
    vector<double> x(nx + 1, 0);
    vector<vector<complex<double> > > PSI(nt + 1,
                                          vector<complex<double> >(nx + 1,
                                                                   0.0));
    vector<double> prob(nx + 1, 0);

// We don't have the first member of the left diagonal and the last member 
// of the right diagonal
    a[0] = 0.0;
    c[nx] = 0.0;

    for (int i = 0; i < nx + 1; i++)
    {
        x[i] = (-nx / 2) + i; // Values on the x axis
        // Eigenfunction of  the harmonic oscillator in the ground state
        phi[i] = exp(-pow(x[i] * delta_x, 2) / 2) / (pow(M_PI, 0.25)); 
        // Anharmonic potential
        V[i] = pow(x[i] * delta_x, 2) / 2 + lambda * pow(x[i] * delta_x, 4);
        // The main diagonal coefficients
        b[i] = 2.0 * I / r - 2.0 + V[i] * delta_x * delta_x; 
    }

    double sum0 = 0.0;
    for (int i = 0; i < nx + 1; i++)
    {
        PSI[0][i] = phi[i]; // Initial condition for the wave function
        sum0 += abs(pow(PSI[0][i], 2)); // Needed for the normalization
    }
    sum0 = sum0 * delta_x;

    for (int i = 0; i < nx + 1; i++)
    {
        PSI[0][i] = PSI[0][i] / sqrt(sum0); // Normalization of the initial 
                                            // wave function
    }

    for (int j = 0; j < nt; j++)
    {
        PSI[j][0] = 0.0;
        PSI[j][nx] = 0.0; // Boundary conditions for the wave function
        d[0] = 0.0;
        d[nx] = 0.0; // Boundary conditions for the rhs

// Fill in the current time step vector d representing the rhs
        for (int i = 1; i < nx + 1; i++)
        {
            d[i] = PSI[j][i + 1]
                    + (2.0 - 2.0 * I / r - V[i] * delta_x * delta_x) * PSI[j][i]
                    + PSI[j][i - 1];
        }

// Now solve the tridiagonal system
        psi = thomas_algorithm(a, b, c, d);

        for (int i = 1; i < nx; i++)
        {
            PSI[j + 1][i] = psi[i]; // Assign values to the wave function
        }
        for (int i = 0; i < nx + 1; i++)
        {
            // Probability density of the wave function in the next time step
            prob[i] = abs(PSI[j + 1][i] * conj(PSI[j + 1][i])); 
        }
        double sum = 0.0;
        for (int i = 0; i < nx + 1; i++)
        {
            sum += prob[i] * delta_x;
        }
        for (int i = 0; i < nx + 1; i++)
        {
            // Normalization of the wave function in the next time step
            PSI[j + 1][i] /= sqrt(sum); 
        }
    }

// Opening files for writing the results
    ofstream file_psi_re, file_psi_imag, file_psi_abs, file_potential,
            file_phi0;
    file_psi_re.open("psi_re.dat");
    file_psi_imag.open("psi_imag.dat");
    file_psi_abs.open("psi_abs.dat");

    for (int i = 0; i < nx + 1; i++)
    {
        file_psi_re << fixed << x[i] << "  ";
        file_psi_imag << fixed << x[i] << "  ";
        file_psi_abs << fixed << x[i] << "  ";
        for (int j = 0; j < nt + 1; j++)
        {
            file_psi_re << fixed << setprecision(6) << PSI[j][i].real() << "  ";
            file_psi_imag << fixed << setprecision(6) << PSI[j][i].imag()
                    << "  ";
            file_psi_abs << fixed << setprecision(6) << abs(PSI[j][i]) << "  ";
        }
        file_psi_re << endl;
        file_psi_imag << endl;
        file_psi_abs << endl;
    }

}

int main(int argc, char **argv)
{
    calc();
    return 0;
}

The black line is abs(psi), the red one is Im(psi) and the blue one is Re(psi).

1 个答案:

答案 0 :(得分:0)

(请记住,我的计算物理课程已经十年了)

你说你正在解决一个依赖时间的系统,但我没有看到任何时间依赖性(即使lambda != 0)。在薛定谔方程中,如果势函数不依赖于时间,则不同的方程称为可分离,因为您可以分别求解微分方程的时间分量和空间分量。

在这种情况下的一般解决方案只是时间无关的薛定谔方程乘以exp(-iE/h_bar)的解。当您绘制术语刚成为1的概率的大小时,概率不会随时间而变化。在这些情况下,人们通常只是完全忽略时间组件。

所有这一切都是因为你的潜在功能不依赖于时间,所以你没有解决时间依赖的薛定谔方程。三对角矩阵算法只能用于求解常微分方程,而如果你的潜力取决于时间,你将得到一个偏微分方程,并需要一种不同的方法来解决它。此外,随着时间的推移绘制概率密度很少有趣。

至于你的潜力不恒定的原因,寻找特征值和特征向量的数值方法很少自然地产生归一化特征向量,那么你在计算概率之前手动归一化你的特征向量吗?