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 }