00001 #include "Williamson2CorrelationFunction.h"
00002
00003 #include "QMCInput.h"
00004 #include <sstream>
00005 #include "StringManipulation.h"
00006 #include "IeeeMath.h"
00007
00008
00009
00010
00011 #define WJ_C_TYPE 3
00012 #define WJ_SCALE 16
00013 #define WJ_OPT_A
00014
00015
00016
00017 #define EXP_CHBY
00018
00019 #define SCALE_CHBY 1
00020
00021 void Williamson2CorrelationFunction::initializeParameters(
00022 Array1D<int> & BeginningIndexOfParameterType,
00023 Array1D<double> &Parameters,
00024 Array1D<int> & BeginningIndexOfConstantType,
00025 Array1D<double> & Constants)
00026 {
00027 if( Constants.dim1() != 1 )
00028 {
00029 cerr << "ERROR: Williamson correlation function entered "
00030 << "without a constant for the cusp condition!" << endl;
00031 exit(0);
00032 }
00033
00034 if( BeginningIndexOfParameterType.dim1() != 2 )
00035 {
00036 cerr << "ERROR: Williamson correlation function entered with an incorrect "
00037 << "number of parameter types!" << endl;
00038 exit(0);
00039 }
00040
00041
00042 g = Constants(0);
00043
00044 L = Parameters(0);
00045
00046
00047
00048
00049 A = Parameters(1);
00050 B = Parameters(2);
00051
00052 if(g <= 0){
00053
00054
00055
00056 s2g = 0.0;
00057 F = 0.0;
00058 A2 = 0.0;
00059 A2F = 0.0;
00060 } else {
00061 s2g = -1.0 * sqrt(2.0 * g / L);
00062 F = s2g / A;
00063 A2 = A * A;
00064 A2F = A2 * F;
00065 }
00066
00067 n = Parameters.dim1() - 3;
00068
00069 Tn.allocate(n);
00070 dTn.allocate(n);
00071 d2Tn.allocate(n);
00072
00073 if(n >= 0)
00074 {
00075 Tn[0] = 1.0;
00076 dTn[0] = 0.0;
00077 d2Tn[0] = 0.0;
00078 }
00079
00080 if(n >= 1)
00081 {
00082 dTn[1] = 1.0;
00083 d2Tn[1] = 0.0;
00084 }
00085
00086 co.allocate(n);
00087
00088 for(int i=0; i<n; i++)
00089 co[i] = Parameters(i+3);
00090 }
00091
00092 void Williamson2CorrelationFunction::evaluate( double _r )
00093 {
00094 r = _r;
00095 double x = r * L;
00096
00097 if(isSingular())
00098 {
00099 FunctionValue = 0.0;
00100 dFunctionValue = 0.0;
00101 d2FunctionValue = -1e10;
00102 return;
00103 }
00104
00105
00106 ir = 1.0 / x;
00107 t1 = exp( x * F );
00108 t2 = A2F * t1 * ir;
00109
00110
00111
00112
00113
00114
00115
00116
00117 yuk = - A2 * (1.0 - t1) * ir;
00118 dyuk = (A2 + t1*(A2F * x - A2)) * ir * ir;
00119 d2yuk = (-2.0 * A2 + t1 * (2.0 * A2 + A2F*x*(F * x - 2.0))) * ir * ir * ir;
00120
00121 #ifdef WJ_OPT_A
00122 dyuk_a = 2.0 * yuk / A - t1 * s2g;
00123 d2yuk_a = 2.0 * dyuk / A - t1 * F * s2g;
00124 d3yuk_a = 2.0 * d2yuk / A - t1 * F * F * s2g;
00125 #endif
00126
00127 temper = exp( - WJ_SCALE*x*x );
00128 dtemper = -2.0*WJ_SCALE*x*temper;
00129 d2temper = 2.0*WJ_SCALE*temper*(2.0*WJ_SCALE*x*x - 1.0);
00130
00131 FunctionValue = yuk*temper;
00132 dFunctionValue = dyuk*temper + yuk*dtemper;
00133 d2FunctionValue = d2yuk*temper + 2.0*dyuk*dtemper + yuk*d2temper;
00134
00135 double dpc0, dpc1, dpc2;
00136 if(x > 1.0)
00137 {
00138 dG_a = 0.0;
00139 dG_xa = 0.0;
00140 dG_xxa = 0.0;
00141 dpc0 = 0.0;
00142 dpc1 = 0.0;
00143 dpc2 = 0.0;
00144 } else {
00145 dpc0 = pow(x-1,WJ_C_TYPE);
00146 dpc1 = pow(x-1,WJ_C_TYPE-1);
00147 dpc2 = pow(x-1,WJ_C_TYPE-2);
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 }
00165
00166
00167 double s, sd, s2d;
00168
00169 #ifdef SYMM_CHBY
00170
00171 xbar = 2.0*x*x - 1.0;
00172 dxbar = 4.0*x;
00173 d2xbar = 4.0;
00174 #endif
00175 #ifdef All_CHBY
00176
00177 xbar = 2.0 * x - 1.0;
00178 dxbar = 2.0;
00179 d2xbar = 0.0;
00180 #endif
00181 #ifdef EXP_CHBY
00182
00183 xbar = exp( -SCALE_CHBY*x*x );
00184 dxbar = -2.0*SCALE_CHBY*x*xbar;
00185 d2xbar = (-2.0*SCALE_CHBY + 4.0*x*x*SCALE_CHBY*SCALE_CHBY)*xbar;
00186 #endif
00187
00188 ChebyshevT(n,xbar,s,sd,s2d);
00189 s2d = d2xbar*sd + dxbar*dxbar*s2d;
00190 sd *= dxbar;
00191
00192
00193
00194 #ifdef EXP_CHBY
00195 pre = 1.0;
00196 dpre = 0.0;
00197 d2pre = 0.0;
00198 #else
00199 pre = dpc0 * x * x;
00200 dpre = dpc1 * x * (-2.0 + (2.0+WJ_C_TYPE)*x);
00201 d2pre = dpc2 *(2.0 + (1.0 + WJ_C_TYPE)*x*(-4.0 + (2.0 + WJ_C_TYPE)*x));
00202 #endif
00203
00204 FunctionValue += pre*s;
00205 dFunctionValue += pre*sd + dpre*s;
00206 d2FunctionValue += pre*s2d + 2.0*dpre*sd + d2pre*s;
00207
00208
00209 dFunctionValue *= L;
00210 d2FunctionValue *= L*L;
00211
00212 if(IeeeMath::isNaN(d2FunctionValue) || IeeeMath::isNaN(FunctionValue))
00213 {
00214 cout << "Bad Jastrow " << isSingular() << endl;
00215 print(cout);
00216 printf(" x = %20.10f r = %20.10f F = %20.10f dF = %20.10e d2F = %20.10e\n",
00217 x,r,
00218 FunctionValue,
00219 dFunctionValue,
00220 d2FunctionValue);
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230 }
00231
00232 double Williamson2CorrelationFunction::get_p_a(int ai)
00233 {
00234 double p_a = 0.0;
00235 switch(ai)
00236 {
00237
00238 case 0:
00239 if(globalInput.flags.optimize_L)
00240 {
00241 p_a = dFunctionValue * r / L;
00242 } else {
00243 p_a = 0.0;
00244 }
00245 break;
00246
00247
00248 case 1:
00249 #ifdef WJ_OPT_A
00250 p_a = temper*dyuk_a;
00251 #else
00252 p_a = 0.0;
00253 #endif
00254 break;
00255
00256
00257 case 2:
00258 p_a = dG_a;
00259 break;
00260
00261
00262 default:
00263 p_a = pre * Tn[ai-3];
00264 break;
00265 }
00266 return p_a;
00267 }
00268
00269 double Williamson2CorrelationFunction::get_p2_xa(int ai)
00270 {
00271 double p2_xa = 0.0;
00272 switch(ai)
00273 {
00274
00275 case 0:
00276 if(globalInput.flags.optimize_L)
00277 {
00278 p2_xa = dFunctionValue + d2FunctionValue * r / L;
00279 } else {
00280 p2_xa = 0.0;
00281 }
00282 break;
00283
00284
00285 case 1:
00286 #ifdef WJ_OPT_A
00287 p2_xa = d2yuk_a*temper + dyuk_a*dtemper;
00288 #else
00289 p2_xa = 0.0;
00290 #endif
00291 break;
00292
00293
00294 case 2:
00295 p2_xa = dG_xa;
00296 break;
00297
00298
00299 default:
00300 p2_xa = dxbar*pre*dTn[ai-3] + dpre*Tn[ai-3];
00301 break;
00302 }
00303 return p2_xa * L;
00304 }
00305
00306 double Williamson2CorrelationFunction::get_p3_xxa(int ai)
00307 {
00308 double p3_xxa = 0.0;
00309 switch(ai)
00310 {
00311
00312 case 0:
00313 if(globalInput.flags.optimize_L)
00314 {
00315 p3_xxa = 2.0 * d2FunctionValue / L;
00316 } else {
00317 p3_xxa = 0.0;
00318 }
00319 break;
00320
00321
00322 case 1:
00323 #ifdef WJ_OPT_A
00324 p3_xxa = d3yuk_a*temper + 2.0*d2yuk_a*dtemper + dyuk_a*d2temper;
00325 #else
00326 p3_xxa = 0.0;
00327 #endif
00328 break;
00329
00330
00331 case 2:
00332 p3_xxa = dG_xxa;
00333 break;
00334
00335
00336 default:
00337 p3_xxa = d2pre*Tn[ai-3];
00338 p3_xxa += (2.0*dpre*dxbar + pre*d2xbar)*dTn[ai-3];
00339 p3_xxa += pre*dxbar*dxbar*d2Tn[ai-3];
00340 break;
00341 }
00342 return p3_xxa * L * L;
00343 }
00344
00345 void Williamson2CorrelationFunction::print(ostream& strm)
00346 {
00347 strm << "Williamson Jastrow parameters ";
00348 #ifdef WJ_OPT_A
00349 strm << " (A optimized):" << endl;
00350 #else
00351 strm << " (A not optimized):" << endl;
00352 #endif
00353
00354 int prec = 10;
00355 int width = 18;
00356 strm.precision(prec);
00357 strm << " g = " << g;
00358 strm << " A = " << A << endl;
00359 strm << " B = " << B << endl;
00360 strm << " L = " << L << endl;
00361 strm << " F = " << F << endl;
00362
00363 strm << "x = r / " << (1.0 / L) << endl;
00364 strm << "U[x_] := " << StringManipulation::fancyDoubleToString(prec,0,-A2)
00365 << " (1.0 - Exp[ " << StringManipulation::fancyDoubleToString(prec,0,F) << " x ])/x";
00366 strm << " Exp[ -" << WJ_SCALE << " x^2 ] ";
00367 strm << StringManipulation::fancyDoubleToString(prec,0,B)
00368 << " (1/" << WJ_C_TYPE << " + x)(x-1)^" << WJ_C_TYPE;
00369
00370 #ifdef EXP_CHBY
00371 strm << " +(";
00372 #else
00373 strm << " + x^2 (x-1)^" << WJ_C_TYPE << " *(";
00374 #endif
00375
00376 for(int i=0; i<n; i++)
00377 {
00378 if(i%3 == 0) strm << endl;
00379 strm << StringManipulation::fancyDoubleToString(prec,width,co[i]);
00380 #ifdef SYMM_CHBY
00381 strm << " ChebyshevT[" << setw(2) << 2*i << ",x]";
00382 #endif
00383 #ifdef All_CHBY
00384 strm << " ChebyshevT[" << i << ",2x-1]";
00385 #endif
00386 #ifdef EXP_CHBY
00387 strm << " ChebyshevT[" << i << ",Exp[-" << SCALE_CHBY << " x^2]]";
00388 #endif
00389 }
00390 strm << ")" << endl;
00391 }
00392
00393 bool Williamson2CorrelationFunction::isSingular()
00394 {
00395 return (g > 0.0 && A < 0.0) || L <= 0.0;
00396 }
00397
00398 void Williamson2CorrelationFunction::ChebyshevT(int n, double x, double &s, double &sd, double &s2d)
00399 {
00400 s2d = 0.0;
00401
00402 if (n == 0){
00403 s = co[0];
00404 sd = 0.0;
00405 return;
00406 }
00407
00408 Tn[1] = x;
00409
00410 s = co[0] + co[1]*x;
00411 sd = co[1];
00412
00413 if (n == 1) return;
00414
00415 for (int k = 2; k < n; k++) {
00416 Tn[k] = x * 2.0 * Tn[k-1] - Tn[k-2];
00417 dTn[k] = x * 2.0 * dTn[k-1] + 2.0 * Tn[k-1] - dTn[k-2];
00418 d2Tn[k] = x * 2.0 * d2Tn[k-1] + 4.0 * dTn[k-1] - d2Tn[k-2];
00419
00420 s += co[k]*Tn[k];
00421 sd += co[k]*dTn[k];
00422 s2d += co[k]*d2Tn[k];
00423 }
00424 }
00425
00426 #undef WJ_C_TYPE