كيفية القيام التكامل العددي مع التذكئ المذبذب التوافقي الكمومي؟

StackOverflow https://stackoverflow.com/questions/599619

سؤال

كيف تفعل تكامل رقمي (ما الطريقة العددية، وما الحيل التي يجب استخدامها) لإدماج أحادي الأبعاد على نطاق لانهائي، حيث توجد وظيفة واحدة أو أكثر في Intrand Intrand 1d الكم المذبذب التوافقي وظائف الموجة. من بين أمور أخرى أريد حساب عناصر مصفوفة بعض الوظائف في أساس مذبذب التوافقي:

فاي.ن(س) = نن حاءن(x) exp (-x2/2)
حيث Hن(س) هو متعدد الحدود النباتية

الخامسم، ن = IN _ {- اللانهاية} ^ {اللانهاية} فايم(x) v (x) phiن(X) DX

أيضا في حالة وجود موجزات متناسقة الكم مع عرض مختلف.

المشكلة هي أن wavefunctions phiن(س) لها سلوك تذبذب، وهو مشكلة كبيرة ن, ، والخوارزمية مثل Teaptive Gauss-Kronrod Trustrature من GSL (مكتبة GNU العلمية) تستغرق وقتا طويلا لحسابها، ولديها أخطاء كبيرة.

هل كانت مفيدة؟

المحلول

إجابة غير مكتملة، لأنني قصيرة بعض الشيء في الوقت الحالي؛ إذا لم يتمكن الآخرون من إكمال الصورة، يمكنني تقديم المزيد من التفاصيل في وقت لاحق.

  1. قم بتطبيق متعامدا على Wavefunctions كلما وحيثما أمكن ذلك. يجب أن يقلل هذا بشكل كبير من كمية الحساب.

  2. هل تحليليا كل ما تستطيع. ثوابت رفع، تقسيم يتكلم بواسطة أجزاء، أيا كان. عزل المنطقة ذات الاهتمام؛ معظم التطهير محدودة الفرقة، وتقليل مساحة الاهتمام سوف تفعل الكثير لحفظ العمل.

  3. بالنسبة للتركيبات نفسها، ربما ترغب في تقسيم Wavefunctions إلى ثلاث قطع ودمج كل منها بشكل منفصل: بت أتاتيجية في المركز بالإضافة إلى ذيول التفضيل بشكل كبير على جانبي. إذا كان اللوحة الغريبة، فستحصل على محظوظ وستغلي ذيول بعضها البعض، مما يعني أنك لا داعي للقلق فقط بشأن المركز. حتى Wavefunctions، عليك فقط دمج واحد ومضاعفة (الصيحة للتماثل!). خلاف ذلك، قم بدمج ذيول باستخدام قاعدة رتبة غاوس-Laguerre عالية ترتيب. قد تضطر إلى حساب القواعد بنفسك؛ لا أعرف إذا سرد الجداول قواعد Gauss-Laguerre جيدة، لأنها لا تستخدم في كثير من الأحيان. ربما ترغب أيضا في التحقق من سلوك الخطأ حيث يرتفع عدد العقد في القاعدة؛ لقد مضى وقت طويل منذ أن استخدمت قواعد غاوس-Laguerre ولا أتذكر ما إذا كانت تظهر ظاهرة رونج. دمج الجزء المركزي باستخدام أي طريقة تريدها؛ Gauss-Kronrod هو خيار قوي، بطبيعة الحال، ولكن هناك أيضا Threwerature Fejer (التي تخضع في بعض الأحيان للأعداد العالية من العقد، والتي قد تعمل بشكل أجمل على Intrand Discillatory) وحتى قاعدة شبه منحرف (التي تظهر دقة مذهلة مع بعض الوظائف التذبذبية ). اختيار واحد وجربه؛ إذا كانت النتائج سيئة، فقم بإعطاء طريقة أخرى لقطة.

أصعب سؤال على الإطلاق؟ بالكاد :)

نصائح أخرى

أود أن أوصي ببعض الأشياء الأخرى:

  1. حاول تحويل الوظيفة إلى مجال محدود لجعل التكامل أكثر قابلية للإدارة.
  2. استخدم التماثل حيثما أمكن - اندلعه إلى مجموع تكاملين من اللانهاية السلبية إلى الصفر والصفر إلى ما لا نهاية لمعرفة ما إذا كانت الوظيفة تماثل أو مضاد للتماثل. يمكن أن تجعل حسابك أسهل.
  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 & QOWF. ربما يمكنك تعيين قيمة، أ. وبعد ويمكن فصل التكامل إلى أجزاء السحب، [0،أ] و [أ، pos_infinity]. في الفترة الزمنية الأولى، يمكنك استخدام أي وظيفة تكامل GSL تريدها، وفي الفترة الزمنية الثانية، يمكنك استخدام QAWO أو QAWF.

2. أو يمكنك دمج الوظيفة إلى حد أعلى، ب, ، وهذا مدمج في [0،ب]. لذلك يمكن حساب التكامل باستخدام طريقة GAUSS Legendry، ويتم توفير ذلك في GSL. على الرغم من وجود بعض الاختلاف بين القيمة الحقيقية والقيمة المحسوبة، ولكن إذا قمت بتعيين ب بشكل صحيح، يمكن إهمال الفرق. طالما أن الفرق أقل من الدقة التي تريدها. ويتم استدعاء هذه الطريقة التي تستخدم وظيفة GSL مرة واحدة فقط ويمكنها استخدام عدة مرات، لأن قيمة الإرجاع نقطة ووزنها المقابل، والتكامل هو فقط مجموع F (xi) * WI، لمزيد من التفاصيل التي يمكنك البحث فيها Gauss Legendre التربيع على ويكيبيديا. عملية متعددة وإضافة أسرع بكثير من التكامل.

3. هناك أيضا وظيفة يمكنها حساب تكامل منطقة إنفينيتي - Qagi، يمكنك البحث عنها في دليل مستخدم GSL. ولكن هذا يسمى في كل مرة تحتاج إلى حساب التكامل، وقد يتسبب ذلك في استغرق الأمر بعض الوقت، لكنني لست متأكدا من الوقت الذي سيستخدمه في برنامجك.

أقترح NO.2 الاختيار الذي قدمته.

إذا كنت ستعمل مع وظائف مذبحة متناسقة أقل من n = 100 قد ترغب في تجربتها:

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

يحسب البرنامج جزءا لا يتجزأ عبر ترويض Gauss-Hermite مع 100 صفات وأوزان (أصفية H_100). بمجرد أن تذهب فوق Hermite_100، فإن التكاملات ليست دقيقة.

باستخدام طريقة التكامل هذه، كتب برنامج يحسب بالضبط ما تريد حسابه ويعمل بشكل جيد إلى حد ما. أيضا، قد يكون هناك طريقة للذهاب إلى أبعد من n = 100 باستخدام شكل مقارب من الأصفار المتعددة متعدد الحدود لكنني لم ينظر إليها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top