00001 #include "CambridgeThreeBodyCorrelationFunction.h"
00002 #include <string>
00003 #include <iostream>
00004 #include <iomanip>
00005 #include <sstream>
00006 #include "QMCInput.h"
00007
00008 void CambridgeThreeBodyCorrelationFunction::initializeParameters(
00009 int electron_nucleus, int electron_electron, Array1D<double> &Parameters,
00010 int power, double max_dist)
00011 {
00012 cutoff = max_dist;
00013 L = cutoff;
00014 C = power;
00015 Nen = electron_nucleus;
00016 Nee = electron_electron;
00017
00018 if( fabs(L) < 1e-10)
00019 {
00020
00021 L = 1.0e10;
00022 if(globalInput.flags.a_diag < 0.0)
00023 {
00024
00025 } else {
00026 cerr << "Error: You can not have L = " << L << " in Cambridge 2 particle Jastrows!\n";
00027 print(cerr);
00028 exit(0);
00029 }
00030 }
00031
00032 if(coeffs == 0)
00033 coeffs = new double[Nen*Nen*Nee];
00034
00035 if(globalInput.flags.calculate_Derivatives == 1)
00036 {
00037 int numParams = Parameters.dim1();
00038 p_a.allocate(numParams);
00039 p2_x1a.allocate(3,numParams);
00040 p2_x2a.allocate(3,numParams);
00041 p2_x1L.allocate(3);
00042 p2_x2L.allocate(3);
00043 p3_xxa.allocate(numParams);
00044 }
00045
00046 int ai = 0;
00047 for (int l=0; l<Nen; l++)
00048 for (int m=0; m<Nen; m++)
00049 for (int n=0; n<Nee; n++)
00050 {
00051 coeffs[ai] = Parameters(l*Nen*Nee+m*Nee+n);
00052 ai++;
00053 }
00054
00055 if(d1pow == 0)
00056 {
00057 d1pow = new double[Nen];
00058 d1pow[0] = 1.0;
00059
00060 d2pow = new double[Nen];
00061 d2pow[0] = 1.0;
00062 r12pow = new double[Nee];
00063 r12pow[0] = 1.0;
00064
00065 d1pow1 = new double[Nen];
00066 d1pow1[0] = 0.0;
00067 d2pow1 = new double[Nen];
00068 d2pow1[0] = 0.0;
00069 r12pow1 = new double[Nee];
00070 r12pow1[0] = 0.0;
00071
00072 d1pow2 = new double[Nen];
00073 d1pow2[0] = 0.0;
00074 d1pow2[1] = 0.0;
00075 d2pow2 = new double[Nen];
00076 d2pow2[0] = 0.0;
00077 d2pow2[1] = 0.0;
00078 r12pow2 = new double[Nee];
00079 r12pow2[0] = 0.0;
00080 r12pow2[1] = 0.0;
00081 }
00082
00083 grad1.allocate(3);
00084 grad2.allocate(3);
00085 }
00086
00087 CambridgeThreeBodyCorrelationFunction::CambridgeThreeBodyCorrelationFunction()
00088 {
00089 d1pow = 0;
00090 d2pow = 0;
00091 r12pow = 0;
00092 d1pow1 = 0;
00093 d2pow1 = 0;
00094 r12pow1 = 0;
00095 d1pow2 = 0;
00096 d2pow2 = 0;
00097 r12pow2 = 0;
00098 coeffs = 0;
00099 }
00100
00101 CambridgeThreeBodyCorrelationFunction::~CambridgeThreeBodyCorrelationFunction()
00102 {
00103 grad1.deallocate();
00104 grad2.deallocate();
00105
00106 p_a.deallocate();
00107 p2_x1a.deallocate();
00108 p2_x2a.deallocate();
00109 p2_x1L.deallocate();
00110 p2_x2L.deallocate();
00111 p3_xxa.deallocate();
00112
00113 delete [] d1pow;
00114 d1pow = 0;
00115
00116 delete [] d2pow;
00117 d2pow = 0;
00118
00119 delete [] r12pow;
00120 r12pow = 0;
00121
00122 delete [] d1pow1;
00123 d1pow1 = 0;
00124
00125 delete [] d2pow1;
00126 d2pow1 = 0;
00127
00128 delete [] r12pow1;
00129 r12pow1 = 0;
00130
00131 delete [] d1pow2;
00132 d1pow2 = 0;
00133
00134 delete [] d2pow2;
00135 d2pow2 = 0;
00136
00137 delete [] r12pow2;
00138 r12pow2 = 0;
00139
00140 delete [] coeffs;
00141 coeffs = 0;
00142
00143 r1v.deallocate();
00144 r2v.deallocate();
00145 r12v.deallocate();
00146 }
00147
00148
00149
00150
00151 void CambridgeThreeBodyCorrelationFunction::evaluate(Array1D<double> &xyz12v,
00152 double dist12)
00153 {
00154 FunctionValue = 0.0;
00155 LaplacianValue = 0.0;
00156 grad1 = 0.0;
00157 grad2 = 0.0;
00158 if(d1 > 0.0 || d2 > 0.0) return;
00159
00160 r12 = dist12 * L;
00161 r12v = xyz12v;
00162 for (int i=1; i<Nee; i++)
00163 {
00164 r12pow[i] = r12pow[i-1]*r12;
00165 r12pow1[i] = r12pow[i-1] * i;
00166
00167 if(i < 2) continue;
00168 r12pow2[i] = r12pow[i-2] * i * (i-1);
00169 }
00170
00171 p2_x1L = 0.0;
00172 p2_x2L = 0.0;
00173
00174 register double polynomial_sum = 0.0;
00175 register double lpolynomial_sum = 0.0;
00176 register double l2polynomial_sum = 0.0;
00177 register double lnpolynomial_sum = 0.0;
00178 register double mpolynomial_sum = 0.0;
00179 register double m2polynomial_sum = 0.0;
00180 register double mnpolynomial_sum = 0.0;
00181 register double npolynomial_sum = 0.0;
00182 register double n2polynomial_sum = 0.0;
00183
00184 register double coeff = 0.0;
00185
00186 int ai = 0;
00187 register double term;
00188 register double _l, _m, _n;
00189 register double ln, mn;
00190 register double l2, m2, n2;
00191
00192
00193
00194
00195
00196
00197 if(globalInput.flags.calculate_Derivatives == 1)
00198 {
00199 for (int l=0; l<Nen; l++)
00200 for (int m=0; m<Nen; m++)
00201 {
00202 double lm = d1pow[l]*d2pow[m];
00203 double dlm = d1pow1[l]*d2pow[m];
00204 double ldm = d1pow[l]*d2pow1[m];
00205 double d2lm = d1pow2[l]*d2pow[m];
00206 double ld2m = d1pow[l]*d2pow2[m];
00207
00208 for (int n=0; n<Nee; n++)
00209 {
00210 coeff = coeffs[ai];
00211
00212
00213 term = lm*r12pow[n];
00214
00215
00216 _l = dlm*r12pow[n];
00217 _m = ldm*r12pow[n];
00218 _n = lm*r12pow1[n];
00219
00220
00221 ln = dlm*r12pow1[n];
00222 mn = ldm*r12pow1[n];
00223
00224
00225 l2 = d2lm*r12pow[n];
00226 m2 = ld2m*r12pow[n];
00227 n2 = lm*r12pow2[n];
00228
00229 polynomial_sum += coeff * term;
00230 lpolynomial_sum += coeff * _l;
00231 mpolynomial_sum += coeff * _m;
00232 npolynomial_sum += coeff * _n;
00233 lnpolynomial_sum += coeff * ln;
00234 mnpolynomial_sum += coeff * mn;
00235 l2polynomial_sum += coeff * l2;
00236 m2polynomial_sum += coeff * m2;
00237 n2polynomial_sum += coeff * n2;
00238
00239 p_a(ai) = pre1*pre2*term;
00240
00241 dU_dr12 = pre1*pre2*_n;
00242 dU_dr1 = (d1pre1*term + pre1*_l)*pre2;
00243 dU_dr2 = (d1pre2*term + pre2*_m)*pre1;
00244
00245 double dL = coeff * (l + m + n) / L;
00246
00247 for (int i=0; i<3; i++)
00248 {
00249 p2_x1a(i,ai) = L*(dU_dr1*r1v(i) + dU_dr12*r12v(i));
00250 p2_x2a(i,ai) = L*(dU_dr2*r2v(i) - dU_dr12*r12v(i));
00251 p2_x1L(i) += dL * p2_x1a(i,ai);
00252 p2_x2L(i) += dL * p2_x2a(i,ai);
00253 }
00254
00255 p3_xxa(ai) = getLapPoly(term, _l, _m, _n,
00256 l2, m2, n2, ln, mn,
00257 pre1, pre2, d1pre1,
00258 d1pre2, d2pre1, d2pre2);
00259
00260 dU_L += dL * p_a(ai);
00261 dU_Lrr += dL * p3_xxa(ai);
00262
00263 ai++;
00264 }
00265 }
00266 } else {
00267
00268
00269
00270 for (int l=0; l<Nen; l++)
00271 for (int m=0; m<Nen; m++)
00272 {
00273 register double lm = d1pow[l]*d2pow[m];
00274 register double dlm = d1pow1[l]*d2pow[m];
00275 register double ldm = d1pow[l]*d2pow1[m];
00276 register double d2lm = d1pow2[l]*d2pow[m];
00277 register double ld2m = d1pow[l]*d2pow2[m];
00278
00279 for (int n=0; n<Nee; n++)
00280 {
00281 coeff = coeffs[ai];
00282 ai++;
00283 if(fabs(coeff) < 1e-30) continue;
00284
00285
00286 term = lm*r12pow[n];
00287
00288
00289 _l = dlm*r12pow[n];
00290 _m = ldm*r12pow[n];
00291 _n = lm*r12pow1[n];
00292
00293
00294 ln = dlm*r12pow1[n];
00295 mn = ldm*r12pow1[n];
00296
00297
00298 l2 = d2lm*r12pow[n];
00299 m2 = ld2m*r12pow[n];
00300 n2 = lm*r12pow2[n];
00301
00302 polynomial_sum += coeff * term;
00303 lpolynomial_sum += coeff * _l;
00304 mpolynomial_sum += coeff * _m;
00305 npolynomial_sum += coeff * _n;
00306 lnpolynomial_sum += coeff * ln;
00307 mnpolynomial_sum += coeff * mn;
00308 l2polynomial_sum += coeff * l2;
00309 m2polynomial_sum += coeff * m2;
00310 n2polynomial_sum += coeff * n2;
00311 }
00312 }
00313 }
00314
00315 FunctionValue = pre1*pre2*polynomial_sum;
00316
00317 dU_dr12 = pre1*pre2*npolynomial_sum;
00318 dU_dr1 = (d1pre1*polynomial_sum + pre1*lpolynomial_sum)*pre2;
00319 dU_dr2 = (d1pre2*polynomial_sum + pre2*mpolynomial_sum)*pre1;
00320
00321 for (int i=0; i<3; i++)
00322 {
00323 grad1(i) = L*(dU_dr1*r1v(i) + dU_dr12*r12v(i));
00324 grad2(i) = L*(dU_dr2*r2v(i) - dU_dr12*r12v(i));
00325 }
00326
00327 LaplacianValue = getLapPoly(polynomial_sum,
00328 lpolynomial_sum, mpolynomial_sum, npolynomial_sum,
00329 l2polynomial_sum, m2polynomial_sum, n2polynomial_sum,
00330 lnpolynomial_sum, mnpolynomial_sum,
00331 pre1, pre2, d1pre1, d1pre2, d2pre1, d2pre2);
00332
00333 if(globalInput.flags.calculate_Derivatives == 1 &&
00334 globalInput.flags.optimize_L == 1)
00335 {
00336 dU_L += pre1_L * pre2 * polynomial_sum;
00337 dU_L += pre1 * pre2_L * polynomial_sum;
00338
00339 dU_dr12 = pre1_L*pre2*npolynomial_sum;
00340 dU_dr1 = (d1pre1_L*polynomial_sum + pre1_L*lpolynomial_sum)*pre2;
00341 dU_dr2 = (d1pre2*polynomial_sum + pre2*mpolynomial_sum)*pre1_L;
00342
00343 for (int i=0; i<3; i++)
00344 {
00345 p2_x1L(i) += L*(dU_dr1*r1v(i) + dU_dr12*r12v(i));
00346 p2_x2L(i) += L*(dU_dr2*r2v(i) - dU_dr12*r12v(i));
00347 }
00348
00349 dU_Lrr += getLapPoly(polynomial_sum,
00350 lpolynomial_sum, mpolynomial_sum, npolynomial_sum,
00351 l2polynomial_sum, m2polynomial_sum, n2polynomial_sum,
00352 lnpolynomial_sum, mnpolynomial_sum,
00353 pre1_L, pre2, d1pre1_L, d1pre2, d2pre1_L, d2pre2);
00354
00355 dU_dr12 = pre1*pre2_L*npolynomial_sum;
00356 dU_dr1 = (d1pre1*polynomial_sum + pre1*lpolynomial_sum)*pre2_L;
00357 dU_dr2 = (d1pre2_L*polynomial_sum + pre2_L*mpolynomial_sum)*pre1;
00358
00359 for (int i=0; i<3; i++)
00360 {
00361 p2_x1L(i) += L*(dU_dr1*r1v(i) + dU_dr12*r12v(i));
00362 p2_x2L(i) += L*(dU_dr2*r2v(i) - dU_dr12*r12v(i));
00363 }
00364
00365 dU_Lrr += getLapPoly(polynomial_sum,
00366 lpolynomial_sum, mpolynomial_sum, npolynomial_sum,
00367 l2polynomial_sum, m2polynomial_sum, n2polynomial_sum,
00368 lnpolynomial_sum, mnpolynomial_sum,
00369 pre1, pre2_L, d1pre1, d1pre2_L, d2pre1, d2pre2_L);
00370 }
00371 }
00372
00373 double CambridgeThreeBodyCorrelationFunction::getLapPoly(double term,
00374 double lterm, double mterm, double nterm,
00375 double l2term, double m2term, double n2term,
00376 double lnterm, double mnterm,
00377 double p1, double p2,
00378 double d1p1, double d1p2,
00379 double d2p1, double d2p2)
00380 {
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 double lap = 2.0*(2.0 * dU_dr12 / r12 +
00398 dU_dr1 / r1 +
00399 dU_dr2 / r2);
00400
00401 double d2U_d2r1 = p2*(d2p1 * term + 2.0 * d1p1 * lterm + p1 * l2term);
00402 double d2U_d2r2 = p1*(d2p2 * term + 2.0 * d1p2 * mterm + p2 * m2term);
00403 double d2U_d2r12 = p1*p2*n2term;
00404 lap += 2.0 * d2U_d2r12 + d2U_d2r1 + d2U_d2r2;
00405
00406 double d2U_dr1r12 = 2.0 * p2 * (d1p1 * nterm + p1 * lnterm);
00407 double d2U_dr2r12 = 2.0 * p1 * (d1p2 * nterm + p2 * mnterm);
00408 for(int i=0; i<3; i++)
00409 lap += r12v(i)*( r1v(i)*d2U_dr1r12 - r2v(i)*d2U_dr2r12 );
00410
00411 return lap * L * L;
00412 }
00413
00414 bool CambridgeThreeBodyCorrelationFunction::setElectron(bool first, Array1D<double> &xyz, double dist)
00415 {
00416
00417 if(first)
00418 {
00419 r1 = dist * L;
00420 d1 = r1 - 1.0;
00421 if(d1 > 0.0) return false;
00422
00423 r1v = xyz;
00424 pre1 = pow(d1,C);
00425 d1pre1 = pre1 * C / d1;
00426 d2pre1 = (C - 1.0) * d1pre1 / d1;
00427
00428 if(globalInput.flags.calculate_Derivatives == 1)
00429 {
00430 pre1_L = d1pre1 * r1 / L;
00431 d1pre1_L = pre1_L / d1 * (C - 1.0 / r1);
00432 d2pre1_L = d2pre1 / d1 * (C * r1 - 2.0) / L;
00433
00434 dU_L = 0.0;
00435 dU_Lrr = 0.0;
00436 }
00437
00438
00439 for (int i=1; i<Nen; i++)
00440 {
00441 d1pow[i] = d1pow[i-1]*r1;
00442 d1pow1[i] = d1pow[i-1] * i;
00443
00444 if(i < 2) continue;
00445 d1pow2[i] = d1pow[i-2] * i * (i-1);
00446 }
00447 } else {
00448 r2 = dist * L;
00449 d2 = r2 - 1.0;
00450 if(d2 > 0.0) return false;
00451
00452 r2v = xyz;
00453 pre2 = pow(d2,C);
00454 d1pre2 = pre2 * C / d2;
00455 d2pre2 = (C - 1.0) * d1pre2 / d2;
00456
00457
00458 for (int i=1; i<Nen; i++)
00459 {
00460 d2pow[i] = d2pow[i-1]*r2;
00461 d2pow1[i] = d2pow[i-1] * i;
00462
00463 if(i < 2) continue;
00464 d2pow2[i] = d2pow[i-2] * i * (i-1);
00465 }
00466
00467 if(globalInput.flags.calculate_Derivatives == 1)
00468 {
00469 pre2_L = d1pre2 * r2 / L;
00470 d1pre2_L = pre2_L / d2 * (C - 1.0 / r2);
00471 d2pre2_L = d2pre2 / d2 * (C * r2 - 2.0) / L;
00472
00473 dU_L = 0.0;
00474 dU_Lrr = 0.0;
00475 }
00476 }
00477 return true;
00478 }
00479
00480 double CambridgeThreeBodyCorrelationFunction::getFunctionValue()
00481 {
00482 return FunctionValue;
00483 }
00484
00485 double CambridgeThreeBodyCorrelationFunction::getFunctionValue(double r12,
00486 double r1,
00487 double r2)
00488 {
00489 r1 *= L;
00490 r2 *= L;
00491 d1 = r1 - 1.0;
00492 d2 = r2 - 1.0;
00493 if(d1 > 0.0 || d2 > 0.0) return 0.0;
00494
00495 r12 = r12 * L;
00496
00497 for (int i=1; i<Nee; i++)
00498 r12pow[i] = r12pow[i-1]*r12;
00499 for (int i=1; i<Nen; i++)
00500 {
00501 d1pow[i] = d1pow[i-1]*r1;
00502 d2pow[i] = d2pow[i-1]*r2;
00503 }
00504
00505 register double polynomial_sum = 0.0;
00506 register double coeff = 0.0;
00507 int ai = 0;
00508
00509
00510
00511 for (int l=0; l<Nen; l++)
00512 for (int m=0; m<Nen; m++)
00513 {
00514 register double lm = d1pow[l]*d2pow[m];
00515 for (int n=0; n<Nee; n++)
00516 {
00517 coeff = coeffs[ai];
00518 ai++;
00519 if(fabs(coeff) < 1e-30) continue;
00520 polynomial_sum += coeff * lm*r12pow[n];
00521 }
00522 }
00523
00524 return pow(d1,C)*pow(d2,C)*polynomial_sum;
00525 }
00526
00527 double CambridgeThreeBodyCorrelationFunction::get_p_a(int ai)
00528 {
00529 if(d1 > 0.0 || d2 > 0.0) return 0.0;
00530
00531 if(globalInput.flags.optimize_L == 1)
00532 {
00533 if(ai == 0) return dU_L;
00534 } else {
00535 if(ai == 0) return 0.0;
00536 }
00537 return p_a(ai-1);
00538 }
00539
00540 Array1D<double>* CambridgeThreeBodyCorrelationFunction::getElectron1Gradient()
00541 {
00542 return &grad1;
00543 }
00544
00545 Array1D<double>* CambridgeThreeBodyCorrelationFunction::getElectron2Gradient()
00546 {
00547 return &grad2;
00548 }
00549
00550 double CambridgeThreeBodyCorrelationFunction::get_p2_xa(bool e1, int xyz, int ai)
00551 {
00552 if(d1 > 0.0 || d2 > 0.0) return 0.0;
00553
00554 if(globalInput.flags.optimize_L == 1)
00555 {
00556 if(ai == 0)
00557 {
00558 if(e1) return p2_x1L(xyz);
00559 else return p2_x2L(xyz);
00560 }
00561 } else {
00562 if(ai == 0) return 0.0;
00563 }
00564 if(e1) return p2_x1a(xyz,ai-1);
00565 return p2_x2a(xyz,ai-1);
00566 }
00567
00568 double CambridgeThreeBodyCorrelationFunction::getLaplacianValue()
00569 {
00570 return LaplacianValue;
00571 }
00572
00573 double CambridgeThreeBodyCorrelationFunction::get_p3_xxa(int ai)
00574 {
00575 if(d1 > 0.0 || d2 > 0.0) return 0.0;
00576
00577 if(globalInput.flags.optimize_L == 1)
00578 {
00579 if(ai == 0) return dU_Lrr;
00580 } else {
00581 if(ai == 0) return 0.0;
00582 }
00583 return p3_xxa(ai-1);
00584 }
00585
00586 double CambridgeThreeBodyCorrelationFunction::getCutoffDist()
00587 {
00588 return cutoff;
00589 }
00590
00591 void CambridgeThreeBodyCorrelationFunction::print(ostream & strm)
00592 {
00593 strm.unsetf(ios::scientific);
00594 strm << "Cambridge 3 particle jastrow parameters:" << endl
00595 << " Nen = " << Nen
00596 << " Nee = " << Nee
00597 << " C = " << C
00598 << " L = " << cutoff;
00599 if(globalInput.flags.optimize_L == 1)
00600 strm << " (optimized)" << endl;
00601 else
00602 strm << " (not optimized)" << endl;
00603
00604
00605 bool symmetric = true;
00606 bool extraPrec = false;
00607 bool printZero = false;
00608
00609
00610 int coWidth, coPrec;
00611 if(extraPrec)
00612 {
00613 coPrec = 15;
00614 coWidth = 20;
00615 } else {
00616 coPrec = 7;
00617 coWidth = 10;
00618 }
00619
00620 strm.unsetf(ios::scientific);
00621 strm << "x1 = r1 / " << setprecision(coPrec) << (1.0 / L) << endl;
00622 strm << "x2 = r2 / " << setprecision(coPrec) << (1.0 / L) << endl;
00623 strm << "x12 = r12 / " << setprecision(coPrec) << (1.0 / L) << endl;
00624 strm << "(x1 - 1)^" << C;
00625 strm << " (x2 - 1)^" << C;
00626 strm << " (" << endl;
00627
00628 int counter = 0;
00629 for(int p=0; p<max(Nen,Nee); p++)
00630 for (int n=0; n<Nee; n++)
00631 for (int l=0; l<Nen; l++)
00632 for (int m=0; m<=l; m++)
00633 if( (l == p || m == p || n == p) &&
00634 (l <= p && m <= p && n <= p))
00635 {
00636 double coeff = coeffs[l*Nen*Nee+m*Nee+n];
00637 if(fabs(coeff) < 1e-50 && !printZero)
00638 continue;
00639
00640 if(counter % 4 == 0 && counter != 0)
00641 strm << endl;
00642 counter++;
00643
00644 if(fabs(coeff - coeffs[m*Nen*Nee+l*Nee+n]) > 1e-20)
00645 symmetric = false;
00646
00647 stringstream co;
00648 co.precision(coPrec);
00649 co.width(coWidth);
00650 co.setf(ios::showpos);
00651 co << left << coeff;
00652
00653 stringstream temp;
00654 stringstream lm;
00655 if(l > 0) lm << "x1";
00656 if(l > 1) lm << "^" << l;
00657 if(m > 0) lm << " x2";
00658 if(m > 1) lm << "^" << m;
00659
00660 if(l != m)
00661 {
00662 lm << " + ";
00663 if(l > 0) lm << "x2";
00664 if(l > 1) lm << "^" << l;
00665 if(m > 0) lm << " x1";
00666 if(m > 1) lm << "^" << m;
00667 temp << " (" << lm.str() << ")";
00668 } else {
00669 if(l > 0 && m > 0)
00670 temp << " " << lm.str();
00671 }
00672
00673 if(n > 0) temp << " x12";
00674 if(n > 1) temp << "^" << n;
00675
00676 int extrawidth = co.str().length() - coWidth;
00677 strm << setw(coWidth) << co.str() << setw(31-extrawidth) << left << temp.str();
00678 }
00679 strm << ")";
00680
00681 if(!symmetric)
00682 strm << " (not symmetric!!)";
00683
00684 strm << endl;
00685 strm << right;
00686 }