変分モンテカルロ(VMC)をやってみる~ヘリウム原子~
Thijssenの計算物理学の12.2.2の部分の練習問題をやってみる。
ヘリウム原子
モデル
最後にヘリウム原子についても同じくVMCをやってみよう。
この系のHamiltonianはBorn-Oppenheimer近似の下でを電子1の座標、を電子2の座標とすると、
と書ける。これまでの時と同様に試行関数を与えたいのだが、この場合は良い試行関数を作ること自体が問題になってしまうので、ここでは天下り的であるが試行関数として次のようなものを使用することにしよう。
ここでとし、これまでと同様には変分パラメータである。
次にこの試行関数を用いた時に局所エネルギーがどのようになるのかを計算してみる*1。
微分演算子の入っていない部分はそのまま係数としてかかるだけなので微分演算子の部分だけを計算すればいいだろう。そこでまずについて計算することにしよう。合成関数のラプラシアンに対する作用が、
であることに注意すると、に関係する部分の計算は、
を計算すればよいことになる。まず初項について計算しよう。この項の計算は簡単で1体の時のラプラシアンの計算と全く同じであるから、
より、
となる。
続いて第二項について計算する。ここでこれ以降の計算の表記を簡単にするためにが入っている部分の指数の肩を
と書くことにし、その微分を
と書くことにする。すると第二項の計算は、
となる。ここでは電子1の座標の成分を、は電子2の座標の成分をそれぞれ表すとした。
最後に第三項の計算を行おう。この項ではの入った項の微分を二回行う必要があるのでの二回微分を表すものとして
とを定義しよう。すると第三項は、
となる。以上から
となることがわかった。同様にしてについて計算すると、
を得ることができる*2。
以上から
と計算でき、よって局所エネルギーは、
と求めることができた。
VMCの方法とソースコード
よってプログラミングで行う操作は次の通りである。
**REPAT**
始めの変分パラメータを決める。
ランダムな場所に個のwalkerを初期配置として配置する。
**REPEAT**
**FOR 全walker**
1. 番目のサンプリング点をとする。walkerの移動後の座標として番目の候補をを中心とする正規分布に従ってとして提案する。
2. メトロポリステスト:
の間の一様乱数を生成し、であれば提案を受理してとする。そうでなければ候補を棄却してとする。
3. サンプリング点での局所エネルギーを計算する。
**END FOR**
得られた局所エネルギーの平均を取ってエネルギーの期待値を求める。
Newton法に従って変分パラメータを更新する。
**END**
ここでは座標であり、今の場合である。
このプログラムを書いてみよう。
▶C言語のプログラム(クリックすると展開されます)
#include<stdio.h> #include<stdlib.h> #include<math.h> #include<time.h> #include "MT.h" int shokihaichi(double data1[], double data2[], double data3[]);/*プロトタイプ宣言*/ int metropolis_walk(double data1[], double data2[], double data3[], double data4[], double data5[], double data6[]);/*プロトタイプ宣言*/ int shokika(double data1[], double data2[], double data3[]);/*プロトタイプ宣言*/ double sigma=0.15; int main(void) { int sample=50000; int i, j; int acc[500]; double alpha_0=0.05; double alpha_ini; double alpha_fin; double x1[500], y1[500], z1[500]; double x2[500], y2[500], z2[500]; double x1_backup[500], y1_backup[500], z1_backup[500]; double x2_backup[500], y2_backup[500], z2_backup[500]; double r1_ini[500], r2_ini[500], r12_ini[500]; double r1_fin[500], r2_fin[500], r12_fin[500]; double r1[500], r2[500], r12[500]; double psi_ini[500], psi_fin[500]; double Denom[500];/*エネルギー計算に出てくる分母の関数*/ double U12[500], DU12[500], DDU12[500]; double R1DR12[500], R2DR12[500]; double Sum_E_w[500]={0}; double E_w[500]={0}; double E=0; double Sum_Edlnpsi_w[500]={0}; double Edlnpsi_w[500]={0}; double Edlnpsi=0; double Sum_dlnpsi_w[500]={0}; double dlnpsi_w[500]={0}; double dlnpsi=0; double dE; double h=1e-3;/*数値微分の幅*/ init_genrand((unsigned)time(NULL)); alpha_fin=alpha_0; do { alpha_ini=alpha_fin;/*前のループでの結果を始まりのalphaに代入*/ /************************************************/ /*dEを求める.*************************************/ /*alpha_iniでの<E>, <Edlnpsi>, <dlnpsi>を計算する.*/ /************************************************/ shokika(Sum_E_w, Sum_Edlnpsi_w, Sum_dlnpsi_w);/*Sumの配列を初期化*/ shokihaichi(x1, y1, z1);/*ランダムにwalkrを配置*/ shokihaichi(x2, y2, z2); for ( i = 0; i < sample; i++) { metropolis_walk(x1, y1, z1, x1_backup, y1_backup, z1_backup);/*提案分布に従ってwalkerを変化させる*/ metropolis_walk(x2, y2, z2, x2_backup, y2_backup, z2_backup); /*Metropolis Testを行う*/ for ( j = 0; j < 500; j++) { r1_ini[j]=sqrt(x1_backup[j]*x1_backup[j]+y1_backup[j]*y1_backup[j]+z1_backup[j]*z1_backup[j]); r2_ini[j]=sqrt(x2_backup[j]*x2_backup[j]+y2_backup[j]*y2_backup[j]+z2_backup[j]*z2_backup[j]); r12_ini[j]=sqrt((x1_backup[j]-x2_backup[j])*(x1_backup[j]-x2_backup[j])+(y1_backup[j]-y2_backup[j])*(y1_backup[j]-y2_backup[j])+(z1_backup[j]-z2_backup[j])*(z1_backup[j]-z2_backup[j])); psi_ini[j]=exp(-4*(r1_ini[j]+r2_ini[j])+r12_ini[j]/(1+alpha_ini*r12_ini[j]));/*始めの確率分布*/ r1_fin[j]=sqrt(x1[j]*x1[j]+y1[j]*y1[j]+z1[j]*z1[j]); r2_fin[j]=sqrt(x2[j]*x2[j]+y2[j]*y2[j]+z2[j]*z2[j]); r12_fin[j]=sqrt((x1[j]-x2[j])*(x1[j]-x2[j])+(y1[j]-y2[j])*(y1[j]-y2[j])+(z1[j]-z2[j])*(z1[j]-z2[j])); psi_fin[j]=exp(-4*(r1_fin[j]+r2_fin[j])+r12_fin[j]/(1+alpha_ini*r12_fin[j]));/*候補の確率分布*/ double metropolis=genrand_real1(); if (psi_fin[j]/psi_ini[j]>metropolis) { acc[j]=acc[j]+1; } else { x1[j]=x1_backup[j]; y1[j]=y1_backup[j]; z1[j]=z1_backup[j]; x2[j]=x2_backup[j]; y2[j]=y2_backup[j]; z2[j]=z2_backup[j]; } /*Metropolis Testの終了*/ /*walkerについての<E>, <Edlnpsi>, <dlnpsi>を計算する.*/ if (i>=4000) { r1[j]=sqrt(x1[j]*x1[j]+y1[j]*y1[j]+z1[j]*z1[j]);/*更新し終えた位置でパラメタを計算*/ r2[j]=sqrt(x2[j]*x2[j]+y2[j]*y2[j]+z2[j]*z2[j]); r12[j]=sqrt((x1[j]-x2[j])*(x1[j]-x2[j])+(y1[j]-y2[j])*(y1[j]-y2[j])+(z1[j]-z2[j])*(z1[j]-z2[j])); R1DR12[j]=x1[j]*(x1[j]-x2[j])+y1[j]*(y1[j]-y2[j])+z1[j]*(z1[j]-z2[j]); R2DR12[j]=x2[j]*(x1[j]-x2[j])+y2[j]*(y1[j]-y2[j])+z2[j]*(z1[j]-z2[j]); Denom[j]=1/(1+alpha_ini*r12[j]); U12[j]=0.5*r12[j]*Denom[j]; DU12[j]=-0.5*alpha_ini*r12[j]*Denom[j]*Denom[j]+0.5*Denom[j]; DDU12[j]=alpha_ini*alpha_ini*r12[j]*Denom[j]*Denom[j]*Denom[j]-alpha_ini*Denom[j]*Denom[j]; Sum_E_w[j]=Sum_E_w[j]-4-0.5*(2*(-2)/r1[j]*R1DR12[j]*DU12[j]/r12[j]-2*(-2)/r2[j]*R2DR12[j]*DU12[j]/r12[j]+4*DU12[j]/r12[j]+2*DU12[j]*DU12[j]+2*DDU12[j])+1/r12[j]; E_w[j]=Sum_E_w[j]/(i-3999); Sum_Edlnpsi_w[j]=Sum_Edlnpsi_w[j]+(-0.5*(r12[j]*Denom[j])*(r12[j]*Denom[j]))*(-4-0.5*(2*(-2)/r1[j]*R1DR12[j]*DU12[j]/r12[j]-2*(-2)/r2[j]*R2DR12[j]*DU12[j]/r12[j]+4*DU12[j]/r12[j]+2*DU12[j]*DU12[j]+2*DDU12[j])+1/r12[j]); Edlnpsi_w[j]=Sum_Edlnpsi_w[j]/(i-3999); Sum_dlnpsi_w[j]=Sum_dlnpsi_w[j]-0.5*(r12[j]*Denom[j])*(r12[j]*Denom[j]); dlnpsi_w[j]=Sum_dlnpsi_w[j]/(i-3999); } } } E=0;/*変数の初期化*/ Edlnpsi=0; dlnpsi=0; /*walker全ての平均を取ることにする*/ for ( j = 0; j < 500; j++) { E=E+E_w[j]; Edlnpsi=Edlnpsi+Edlnpsi_w[j]; dlnpsi=dlnpsi+dlnpsi_w[j]; } E=E/500; Edlnpsi=Edlnpsi/500; dlnpsi=dlnpsi/500;/*dE/dalphaの計算をするための部品を計算した.*/ dE=2*(Edlnpsi-E*dlnpsi);/*dE/dalphaの計算ができた.*/ /*****************************/ /*ddE/ddalphaの数値微分を行う.*/ /****************************/ double alpha_plus=alpha_ini+h;/*微分のためにalphaを変化させる*/ double alpha_minus=alpha_ini-h; /***********************************/ /***********************************/ /*alpha_plusでのdE/dalphaを計算する.*/ /***********************************/ /***********************************/ shokika(Sum_E_w, Sum_Edlnpsi_w, Sum_dlnpsi_w);/*Sumの配列を初期化*/ shokihaichi(x1, y1, z1);/*ランダムにwalkrを配置*/ shokihaichi(x2, y2, z2); for ( i = 0; i < sample; i++) { metropolis_walk(x1, y1, z1, x1_backup, y1_backup, z1_backup);/*提案分布に従ってwalkerを変化させる*/ metropolis_walk(x2, y2, z2, x2_backup, y2_backup, z2_backup); /*Metropolis Testを行う*/ for ( j = 0; j < 500; j++) { r1_ini[j]=sqrt(x1_backup[j]*x1_backup[j]+y1_backup[j]*y1_backup[j]+z1_backup[j]*z1_backup[j]); r2_ini[j]=sqrt(x2_backup[j]*x2_backup[j]+y2_backup[j]*y2_backup[j]+z2_backup[j]*z2_backup[j]); r12_ini[j]=sqrt((x1_backup[j]-x2_backup[j])*(x1_backup[j]-x2_backup[j])+(y1_backup[j]-y2_backup[j])*(y1_backup[j]-y2_backup[j])+(z1_backup[j]-z2_backup[j])*(z1_backup[j]-z2_backup[j])); psi_ini[j]=exp(-4*(r1_ini[j]+r2_ini[j])+r12_ini[j]/(1+alpha_plus*r12_ini[j]));/*始めの確率分布*/ r1_fin[j]=sqrt(x1[j]*x1[j]+y1[j]*y1[j]+z1[j]*z1[j]); r2_fin[j]=sqrt(x2[j]*x2[j]+y2[j]*y2[j]+z2[j]*z2[j]); r12_fin[j]=sqrt((x1[j]-x2[j])*(x1[j]-x2[j])+(y1[j]-y2[j])*(y1[j]-y2[j])+(z1[j]-z2[j])*(z1[j]-z2[j])); psi_fin[j]=exp(-4*(r1_fin[j]+r2_fin[j])+r12_fin[j]/(1+alpha_plus*r12_fin[j]));/*候補の確率分布*/ double metropolis=genrand_real1(); if (psi_fin[j]/psi_ini[j]>metropolis) { acc[j]=acc[j]+1; } else { x1[j]=x1_backup[j]; y1[j]=y1_backup[j]; z1[j]=z1_backup[j]; x2[j]=x2_backup[j]; y2[j]=y2_backup[j]; z2[j]=z2_backup[j]; } /*Metropolis Testの終了*/ /*walkerについての<E>, <Edlnpsi>, <dlnpsi>を計算する.*/ if (i>=4000) { r1[j]=sqrt(x1[j]*x1[j]+y1[j]*y1[j]+z1[j]*z1[j]);/*更新し終えた位置でパラメタを計算*/ r2[j]=sqrt(x2[j]*x2[j]+y2[j]*y2[j]+z2[j]*z2[j]); r12[j]=sqrt((x1[j]-x2[j])*(x1[j]-x2[j])+(y1[j]-y2[j])*(y1[j]-y2[j])+(z1[j]-z2[j])*(z1[j]-z2[j])); R1DR12[j]=x1[j]*(x1[j]-x2[j])+y1[j]*(y1[j]-y2[j])+z1[j]*(z1[j]-z2[j]); R2DR12[j]=x2[j]*(x1[j]-x2[j])+y2[j]*(y1[j]-y2[j])+z2[j]*(z1[j]-z2[j]); Denom[j]=1/(1+alpha_plus*r12[j]); U12[j]=0.5*r12[j]*Denom[j]; DU12[j]=-0.5*alpha_plus*r12[j]*Denom[j]*Denom[j]+0.5*Denom[j]; DDU12[j]=alpha_plus*alpha_plus*r12[j]*Denom[j]*Denom[j]*Denom[j]-alpha_plus*Denom[j]*Denom[j]; Sum_E_w[j]=Sum_E_w[j]-4-0.5*(2*(-2)/r1[j]*R1DR12[j]*DU12[j]/r12[j]-2*(-2)/r2[j]*R2DR12[j]*DU12[j]/r12[j]+4*DU12[j]/r12[j]+2*DU12[j]*DU12[j]+2*DDU12[j])+1/r12[j]; E_w[j]=Sum_E_w[j]/(i-3999); Sum_Edlnpsi_w[j]=Sum_Edlnpsi_w[j]+(-0.5*(r12[j]*Denom[j])*(r12[j]*Denom[j]))*(-4-0.5*(2*(-2)/r1[j]*R1DR12[j]*DU12[j]/r12[j]-2*(-2)/r2[j]*R2DR12[j]*DU12[j]/r12[j]+4*DU12[j]/r12[j]+2*DU12[j]*DU12[j]+2*DDU12[j])+1/r12[j]); Edlnpsi_w[j]=Sum_Edlnpsi_w[j]/(i-3999); Sum_dlnpsi_w[j]=Sum_dlnpsi_w[j]-0.5*(r12[j]*Denom[j])*(r12[j]*Denom[j]); dlnpsi_w[j]=Sum_dlnpsi_w[j]/(i-3999); } } } E=0;/*変数の初期化*/ Edlnpsi=0; dlnpsi=0; /*walker全ての平均を取ることにする*/ for ( j = 0; j < 500; j++) { E=E+E_w[j]; Edlnpsi=Edlnpsi+Edlnpsi_w[j]; dlnpsi=dlnpsi+dlnpsi_w[j]; } E=E/500; Edlnpsi=Edlnpsi/500; dlnpsi=dlnpsi/500;/*dE/dalpha_plusの計算をするための部品を計算した.*/ double dE_plus=2*(Edlnpsi-E*dlnpsi);/*dE/dalpha_plusの計算ができた.*/ /***********************************/ /***********************************/ /*alpha_minusでのdE/dalphaを計算する.*/ /***********************************/ /***********************************/ shokika(Sum_E_w, Sum_Edlnpsi_w, Sum_dlnpsi_w);/*Sumの配列を初期化*/ shokihaichi(x1, y1, z1);/*ランダムにwalkrを配置*/ shokihaichi(x2, y2, z2); for ( i = 0; i < sample; i++) { metropolis_walk(x1, y1, z1, x1_backup, y1_backup, z1_backup);/*提案分布に従ってwalkerを変化させる*/ metropolis_walk(x2, y2, z2, x2_backup, y2_backup, z2_backup); /*Metropolis Testを行う*/ for ( j = 0; j < 500; j++) { r1_ini[j]=sqrt(x1_backup[j]*x1_backup[j]+y1_backup[j]*y1_backup[j]+z1_backup[j]*z1_backup[j]); r2_ini[j]=sqrt(x2_backup[j]*x2_backup[j]+y2_backup[j]*y2_backup[j]+z2_backup[j]*z2_backup[j]); r12_ini[j]=sqrt((x1_backup[j]-x2_backup[j])*(x1_backup[j]-x2_backup[j])+(y1_backup[j]-y2_backup[j])*(y1_backup[j]-y2_backup[j])+(z1_backup[j]-z2_backup[j])*(z1_backup[j]-z2_backup[j])); psi_ini[j]=exp(-4*(r1_ini[j]+r2_ini[j])+r12_ini[j]/(1+alpha_minus*r12_ini[j]));/*始めの確率分布*/ r1_fin[j]=sqrt(x1[j]*x1[j]+y1[j]*y1[j]+z1[j]*z1[j]); r2_fin[j]=sqrt(x2[j]*x2[j]+y2[j]*y2[j]+z2[j]*z2[j]); r12_fin[j]=sqrt((x1[j]-x2[j])*(x1[j]-x2[j])+(y1[j]-y2[j])*(y1[j]-y2[j])+(z1[j]-z2[j])*(z1[j]-z2[j])); psi_fin[j]=exp(-4*(r1_fin[j]+r2_fin[j])+r12_fin[j]/(1+alpha_minus*r12_fin[j]));/*候補の確率分布*/ double metropolis=genrand_real1(); if (psi_fin[j]/psi_ini[j]>metropolis) { acc[j]=acc[j]+1; } else { x1[j]=x1_backup[j]; y1[j]=y1_backup[j]; z1[j]=z1_backup[j]; x2[j]=x2_backup[j]; y2[j]=y2_backup[j]; z2[j]=z2_backup[j]; } /*Metropolis Testの終了*/ /*walkerについての<E>, <Edlnpsi>, <dlnpsi>を計算する.*/ if (i>=4000) { r1[j]=sqrt(x1[j]*x1[j]+y1[j]*y1[j]+z1[j]*z1[j]);/*更新し終えた位置でパラメタを計算*/ r2[j]=sqrt(x2[j]*x2[j]+y2[j]*y2[j]+z2[j]*z2[j]); r12[j]=sqrt((x1[j]-x2[j])*(x1[j]-x2[j])+(y1[j]-y2[j])*(y1[j]-y2[j])+(z1[j]-z2[j])*(z1[j]-z2[j])); R1DR12[j]=x1[j]*(x1[j]-x2[j])+y1[j]*(y1[j]-y2[j])+z1[j]*(z1[j]-z2[j]); R2DR12[j]=x2[j]*(x1[j]-x2[j])+y2[j]*(y1[j]-y2[j])+z2[j]*(z1[j]-z2[j]); Denom[j]=1/(1+alpha_minus*r12[j]); U12[j]=0.5*r12[j]*Denom[j]; DU12[j]=-0.5*alpha_minus*r12[j]*Denom[j]*Denom[j]+0.5*Denom[j]; DDU12[j]=alpha_minus*alpha_minus*r12[j]*Denom[j]*Denom[j]*Denom[j]-alpha_minus*Denom[j]*Denom[j]; Sum_E_w[j]=Sum_E_w[j]-4-0.5*(2*(-2)/r1[j]*R1DR12[j]*DU12[j]/r12[j]-2*(-2)/r2[j]*R2DR12[j]*DU12[j]/r12[j]+4*DU12[j]/r12[j]+2*DU12[j]*DU12[j]+2*DDU12[j])+1/r12[j]; E_w[j]=Sum_E_w[j]/(i-3999); Sum_Edlnpsi_w[j]=Sum_Edlnpsi_w[j]+(-0.5*(r12[j]*Denom[j])*(r12[j]*Denom[j]))*(-4-0.5*(2*(-2)/r1[j]*R1DR12[j]*DU12[j]/r12[j]-2*(-2)/r2[j]*R2DR12[j]*DU12[j]/r12[j]+4*DU12[j]/r12[j]+2*DU12[j]*DU12[j]+2*DDU12[j])+1/r12[j]); Edlnpsi_w[j]=Sum_Edlnpsi_w[j]/(i-3999); Sum_dlnpsi_w[j]=Sum_dlnpsi_w[j]-0.5*(r12[j]*Denom[j])*(r12[j]*Denom[j]); dlnpsi_w[j]=Sum_dlnpsi_w[j]/(i-3999); } } } E=0;/*変数の初期化*/ Edlnpsi=0; dlnpsi=0; /*walker全ての平均を取ることにする*/ for ( j = 0; j < 500; j++) { E=E+E_w[j]; Edlnpsi=Edlnpsi+Edlnpsi_w[j]; dlnpsi=dlnpsi+dlnpsi_w[j]; } E=E/500; Edlnpsi=Edlnpsi/500; dlnpsi=dlnpsi/500;/*dE/dalpha_minusの計算をするための部品を計算した.*/ double dE_minus=2*(Edlnpsi-E*dlnpsi);/*dE/dalpha_minusの計算ができた.*/ /***************************************************/ /***************************************************/ /*alphaをNewton法で求めるための部品をすべて計算し終えた*/ /***************************************************/ /***************************************************/ /*alphaの更新を行う*/ double ddE=(dE_plus-dE_minus)/(2*h);/*dE/dalphaの数値微分ddEが計算できた.*/ alpha_fin=alpha_ini-dE/ddE;/*alphaを更新する.*/ printf("alpha_fin=%.10f, alpha_ini=%.10f dE=%.10f\n", alpha_fin, alpha_ini, dE); } while (fabs(alpha_fin-alpha_ini)>1e-4); double alpha_val=alpha_fin;/*最適化した変分パラメータ*/ printf("変分パラメータはalpha=%.10f", alpha_val); /*****************************/ /*****************************/ /*alphaでのエネルギーを計算する*/ /*****************************/ /*****************************/ shokika(Sum_E_w, Sum_Edlnpsi_w, Sum_dlnpsi_w);/*Sumの配列を初期化*/ shokihaichi(x1, y1, z1);/*ランダムにwalkrを配置*/ shokihaichi(x2, y2, z2); for ( i = 0; i < sample; i++) { metropolis_walk(x1, y1, z1, x1_backup, y1_backup, z1_backup);/*提案分布に従ってwalkerを変化させる*/ metropolis_walk(x2, y2, z2, x2_backup, y2_backup, z2_backup); /*Metropolis Testを行う*/ for ( j = 0; j < 500; j++) { r1_ini[j]=sqrt(x1_backup[j]*x1_backup[j]+y1_backup[j]*y1_backup[j]+z1_backup[j]*z1_backup[j]); r2_ini[j]=sqrt(x2_backup[j]*x2_backup[j]+y2_backup[j]*y2_backup[j]+z2_backup[j]*z2_backup[j]); r12_ini[j]=sqrt((x1_backup[j]-x2_backup[j])*(x1_backup[j]-x2_backup[j])+(y1_backup[j]-y2_backup[j])*(y1_backup[j]-y2_backup[j])+(z1_backup[j]-z2_backup[j])*(z1_backup[j]-z2_backup[j])); psi_ini[j]=exp(-4*(r1_ini[j]+r2_ini[j])+r12_ini[j]/(1+alpha_val*r12_ini[j]));/*始めの確率分布*/ r1_fin[j]=sqrt(x1[j]*x1[j]+y1[j]*y1[j]+z1[j]*z1[j]); r2_fin[j]=sqrt(x2[j]*x2[j]+y2[j]*y2[j]+z2[j]*z2[j]); r12_fin[j]=sqrt((x1[j]-x2[j])*(x1[j]-x2[j])+(y1[j]-y2[j])*(y1[j]-y2[j])+(z1[j]-z2[j])*(z1[j]-z2[j])); psi_fin[j]=exp(-4*(r1_fin[j]+r2_fin[j])+r12_fin[j]/(1+alpha_val*r12_fin[j]));/*候補の確率分布*/ double metropolis=genrand_real1(); if (psi_fin[j]/psi_ini[j]>metropolis) { acc[j]=acc[j]+1; } else { x1[j]=x1_backup[j]; y1[j]=y1_backup[j]; z1[j]=z1_backup[j]; x2[j]=x2_backup[j]; y2[j]=y2_backup[j]; z2[j]=z2_backup[j]; } /*Metropolis Testの終了*/ /*walkerについての<E>, <Edlnpsi>, <dlnpsi>を計算する.*/ if (i>=4000) { r1[j]=sqrt(x1[j]*x1[j]+y1[j]*y1[j]+z1[j]*z1[j]);/*更新し終えた位置でパラメタを計算*/ r2[j]=sqrt(x2[j]*x2[j]+y2[j]*y2[j]+z2[j]*z2[j]); r12[j]=sqrt((x1[j]-x2[j])*(x1[j]-x2[j])+(y1[j]-y2[j])*(y1[j]-y2[j])+(z1[j]-z2[j])*(z1[j]-z2[j])); R1DR12[j]=x1[j]*(x1[j]-x2[j])+y1[j]*(y1[j]-y2[j])+z1[j]*(z1[j]-z2[j]); R2DR12[j]=x2[j]*(x1[j]-x2[j])+y2[j]*(y1[j]-y2[j])+z2[j]*(z1[j]-z2[j]); Denom[j]=1/(1+alpha_val*r12[j]); U12[j]=0.5*r12[j]*Denom[j]; DU12[j]=-0.5*alpha_val*r12[j]*Denom[j]*Denom[j]+0.5*Denom[j]; DDU12[j]=alpha_val*alpha_val*r12[j]*Denom[j]*Denom[j]*Denom[j]-alpha_val*Denom[j]*Denom[j]; Sum_E_w[j]=Sum_E_w[j]-4-0.5*(2*(-2)/r1[j]*R1DR12[j]*DU12[j]/r12[j]-2*(-2)/r2[j]*R2DR12[j]*DU12[j]/r12[j]+4*DU12[j]/r12[j]+2*DU12[j]*DU12[j]+2*DDU12[j])+1/r12[j]; E_w[j]=Sum_E_w[j]/(i-3999); } } } E=0;/*変数の初期化*/ /*walker全ての平均を取ることにする*/ for ( j = 0; j < 500; j++) { E=E+E_w[j]; } E=E/500; printf("基底状態のエネルギーは%.10f", E); return 0; } int shokihaichi(double data1[], double data2[], double data3[]) { int i; for ( i = 0; i < 500; i++) { data1[i]=(genrand_real1()-0.5)*2*2; data2[i]=(genrand_real1()-0.5)*2*2; data3[i]=(genrand_real1()-0.5)*2*2; } return 0; } int metropolis_walk(double data1[], double data2[], double data3[], double data4[], double data5[], double data6[])/*1~3がx,y,z, 4~6はそれらのバックアップ*/ { int i; double p[500]; double q[500]; double pi=asin(1e0)*2e0; for ( i = 0; i < 500; i++) { /*x*/ data4[i]=data1[i];/*バックアップにxの値を保存*/ p[i]=genrand_real1(); q[i]=genrand_real1(); data1[i]=data1[i]+sigma*sqrt(-2*log(p[i]))*cos(2*pi*q[i]); /*y*/ data5[i]=data2[i];/*バックアップにyの値を保存*/ p[i]=genrand_real1(); q[i]=genrand_real1(); data2[i]=data2[i]+sigma*sqrt(-2*log(p[i]))*cos(2*pi*q[i]); /*z*/ data6[i]=data3[i];/*バックアップにxの値を保存*/ p[i]=genrand_real1(); q[i]=genrand_real1(); data3[i]=data3[i]+sigma*sqrt(-2*log(p[i]))*cos(2*pi*q[i]); } return 0; } int shokika(double data1[], double data2[], double data3[]) { int i; for ( i = 0; i < 500; i++) { data1[i]=0; data2[i]=0; data3[i]=0; } return 0; }
このプログラムを実行すると、となり、その時の基底状態のエネルギーとしてが得られる。これはHartree-Fockの値やDFTの値、厳密値と比肩しうる数値になっている。