加速解决一维Schrödinger方程的C ++代码

时间:2019-03-03 23:05:11

标签: c++ performance

在下面,您将看到我的c ++代码,它使用Numerov's method解决了一维Schrödinger方程。但是我有两个问题:

  1. 当我增加盒子的尺寸时,基态的波动函数将为零,问题出在归一化,我不知道为什么。
  2. 它太慢了,我需要将盒子增加到足够大,关于如何加快速度的任何想法都很棒。

这是我的代码:

#include <iostream>
#include <math.h>
#include <fstream>
#include <string>
#include <iomanip>
#include <sstream>
using namespace std;

#define pi 3.1415926535897932384626433

class ID_TISE{

    public:
        ID_TISE(int N_graid, int x_min, int x_max, double dx, double e_tr, double de, double e_up, double m, double h_bar, double c);
        ~ID_TISE();

        //functions
        double Potential(char, int);
        double PotentialIon(char, int);
        void Setk2(double *k2, double E, int N, char lr);
        void Numerov(double *psi, double *k2, int N);
        double diff_slope(double e_tr,int N_L, int N_R);;
        string string_precision(int, int);
        double x(char lr, int index);
        void Numerov_Solver(double*, double*);
        void id_tise();

        int N_graid ;

        double x_min;
        double x_max;
        double dx;

        //set trial energy
        double e_tr;
        double de;
        double e_up;
        int N_E = 10000;

        //constant
        double m ;
        double h_bar;
        double c; // second point of the wavefunctions

        //array
        double *psi_l = NULL;
        double *psi_r = NULL;
        double *k2_l = NULL;
        double *k2_r = NULL;

};

ID_TISE::ID_TISE(int N_graid, int x_min, int x_max, double dx, double e_tr, double de, double e_up, double m, double h_bar, double c){

    this->N_graid = N_graid;
    this->x_min = x_min;
    this->x_max = x_max;
    this->dx = dx;
    this->e_tr =e_tr;
    this->de = de;
    this->e_up = e_up;
    this->m = m;
    this->h_bar=h_bar;
    this->c=c;

    psi_l = new double[N_graid];
    psi_r = new double[N_graid];
    k2_l = new double[N_graid];
    k2_r = new double[N_graid];

}

ID_TISE::~ID_TISE(){

    delete[] psi_l;
    delete[] psi_r;
    delete[] k2_l;
    delete[] k2_r;

}

void ID_TISE::id_tise(){

    ofstream fout;

    int im = int(N_graid/2);
    int N_R = N_graid - im + 2;
    int N_L = im + 2;

    //initialization left solution
    psi_l[0] = 0.0;
    psi_l[1] = c;
    //initialization right solution
    psi_r[0] = 0.0;
    psi_r[1] = c;

    int ii = 0, inode = 0, inodeUp = 1;
    while(e_tr < e_up){
        double ds1 = diff_slope(e_tr,N_L,N_R);
        e_tr += de;
        double ds2 = diff_slope(e_tr,N_L,N_R);

        if(ds1*ds2 < 0.0){

            if(e_tr < -9.0e-7 || e_tr > 9.0e-7){ // to prevent reaching to E = 0
                cout <<"E_"<<ii++ <<" = "<< e_tr << endl;
                Normalizer(psi_r,im);
                Normalizer(psi_l,im);

                fout.open("psi_"+string_precision(ii,0)+ ".dat");

                if(e_tr < 0){

                    if(inode%2 != 0.){
                            for(int i = 0; i < im; i++)
                                fout << x('l',i) << "\t" << -psi_l[i] << endl;
                    }
                    else{
                        for(int i = 0; i < im; i++)
                            fout << x('l',i) << "\t" << psi_l[i] << endl;
                    }
                    for(int i = im-1; i > -1; i--)
                        fout << x('r',i) << "\t" << psi_r[i] << endl;

                    inode++;
                }
                else{

                    if(inodeUp%2 == 0.){
                        for(int i = 0; i < im; i++)
                            fout << x('l',i) << "\t" << -psi_l[i] << endl;
                    }
                    else{
                        for(int i = 0; i < im; i++)
                            fout << x('l',i) << "\t" << psi_l[i] << endl;
                    }
                    for(int i = im-1; i > -1; i--)
                        fout << x('r',i) << "\t" << psi_r[i] << endl;

                    inodeUp++;

                }

                fout.close();
            }
        }
        else continue;
    }
}

void ID_TISE::Normalizer(double *psi,int N){

    double sum = 0.;

    for(int i=0 ; i<N ; i++)
        sum += psi[i]*psi[i]*dx;

    sum=sqrt(sum);

    for(int i=0 ; i<N ; i++){
        psi[i]=psi[i]/sum;
    }
}


void ID_TISE::Numerov(double *psi, double *k2 , int N){

    double h12 = (dx*dx)/12.;
    for(int i = 1; i < N; i++){
        psi[i+1] = (2.*(1.-5.*h12*k2[i])*psi[i] - (1. + h12*k2[i-1])*psi[i-1])/(1. + h12*k2[i+1]);
    }
}

void ID_TISE::Setk2(double *k2, double E, int N, char lr){
    for(int i = 0; i < N; i++){
        if(E > 0)
            k2[i] = (2.*m/(h_bar*h_bar))*(E - PotentialIon(lr,i));
        else
            k2[i] = (2.*m/(h_bar*h_bar))*(E - Potential(lr,i));
    }
}

double ID_TISE::Potential(char lr, int index){
    return -1./sqrt(x(lr, index)*x(lr, index)+2.);
}

double ID_TISE::PotentialIon(char lr, int index){
    return 0.;
}

double ID_TISE::x(char lr, int index){
    if(lr == 'l')
        return x_min + (index)*dx; // dx = h
    else
        return x_max - (index)*dx; // the right solution
}

double ID_TISE::diff_slope(double e_tr, int N_L, int N_R){

    double dslope;
    //initialization left solution
    psi_l[0] = 0.0;
    psi_l[1] = c;
    //initialization right solution
    psi_r[0] = 0.0;
    psi_r[1] = c;
    Setk2(k2_l, e_tr, N_L, 'l');
    Setk2(k2_r, e_tr, N_R, 'r');
    Numerov(psi_l, k2_l, N_L);
    Numerov(psi_r, k2_r, N_R);
    double y_m = (psi_l[N_L-1]+psi_r[N_R-1])/2.;
    dslope = (2.*y_m - psi_l[N_L - 3] - psi_r[N_R - 3])/(dx*psi_r[N_R - 2]);

    return dslope;

}


string ID_TISE::string_precision(int value, int n_digits){

    if(n_digits < 6) n_digits = 6;
    ostringstream out;
    out << fixed<<setprecision(n_digits) << value;
    return out.str();
}


int main(){

    int N_graid = 500000;

    double x_min = -500;
    double x_max = -x_min;
    double dx = (x_max - x_min)/(N_graid-1);

    //set trial energy
    double e_tr = -0.6;
    double de = 0.000001;
    double e_up = 1.0;

    //constant
    double m = 1.;
    double h_bar = 1.;
    double c = 0.00000001; // second point of the wavefunctions
    ID_TISE &id_tise = *(new ID_TISE(N_graid,x_min,x_max,dx,e_tr,de,e_up,m,h_bar,c));
    id_tise.id_tise();


}

0 个答案:

没有答案