문제

수행하는 방법 수치 적 통합 Integrand의 하나 이상의 함수가있는 무한 범위에서 1 차원 통합을위한 (수치 방법 및 사용 요법) 1D Quantum Harmonic Oscillator 웨이브 기능. 다른 것 중에서도 고조파 발진기 기준으로 일부 함수의 매트릭스 요소를 계산하고 싶습니다.

N(x) = nN 시간N(x) exp (-x2/2)
여기서 hN(x)입니다 헤르메이트 다항식

Vm, n = int _ {-Infinity}^{Infinity} phi(x) v (x) phiN(x) dx

또한 너비가 다른 양자 고조파 파동이있는 경우.

문제는 파도가 phi입니다N(x) 진동 거동이 있는데, 이는 큰 문제입니다. N, GSL (GNU Scientific Library)의 적응 형 가우스-크론로드 쿼드 레이터와 같은 알고리즘은 계산하는 데 오랜 시간이 걸리며 오류가 크다.

도움이 되었습니까?

해결책

지금은 시간이 조금 짧기 때문에 불완전한 대답입니다. 다른 사람들이 그림을 완성 할 수 없다면 나중에 더 자세한 내용을 제공 할 수 있습니다.

  1. 가능한 한 언제 어디서나 파도의 직교 성을 적용하십시오. 이것은 계산량을 크게 줄여야합니다.

  2. 가능한 모든 것을 분석적으로 수행하십시오. 상수를 들어 올리고, 부품별로 쪼개는 것. 관심 영역을 분리하십시오. 대부분의 물결은 대역 제한이며 관심 영역을 줄이면 작업을 저장하는 데 많은 도움이됩니다.

  3. 사분면 자체의 경우 파도가 세 조각으로 나누고 각각을 별도로 통합하고 싶을 것입니다. 중앙의 진동 비트와 양쪽의 지수로 정리하는 꼬리가 있습니다. 파도가 이상한 경우, 운이 좋으며 꼬리가 서로를 취소하므로 중앙에 대해서만 걱정하면됩니다. 파도가 가득하기 위해서는 하나만 통합하고 두 배가되면 (대칭을위한 Hooray!). 그렇지 않으면 고차 가우스 라게 레어 직교 규칙을 사용하여 꼬리를 통합하십시오. 규칙을 직접 계산해야 할 수도 있습니다. 테이블이 너무 자주 사용되지 않기 때문에 테이블이 Good Gauss-Laguerre 규칙을 나열하는지 모르겠습니다. 규칙의 노드 수가 증가함에 따라 오류 동작을 확인하고 싶을 수도 있습니다. Gauss-Laguerre 규칙을 사용한 지 오랜 시간이 지났으며 Runge의 현상을 전시했는지 기억이 나지 않습니다. 원하는 방법을 사용하여 중앙 부분을 통합하십시오. Gauss-Kronrod는 물론 확실한 선택이지만 Fejer Quarrature (때로는 진동 통합에서 더 잘 작동 할 수있는 많은 수의 노드로 더 잘 확장되는 경우)와 사다리꼴 규칙 (특정 진동 기능으로 놀라운 정확도를 나타냅니다. ). 하나를 골라 시험해보십시오. 결과가 좋지 않으면 다른 방법을 촬영하십시오.

가장 어려운 질문? 거의 ~ 아니다 :)

다른 팁

몇 가지 다른 것들을 추천합니다.

  1. 함수를 유한 도메인으로 변환하여 통합을보다 관리하기 쉽게 만들어보십시오.
  2. 가능한 경우 대칭을 사용하십시오 - 음의 무한대에서 0에서 0으로, 무한대로 두 개의 적분의 합으로 나누고 함수가 대칭 또는 대칭 대칭인지 확인하십시오. 컴퓨팅을 더 쉽게 만들 수 있습니다.
  3. 들여다보다 가우스-라게 레어 웨드 워드 그리고 그것이 당신을 도울 수 있는지 확인하십시오.

그만큼 wkb 근사?

나는 지금이 중 어느 것도 설명하거나 자격을 갖추지 않을 것입니다. 이 코드는 그대로 작성되었으며 아마도 부정확합니다. 그것이 내가 찾고 있던 코드인지 확실하지 않습니다. 몇 년 전에이 문제를 겪었고 아카이브를 검색 할 때 이것을 찾았다는 것을 기억합니다. 출력을 직접 플로팅해야하며 일부 지침이 제공됩니다. 무한 범위의 통합은 내가 해결 한 문제이며 코드를 실행하면 '인피니티'에서 라운드 오프 오류를 나타냅니다 (수치 적으로 큰 의미).

// compile g++ base.cc -lm
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <math.h>

using namespace std;

int main ()
        {
        double xmax,dfx,dx,x,hbar,k,dE,E,E_0,m,psi_0,psi_1,psi_2;
        double w,num;
        int n,temp,parity,order;
        double last;
        double propogator(double E,int parity);
        double eigen(double E,int parity);
         double f(double x, double psi, double dpsi);
        double g(double x, double psi, double dpsi);
        double rk4(double x, double psi, double dpsi, double E);

        ofstream datas ("test.dat");

        E_0= 1.602189*pow(10.0,-19.0);// ev joules conversion
        dE=E_0*.001;
//w^2=k/m                 v=1/2 k x^2             V=??? = E_0/xmax   x^2      k-->
//w=sqrt( (2*E_0)/(m*xmax) );
//E=(0+.5)*hbar*w;

        cout << "Enter what energy level your looking for, as an (0,1,2...) INTEGER: ";
        cin >> order;

        E=0;
        for (n=0; n<=order; n++)
                {
                parity=0;
//if its even parity is 1 (true)
                temp=n;
                if ( (n%2)==0 ) {parity=1; }
                cout << "Energy " << n << " has these parameters: ";
                E=eigen(E,parity);
                if (n==order)
                        {
                        propogator(E,parity);
                        cout <<" The postive values of the wave function were written to sho.dat \n";
                        cout <<" In order to plot the data should be reflected about the y-axis \n";
                        cout <<"  evenly for even energy levels and oddly for odd energy levels\n";
                        }
                E=E+dE;
                }
        }

double propogator(double E,int parity)
        {
        ofstream datas ("sho.dat") ;

        double hbar =1.054*pow(10.0,-34.0);
        double m =9.109534*pow(10.0,-31.0);
        double E_0= 1.602189*pow(10.0,-19.0);
        double dx =pow(10.0,-10);
        double xmax= 100*pow(10.0,-10.0)+dx;
        double dE=E_0*.001;
        double last=1;
        double x=dx;
        double psi_2=0.0;
        double psi_0=0.0;
        double psi_1=1.0;
//      cout <<parity << " parity passsed \n";
        psi_0=0.0;
        psi_1=1.0;
        if (parity==1)
                {
                psi_0=1.0;
                psi_1=m*(1.0/(hbar*hbar))* dx*dx*(0-E)+1 ;
                }

        do
                {
                datas << x << "\t" << psi_0 << "\n";
                psi_2=(2.0*m*(dx/hbar)*(dx/hbar)*(E_0*(x/xmax)*(x/xmax)-E)+2.0)*psi_1-psi_0;
//cout << psi_1 << "=psi_1\n";
                psi_0=psi_1;
                psi_1=psi_2;
                x=x+dx;
                } while ( x<= xmax);
//I return 666 as a dummy value sometimes to check the function has run
        return 666;
        }


   double eigen(double E,int parity)
        {
        double hbar =1.054*pow(10.0,-34.0);
        double m =9.109534*pow(10.0,-31.0);
        double E_0= 1.602189*pow(10.0,-19.0);
        double dx =pow(10.0,-10);
        double xmax= 100*pow(10.0,-10.0)+dx;
        double dE=E_0*.001;
        double last=1;
        double x=dx;
        double psi_2=0.0;
        double psi_0=0.0;
        double psi_1=1.0;
        do
                {
                psi_0=0.0;
                psi_1=1.0;

                if (parity==1)
                        {double psi_0=1.0; double psi_1=m*(1.0/(hbar*hbar))* dx*dx*(0-E)+1 ;}
                x=dx;
                do
                        {
                        psi_2=(2.0*m*(dx/hbar)*(dx/hbar)*(E_0*(x/xmax)*(x/xmax)-E)+2.0)*psi_1-psi_0;
                        psi_0=psi_1;
                        psi_1=psi_2;
                        x=x+dx;
                        } while ( x<= xmax);


                if ( sqrt(psi_2*psi_2)<=1.0*pow(10.0,-3.0))
                        {
                        cout << E << " is an eigen energy and " << psi_2 << " is psi of 'infinity'  \n";
                        return E;
                        }
                else
                        {
                        if ( (last >0.0 && psi_2<0.0) ||( psi_2>0.0 && last<0.0) )
                                {
                                E=E-dE;
                                dE=dE/10.0;
                                }
                        }
                last=psi_2;
                E=E+dE;
                } while (E<=E_0);
        }

이 코드가 올바른 것처럼 보이고, 잘못되고, 흥미 롭거나 당신이 구체적인 질문이 있으면 묻고 대답하겠습니다.

저는 물리학을 전공하는 학생이며 문제도 발생했습니다. 요즘 나는이 질문에 대해 계속 생각하고 내 자신의 대답을 얻습니다. 이 질문을 해결하는 데 도움이 될 수 있다고 생각합니다.

1. GSL에는 진동 함수 인 Qawo & Qawf를 통합하는 데 도움이 될 수있는 기능이 있습니다. 어쩌면 값을 설정할 수 있습니다. . 통합은 견인 부품으로 분리 될 수 있습니다. [0,] 그리고 [, pos_infinity]. 첫 번째 간격으로 원하는 GSL 통합 기능을 사용할 수 있으며 두 번째 간격으로 Qawo 또는 Qawf를 사용할 수 있습니다.

2. 또는 기능을 상한으로 통합 할 수 있습니다. , 그것은 [0,]. 따라서 통합은 Gauss Legendry 메소드를 사용하여 계산할 수 있으며 이는 GSL에서 제공됩니다. 실제 가치와 계산 된 값 사이에 약간의 차이가있을 수 있지만 설정하는 경우 제대로 차이를 무시할 수 있습니다. 차이가 원하는 정확도보다 작다면. 그리고 GSL 함수를 사용하는이 방법은 한 번만 호출되며 여러 번만 사용할 수 있습니다. 반환 값은 포인트이고 해당 가중치이며 통합은 F (xi)*wi의 합이므로 자세한 내용은 Gauss Legendre를 검색 할 수 있습니다. Wikipedia의 Quadrature. 다중 및 추가 작업은 통합보다 훨씬 빠릅니다.

3. Infinity Area 통합을 계산할 수있는 함수가 있습니다. QAGI는 GSL-USER 가이드에서 검색 할 수 있습니다. 그러나 이것은 통합을 계산해야 할 때마다 호출되며, 이로 인해 시간이 많이 걸릴 수 있지만 프로그램에서 얼마나 오래 사용할 것인지 잘 모르겠습니다.

나는 내가 제안한 No.2 선택을 제안한다.

N = 100 미만의 고조파 오실레이터 기능으로 작업하려면 시도해 볼 수 있습니다.

http://www.mymathlib.com/quadrature/gauss_hermite.html

이 프로그램은 100 개의 0과 무게 (H_100의 0)와 함께 Gauss-Hermite Quarration을 통해 적분을 계산합니다. Hermite_100을 넘어 서면 적분은 정확하지 않습니다.

이 통합 방법을 사용하여 계산하려는 내용을 정확하게 계산하는 프로그램을 작성했으며 상당히 잘 작동합니다. 또한, 헤르 메이트-폴리 릭 제로의 점근 형태를 사용하여 n = 100을 넘어선 방법이있을 수 있지만 나는 그것을 조사하지 않았다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top