00001 
00002 
00003 
00004 
00005 #include "QMCPsiPotential.h"
00006 
00007 QMCInput *QMCPsiPotential::qmc_input;
00008 QMCBasisFunction *QMCPsiPotential::qmc_basis;
00009 JTS_ORBITAL QMCPsiPotential::orbital;
00010 
00011 QMCPsiPotential::QMCPsiPotential()
00012 {
00013 }
00014 
00015 QMCPsiPotential::~QMCPsiPotential()
00016 {
00017 }
00018 
00019 void QMCPsiPotential::Initialize(QMCInput *s_qmc_input)
00020 {
00021   qmc_input = s_qmc_input;
00022   qmc_basis = &(qmc_input->BF);
00023   LoadOrbitals(AllocateOrbitals());
00024 }
00025 
00026 int QMCPsiPotential::CountGaussians()
00027 {
00028   int numgaussians = 0;
00029   for (int i = 0; i < qmc_basis->BFCoeffs.dim1(); i++)
00030     for (int j = 0; j < qmc_basis->BFCoeffs(i).getNumberBasisFunctions(); j++)
00031       numgaussians += qmc_basis->BFCoeffs(i).N_Gauss(j);
00032   return numgaussians;
00033 }
00034 
00035 int QMCPsiPotential::AllocateOrbitals()
00036 {
00037   int numgaussians = CountGaussians();
00038 
00039   
00040   orbital.l = (int *) malloc(sizeof(int) * numgaussians);
00041   orbital.m = (int *) malloc(sizeof(int) * numgaussians);
00042   orbital.n = (int *) malloc(sizeof(int) * numgaussians);
00043   orbital.x = (double *) malloc(sizeof(double) * numgaussians);
00044   orbital.y = (double *) malloc(sizeof(double) * numgaussians);
00045   orbital.z = (double *) malloc(sizeof(double) * numgaussians);
00046   orbital.coeff = (double *) malloc(sizeof(double) * numgaussians);
00047   orbital.coeff0 = (double *) malloc(sizeof(double) * numgaussians);
00048   orbital.exponent = (double *) malloc(sizeof(double) * numgaussians);
00049 
00050   return numgaussians;
00051 }
00052 
00053 void QMCPsiPotential::LoadOrbitals(int numgaussians)
00054 {
00055   int idx = 0;
00056   for (int i = 0; i < qmc_basis->BFCoeffs.dim1(); i++)
00057   {
00058     double x, y, z;
00059     x = qmc_input->Molecule.Atom_Positions(i, 0);
00060     y = qmc_input->Molecule.Atom_Positions(i, 1);
00061     z = qmc_input->Molecule.Atom_Positions(i, 2);
00062     
00063     for (int j = 0; j < qmc_basis->BFCoeffs(i).getNumberBasisFunctions(); j++)
00064     {
00065       
00066       for (int k = 0; k < qmc_basis->BFCoeffs(i).N_Gauss(j); k++)
00067       {
00068        orbital.x[idx] = x;
00069        orbital.y[idx] = y;
00070        orbital.z[idx] = z;
00071        orbital.exponent[idx] = qmc_basis->BFCoeffs(i).Coeffs(j, k, 0);
00072        orbital.coeff0[idx] = qmc_basis->BFCoeffs(i).Coeffs(j, k, 1);
00073        orbital.l[idx] = qmc_basis->BFCoeffs(i).xyz_powers(j, 0);
00074        orbital.m[idx] = qmc_basis->BFCoeffs(i).xyz_powers(j, 1);
00075        orbital.n[idx] = qmc_basis->BFCoeffs(i).xyz_powers(j, 2);
00076        orbital.numgaussians = numgaussians;
00077        idx++;
00078       }
00079     }
00080   }
00081 }
00082 
00083 void QMCPsiPotential::UseWavefunction(int wfnum, int spin)
00084 {
00085   
00086   
00087   int idx = 0;
00088 
00089   int betaO = -1, alphaO = -1;
00090   int orb = 0;
00091   while(betaO < 0 || alphaO < 0)
00092     {
00093       if(alphaO < 0 && qmc_input->WF.AlphaOccupation(0,orb) == wfnum)
00094         alphaO = orb;
00095       if(betaO < 0 && qmc_input->WF.BetaOccupation(0,orb) == wfnum)
00096         betaO = orb;
00097       orb++;
00098     }
00099   cout << "alphaO = " << alphaO << endl;
00100   cout << "betaO  = " << betaO << endl;
00101 
00102   
00103 
00104 
00105 
00106   assert(0);
00107 
00108   
00109   for (int i = 0; i < qmc_basis->BFCoeffs.dim1(); i++)
00110   {
00111     
00112     for (int j = 0; j < qmc_basis->BFCoeffs(i).getNumberBasisFunctions(); j++)
00113     {
00114       
00115       
00116       double factor = (spin == 0 ? qmc_input->WF.OrbitalCoeffs(alphaO, j) : qmc_input->WF.OrbitalCoeffs(betaO, j));
00117       
00118       for (int k = 0; k < qmc_basis->BFCoeffs(i).N_Gauss(j); k++)
00119       {
00120        orbital.coeff[idx] = orbital.coeff0[idx] * factor;
00121        idx++;
00122       }
00123     }
00124   }
00125 }
00126 
00127 double QMCPsiPotential::GetPoten(int wfnum, int spin, double x, double y, double z)
00128 {
00129   int j, k;
00130   int numgaussians = orbital.numgaussians;
00131   
00132   
00133   UseWavefunction(wfnum, spin);
00134  
00135   
00136   double sum = 0;
00137   for (j = 0; j < numgaussians; j++)
00138   {
00139       int l1, m1, n1;
00140       double exponent1, coeff1;
00141       double x1, y1, z1;
00142 
00143       x1 = orbital.x[j]; y1 = orbital.y[j]; z1 = orbital.z[j];
00144       l1 = orbital.l[j]; m1 = orbital.m[j]; n1 = orbital.n[j];
00145       exponent1 = orbital.exponent[j];
00146       coeff1 = orbital.coeff[j];
00147 
00148       for (k = 0; k < numgaussians; k++)
00149       {
00150         int l2, m2, n2;
00151         double exponent2, coeff2;
00152         double x2, y2, z2;
00153       
00154         x2 = orbital.x[k]; y2 = orbital.y[k]; z2 = orbital.z[k];
00155         l2 = orbital.l[k]; m2 = orbital.m[k]; n2 = orbital.n[k];
00156         exponent2 = orbital.exponent[k];
00157         coeff2 = orbital.coeff[k];
00158 
00159         
00160         sum += coeff1 * coeff2 * OverlapVGaussians(l1, m1, n1, exponent1, x1, y1, z1, l2, m2, n2, exponent2, x2, y2, z2, x, y, z);
00161       }
00162   }
00163   return sum;
00164 }
00165 
00166 double QMCPsiPotential::NormGaussian(int l, int m, int n, double exponent)
00167 {
00168   return pow(2.0 * exponent / 3.1415926535, 0.75) * sqrt(pow(4.0 * exponent, l + m + n) / (DFactorial(2 * l - 1) * DFactorial(2 * m - 1) * DFactorial(2 * n - 1)));
00169 }
00170 
00171 double QMCPsiPotential::OverlapVGaussians(int l1, int m1, int n1, double exponent1, double x1, double y1, double z1, int l2, int m2, int n2, double exponent2, double x2, double y2, double z2, double xnuc, double ynuc, double znuc)
00172 {
00173   
00174 
00175 
00176 
00177   double gamma = exponent1 + exponent2;
00178 
00179   
00180   double px, py, pz;
00181   double pax, pay, paz;
00182   double pbx, pby, pbz;
00183 
00184   px = (exponent1 * x1 + exponent2 * x2) / gamma;
00185   py = (exponent1 * y1 + exponent2 * y2) / gamma;
00186   pz = (exponent1 * z1 + exponent2 * z2) / gamma;
00187   pax = x1 - px; pay = y1 - py; paz = z1 - pz;
00188   pbx = x2 - px; pby = y2 - py; pbz = z2 - pz;
00189 
00190   int i;
00191   double f[9];
00192 
00193   double sum = 0;
00194   
00195   
00196   double pnx, pny, pnz, p2, p;
00197   pnx = xnuc - px;
00198   pny = ynuc - py;
00199   pnz = znuc - pz;
00200   p2 = pnx * pnx + pny * pny + pnz * pnz;
00201   p = sqrt(p2);
00202 
00203   
00204   double gx[9], gy[9], gz[9];
00205   binomial_f(l1, l2, pax, pbx, f);
00206   g_function(l1 + l2, f, 1.0 / gamma, p, gx);
00207   binomial_f(m1, m2, pay, pby, f);
00208   g_function(m1 + m2, f, 1.0 / gamma, p, gy);
00209   binomial_f(n1, n2, paz, pbz, f);
00210   g_function(n1 + n2, f, 1.0 / gamma, p, gz);
00211 
00212   
00213   double aux[27];
00214   for (i = 0; i <= l1 + l2 + m1 + m2 + n1 + n2; i++)
00215      aux[i] = MathFunctions::F_gamma((double) i, gamma * p2);
00216 
00217   
00218   int l, m, n;
00219    for (l = 0; l <= l1 + l2; l++)
00220      for (m = 0; m <= m1 + m2; m++)
00221        for (n = 0; n <= n1 + n2; n++)
00222          sum += gx[l] * gy[m] * gz[n] * aux[l + m + n];
00223 
00224   
00225   double dx, dy, dz;
00226   dx = x2 - x1; dy = y2 - y1; dz = z2 - z1;
00227   
00228   return (2.0 * 3.1415926535 / gamma) * exp(-exponent1 * exponent2 * (dx * dx + dy * dy + dz * dz) / gamma) * sum;
00229 }
00230 
00231 double QMCPsiPotential::DFactorial(int n)
00232 {
00233   
00234   
00235   double x = 1;
00236   while (n > 0)
00237   {
00238     x *= n;
00239     n -= 2;
00240   }
00241   return (double) x;
00242 }
00243 
00244 double QMCPsiPotential::intpow(double x, int n)
00245 {
00246   double y = 1;
00247   while (n > 0)
00248   {
00249     y *= x; n--;
00250   }
00251   return y;
00252 }
00253 
00254 void QMCPsiPotential::binomial_f(int l, int m, double a, double b, double *f)
00255 {
00256   
00257 
00258 
00259 
00260 
00261   int n;
00262   double c;
00263 
00264   
00265   if (m < l) 
00266   { 
00267     n = m; m = l; l = n; 
00268     c = a; a = b; b = c;
00269   }
00270 
00271   
00272   if (l < 0 || l > 4) {printf("Invalid l value: %i\n", l); exit(1);}
00273   if (m < 0 || m > 4) {printf("Invalid m value: %i\n", m); exit(1);}
00274  
00275   if (l == 0)
00276   {
00277     if (m == 0)
00278     {
00279       f[0] = 1;
00280     }
00281     else if (m == 1)
00282     {
00283       f[0] = b;
00284       f[1] = 1;
00285     }
00286     else if (m == 2)
00287     {
00288       f[0] = b * b;
00289       f[1] = 2 * b;
00290       f[2] = 1;
00291     }
00292     else if (m == 3)
00293     {
00294       f[0] = b * b * b;
00295       f[1] = 3 * b * b;
00296       f[2] = 3 * b;
00297       f[3] = 1;
00298     }
00299     else if (m == 4)
00300     {
00301       f[0] = b * b * b * b;
00302       f[1] = 4 * b * b * b;
00303       f[2] = 6 * b * b;
00304       f[3] = 4 * b;
00305       f[4] = 1;
00306     }
00307   }
00308   else if (l == 1)
00309   {
00310     if (m == 1)
00311     {
00312       f[0] = a * b;
00313       f[1] = a + b;
00314       f[2] = 1;
00315     }
00316     else if (m == 2)
00317     {
00318       f[0] = a * b * b;
00319       f[1] = (2 * a + b) * b;
00320       f[2] = a + 2 * b;
00321       f[3] = 1;
00322     }
00323     else if (m == 3)
00324     {
00325       f[0] = a * b * b * b;
00326       f[1] = b * b * (3 * a + b); 
00327       f[2] = 3 * b * (a + b);
00328       f[3] = a + 3 * b;
00329       f[4] = 1;
00330     }
00331     else if (m == 4)
00332     {
00333       f[0] = a * b * b * b * b;
00334       f[1] = b * b * b * (4 * a + b);
00335       f[2] = 2 * b * b * (3 * a + 2 * b);
00336       f[3] = 2 * b * (2 * a + 3 * b);
00337       f[4] = a + 4 * b;
00338       f[5] = 1;
00339     }
00340   }
00341   else if (l == 2)
00342   {
00343     if (m == 2)
00344     {
00345       f[0] = a * a * b * b;
00346       f[1] = 2 * a * b * (a + b);
00347       f[2] = a * a + 4 * a * b + b * b;
00348       f[3] = 2 * (a + b);
00349       f[4] = 1;
00350     }
00351     else if (m == 3)
00352     {
00353       f[0] = a * a * b * b * b;
00354       f[1] = a * b * b * (3 * a + 2 * b);
00355       f[2] = b * (3 * a * a + 6 * a * b + b * b);
00356       f[3] = a * a + 6 * a * b + 3 * b * b;
00357       f[4] = 2 * a + 3 * b;
00358       f[5] = 1;
00359     }
00360     else if (m == 4)
00361     {
00362       f[0] = a * a * b * b * b * b;
00363       f[1] = 2 * a * b * b * b * (2 * a + b);
00364       f[2] = b * b * (6 * a * a + 8 * a * b + b * b);
00365       f[3] = 4 * b * (a * a + 3 * a * b + b * b);
00366       f[4] = a * a + 8 * a * b + 6 * b * b;
00367       f[5] = 2 * (a + 2 * b);
00368       f[6] = 1;
00369     }
00370   }
00371   else if (l == 3)
00372   {
00373     if (m == 3)
00374     {
00375       f[0] = a * a * a * b * b * b;
00376       f[1] = 3 * a * a * b * b * (a + b);
00377       f[2] = 3 * a * b * (a * a + 3 * a * b + b * b);
00378       f[3] = a * a * a + 9 * a * a * b + 9 * a * b * b + b * b * b;
00379       f[4] = 3 * (a * a + 3 * a * b + b * b);
00380       f[5] = 3 * (a + b);
00381       f[6] = 1;
00382     }
00383     else if (m == 4)
00384     {
00385       f[0] = a * a * a * b * b * b * b;
00386       f[1] = a * a * b * b * b * (4 * a + 3 * b);
00387       f[2] = 3 * a * b * b * (2 * a * a + 4 * a * b + b * b);
00388       f[3] = b * (4 * a * a * a + 18 * a * a * b + 12 * a * b * b + b * b * b);
00389       f[4] = a * a * a + 12 * a * a * b + 18 * a * b * b + 4 * b * b * b;
00390       f[5] = 3 * (a * a + 4 * a * b + 2 * b * b);
00391       f[6] = 3 * a + 4 * b;
00392       f[7] = 1;
00393     }
00394   }
00395   else if (l == 4)
00396   {
00397     if (m == 4)
00398     {
00399       f[0] = a * a * a * a * b * b * b * b;
00400       f[1] = 4 * a * a * a * b * b * b * (a + b);
00401       f[2] = 2 * a * a * b * b * (3 * a * a + 8 * a * b + 3 * b * b);
00402       f[3] = 4 * a * b * (a * a * a + 6 * a * a * b + 6 * a * b * b + b * b * b);
00403       f[4] = a * a * a * a + 16 * a * a * a * b + 36 * a * a * b * b + 16 * a * b * b * b + b * b * b * b;
00404       f[5] = 4 * (a * a * a + 6 * a * a * b + 6 * a * b * b + b * b * b);
00405       f[6] = 6 * a * a + 16 * a * b + 6 * b * b;
00406       f[7] = 4 * (a + b);
00407       f[8] = 1;
00408     }
00409   }
00410 }
00411 
00412 void QMCPsiPotential::g_function(int suml, double *f, double ig, double p, double *g)
00413 {
00414   
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425   
00426   if (suml > 8) {printf("Invalid suml value: %i\n", suml); exit(1);}
00427 
00428   if (suml == 0)
00429   {
00430     g[0] = 1;
00431   }
00432   else if (suml == 1)
00433   {
00434     g[0] = f[0];
00435     g[1] = -p;
00436   }
00437   else if (suml == 2)
00438   {
00439     g[0] = f[0] + 0.5 * ig;
00440     g[1] = -p * f[1] - 0.5 * ig;
00441     g[2] = p * p;
00442   }
00443   else if (suml == 3)
00444   {
00445     g[0] = f[0] + 0.5 * ig * f[2];
00446     g[1] = -p * f[1] - 0.5 * ig * f[2] - 1.5 * ig * p;
00447     g[2] = p * p * f[2] + 1.5 * ig * p;
00448     g[3] = -p * p * p;
00449   }
00450   else if (suml == 4)
00451   {
00452     g[0] = f[0] + 0.5 * ig * f[2] + 0.75 * ig * ig;
00453     g[1] = -p * f[1] - 0.5 * ig * f[2] - 1.5 * ig * p * f[3] - 1.5 * ig * ig;
00454     g[2] = p * p * f[2] + 1.5 * ig * p * f[3] + 0.75 * ig * ig + 3 * ig * p * p;
00455     g[3] = -p * p * p * f[3] - 3 * ig * p * p;
00456     g[4] = p * p * p * p;
00457   }
00458   else if (suml == 5)
00459   {
00460     g[0] = f[0] + 0.5 * ig * f[2] + 0.75 * ig * ig * f[4];
00461     g[1] = -p * f[1] - 0.5 * ig * f[2] - 1.5 * ig * p * f[3] - 1.5 * ig * ig * f[4] - 3.75 * ig * ig * p;
00462     g[2] = p * p * f[2] + 1.5 * ig * p * f[3] + 0.75 * ig * ig * f[4] + 3 * ig * p * p * f[4] + 7.5 * ig * ig * p;
00463     g[3] = -p * p * p * f[3] - 3 * ig * p * p * f[4] - 3.75 * ig * ig * p * f[5] - 5 * ig * p * p * p;
00464     g[4] = p * p * p * p * f[4] + 5 * ig * p * p * p;
00465     g[5] = -p * p * p * p * p;
00466   }
00467   else if (suml == 6)
00468   {
00469     g[0] = f[0] + 0.5 * ig * f[2] + 0.75 * ig * ig * f[4] + 1.875 * ig * ig * ig;
00470     g[1] = -p * f[1] - 0.5 * ig * f[2] - 1.5 * ig * p * f[3] - 1.5 * ig * ig * f[4] - 3.75 * ig * ig * p * f[5] - 5.625 * ig * ig * ig;
00471     g[2] = p * p * f[2] + 1.5 * ig * p * f[3] + 0.75 * ig * ig * f[4] + 3 * ig * p * p * f[4] + 7.5 * ig * ig * p * f[5] + 5.625 * ig * ig * ig + 11.25 * ig * ig * p * p;
00472     g[3] = -p * p * p * f[3] - 3 * ig * p * p * f[4] - 3.75 * ig * ig * p * f[5] - 5 * ig * p * p * p * f[5] - 1.875 * ig * ig * ig * f[6] - 22.5 * ig * ig * p * p;
00473     g[4] = p * p * p * p * f[4] + 5 * ig * p * p * p * f[5] + 11.25 * ig * ig * p * p + 7.5 * ig * p * p * p * p;
00474     g[5] = -p * p * p * p * p * f[5] - 7.5 * ig * p * p * p * p;
00475     g[6] = p * p * p * p * p * p;
00476   }
00477   else if (suml == 7)
00478   {
00479     g[0] = f[0] + 0.5 * ig * f[2] + 0.75 * ig * ig * f[4] + 1.875 * ig * ig * ig * f[6];
00480     g[1] = -p * f[1] - 0.5 * ig * f[2] - 1.5 * ig * p * f[3] - 1.5 * ig * ig * f[4] - 3.75 * ig * ig * p * f[5] - 5.625 * ig * ig * ig * f[6] - 13.125 * ig * ig * ig * p;
00481     g[2] = p * p * f[2] + 1.5 * ig * p * f[3] + 0.75 * ig * ig * f[4] + 3 * ig * p * p * f[4] + 7.5 * ig * ig * p * f[5] + 5.625 * ig * ig * ig * f[6] + 11.25 * ig * ig * p * p * f[6] + 39.375 * ig * ig * ig * p;
00482     g[3] = -p * p * p * f[3] - 3 * ig * p * p * f[4] - 3.75 * ig * ig * p * f[5] - 5 * ig * p * p * p * f[5] - 1.875 * ig * ig * ig * f[6] - 22.5 * ig * ig * p * p * f[6] - 39.375 * ig * ig * ig * p - 26.25 * ig * ig * p * p * p;
00483     g[4] = p * p * p * p * f[4] + 5 * ig * p * p * p * f[5] + 11.25 * ig * ig * p * p * f[6] + 7.5 * ig * p * p * p * p * f[6] + 13.125 * ig * ig * ig * p + 52.5 * ig * ig * p * p * p;
00484     g[5] = -p * p * p * p * p * f[5] - 7.5 * ig * p * p * p * p * f[6] - 26.25 * ig * ig * p * p * p - 10.5 * ig * p * p * p * p * p;
00485     g[6] = p * p * p * p * p * p * f[6] + 10.5 * ig * p * p * p * p * p;
00486     g[7] = -p * p * p * p * p * p * p; 
00487   }
00488   else if (suml == 8)
00489   {
00490     g[0] = f[0] + 0.5 * ig * f[2] + 0.75 * ig * ig * f[4] + 1.875 * ig * ig * ig * f[6] + 6.5625 * ig * ig * ig * ig * f[8];
00491     g[1] = -p * f[1] - 0.5 * ig * f[2] - 1.5 * ig * p * f[3] - 1.5 * ig * ig * f[4] - 3.75 * ig * ig * p * f[5] - 5.625 * ig * ig * ig * f[6] - 13.125 * ig * ig * ig * p * f[7] - 26.25 * ig * ig * ig * ig;
00492     g[2] = p * p * f[2] + 1.5 * ig * p * f[3] + 0.75 * ig * ig * f[4] + 3 * ig * p * p * f[4] + 7.5 * ig * ig * p * f[5] + 5.625 * ig * ig * ig * f[6] + 11.25 * ig * ig * p * p * f[6] + 39.375 * ig * ig * ig * p * f[7] + 39.375 * ig * ig * ig * ig + 52.5 * ig * ig * ig * p * p;
00493     g[3] = -p * p * p * f[3] - 3 * ig * p * p * f[4] - 3.75 * ig * ig * p * f[5] - 5 * ig * p * p * p * f[5] - 1.875 * ig * ig * ig * f[6] - 22.5 * ig * ig * p * p * f[6] - 39.375 * ig * ig * ig * p * f[7] - 26.25 * ig * ig * p * p * p * f[7] - 26.25 * ig * ig * ig * ig - 157.5 * ig * ig * ig * p * p;
00494     g[4] = p * p * p * p * f[4] + 5 * ig * p * p * p * f[5] + 11.25 * ig * ig * p * p * f[6] + 7.5 * ig * p * p * p * p * f[6] + 13.125 * ig * ig * ig * p * f[7] + 52.5 * ig * ig * p * p * p * f[7] + 6.5625 * ig * ig * ig * ig * f[8] + 157.5 * ig * ig * ig * p * p + 52.5 * ig * ig * p * p * p * p;
00495     g[5] = -p * p * p * p * p * f[5] - 7.5 * ig * p * p * p * p * f[6] - 26.25 * ig * ig * p * p * p * f[7] - 10.5 * ig * p * p * p * p * p * f[7] - 52.5 * ig * ig * ig * p * p - 105 * ig * ig * p * p * p * p;
00496     g[6] = p * p * p * p * p * p * f[6] + 10.5 * ig * p * p * p * p * p * f[7] + 52.5 * ig * ig * p * p * p * p + 14 * ig * p * p * p * p * p * p;
00497     g[7] = -p * p * p * p * p * p * p * f[7] - 14 * ig * p * p * p * p * p * p;
00498     g[8] = p * p * p * p * p * p * p * p;
00499   } 
00500 }