00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "QMCBasisFunction.h"
00033 #include "IeeeMath.h"
00034 #include "MathFunctions.h"
00035
00036 QMCBasisFunction::QMCBasisFunction()
00037 {}
00038
00039 void QMCBasisFunction::initialize(QMCFlags * FLAGS, QMCMolecule * MOL)
00040 {
00041 flags = FLAGS;
00042 Molecule = MOL;
00043 Xcalc.allocate(3);
00044 }
00045
00046 void QMCBasisFunction::initializeInterpolations()
00047 {
00048 use_radial_interpolation = false;
00049
00050 if( flags->use_basis_function_interpolation == 0 )
00051 {
00052
00053 }
00054 else if( flags->use_basis_function_interpolation == 1 )
00055 {
00056
00057 int norb = 0;
00058
00059 for(int i=0; i<BFCoeffs.dim1(); i++)
00060 {
00061 if( BFCoeffs(i).getNumberBasisFunctions() > norb )
00062 {
00063 norb = BFCoeffs(i).getNumberBasisFunctions();
00064 }
00065 }
00066
00067
00068 RadialFunctionInterpolation.allocate(BFCoeffs.dim1(),norb);
00069 RadialFunctionFirstDerivativeInterpolation.allocate(BFCoeffs.dim1(),
00070 norb);
00071 RadialFunctionSecondDerivativeInterpolation.allocate(BFCoeffs.dim1(),
00072 norb);
00073
00074 for(int bfc_number=0; bfc_number<BFCoeffs.dim1(); bfc_number++)
00075 {
00076 for( int orbital=0;
00077 orbital<BFCoeffs(bfc_number).getNumberBasisFunctions();
00078 orbital++)
00079 {
00080 initializeInterpolation(bfc_number,orbital,
00081 RadialFunctionInterpolation(bfc_number,orbital),0);
00082 initializeInterpolation(bfc_number,orbital,
00083 RadialFunctionFirstDerivativeInterpolation(bfc_number,orbital),1);
00084 initializeInterpolation(bfc_number,orbital,
00085 RadialFunctionSecondDerivativeInterpolation(bfc_number,orbital),2);
00086 }
00087 }
00088
00089
00090
00091 use_radial_interpolation = true;
00092 }
00093 else
00094 {
00095 cerr << "ERROR: Incorrect value for use_basis_function_splines input!"
00096 << endl;
00097 exit(0);
00098 }
00099 }
00100
00101 void QMCBasisFunction::
00102 initializeInterpolation(int bfc_number,int orbital,
00103 CubicSplineWithGeometricProgressionGrid & S,
00104 int whichDerivative)
00105 {
00106 Array1D<double> x(flags->number_basis_function_interpolation_grid_points);
00107 Array1D<double> y(flags->number_basis_function_interpolation_grid_points);
00108
00109
00110
00111 const double maxDistance = 60.0;
00112 const double beta = pow(maxDistance/
00113 flags->basis_function_interpolation_first_point,
00114 2.0/flags->number_basis_function_interpolation_grid_points);
00115
00116
00117 QMCBasisFunctionCoefficients * BFC = &BFCoeffs(bfc_number);
00118
00119
00120
00121 for(int i=0; i<x.dim1(); i++)
00122 {
00123
00124 x(i) = pow(beta,i) * (flags->basis_function_interpolation_first_point *
00125 flags->basis_function_interpolation_first_point);
00126
00127 switch( whichDerivative )
00128 {
00129 case 0:
00130 y(i) = radialFunction(*BFC,orbital,x(i));
00131 break;
00132 case 1:
00133 y(i) = radialFunctionFirstDerivative(*BFC,orbital,x(i));
00134 break;
00135 case 2:
00136 y(i) = radialFunctionSecondDerivative(*BFC,orbital,x(i));
00137 break;
00138 default:
00139 cerr << "ERROR: Trying to calculate unavailable derivatives in "
00140 << "QMCBasisFunction::initializeInterpolation(...)" << endl;
00141 exit(0);
00142 }
00143 }
00144
00145 S.setGridParameters(x(0),beta);
00146 S.initializeWithFunctionValues(x,y,0,0);
00147 }
00148
00149 void QMCBasisFunction::operator=( const QMCBasisFunction & rhs )
00150 {
00151 N_BasisFunctions = rhs.N_BasisFunctions;
00152 flags = rhs.flags;
00153 Molecule = rhs.Molecule;
00154 Xcalc = rhs.Xcalc;
00155 BFCoeffs = rhs.BFCoeffs;
00156 BFLookupTable = rhs.BFLookupTable;
00157
00158 RadialFunctionInterpolation = rhs. RadialFunctionInterpolation;
00159 RadialFunctionFirstDerivativeInterpolation =
00160 rhs.RadialFunctionFirstDerivativeInterpolation;
00161 RadialFunctionSecondDerivativeInterpolation =
00162 rhs.RadialFunctionSecondDerivativeInterpolation;
00163
00164 use_radial_interpolation = rhs.use_radial_interpolation;
00165 }
00166
00167 int QMCBasisFunction::getNumberBasisFunctions(int i)
00168 {
00169 return BFCoeffs(i).getNumberBasisFunctions();
00170 }
00171
00172 QMCBasisFunctionCoefficients* QMCBasisFunction::getBFCoeffs(int i)
00173 {
00174 return &BFCoeffs(i);
00175 }
00176
00177 istream& operator >>(istream &strm, QMCBasisFunction &rhs)
00178 {
00179 rhs.BFCoeffs.allocate(rhs.flags->Natoms);
00180
00181 for(int i=0; i<rhs.flags->Natoms; i++) strm >> rhs.BFCoeffs(i);
00182
00183 rhs.N_BasisFunctions = 0;
00184 for(int i=0; i<rhs.flags->Natoms; i++)
00185 rhs.N_BasisFunctions += rhs.BFCoeffs(i).getNumberBasisFunctions();
00186
00187 rhs.BFLookupTable.allocate(rhs.N_BasisFunctions,2);
00188
00189 int ii = 0;
00190 int Atom = 0;
00191 while(ii < rhs.N_BasisFunctions)
00192 {
00193 for(int Orbital=0; Orbital <
00194 rhs.BFCoeffs(Atom).getNumberBasisFunctions(); Orbital++)
00195 {
00196 rhs.BFLookupTable(ii,0) = Atom;
00197 rhs.BFLookupTable(ii,1) = Orbital;
00198 ii++;
00199 }
00200 Atom++;
00201 }
00202
00203 rhs.initializeInterpolations();
00204
00205 return strm;
00206 }
00207
00208 ostream& operator <<(ostream& strm,QMCBasisFunction& rhs)
00209 {
00210 strm << "&basis" << endl;
00211 for(int i=0; i<rhs.flags->Natoms; i++)
00212 strm << rhs.BFCoeffs(i);
00213 strm << "&" << endl;
00214 return strm;
00215 }
00216
00217 void QMCBasisFunction::read(string runfile)
00218 {
00219 ifstream input_file(runfile.c_str());
00220
00221 if(!input_file)
00222 {
00223 cerr << "ERROR: Could not open " << runfile << "!" << endl;
00224 exit(1);
00225 }
00226
00227 string temp_string;
00228 input_file >> temp_string;
00229 while((temp_string != "&basis") && (input_file.eof() != 1))
00230 {
00231 input_file >> temp_string;
00232 }
00233
00234 if(temp_string == "&basis") input_file >> *this;
00235 }
00236
00237 double QMCBasisFunction::
00238 radialFunction(QMCBasisFunctionCoefficients& BFC,
00239 int orbital, double r_sq)
00240 {
00241 double temp = 0.0;
00242
00243 int nGaussians = BFC.N_Gauss(orbital);
00244
00245 qmcfloat **coeffs = BFC.Coeffs.array()[orbital];
00246
00247 for(int i=0; i<nGaussians; i++)
00248 {
00249 temp += coeffs[i][1]*exp(-coeffs[i][0]*r_sq);
00250 }
00251
00252 return temp;
00253 }
00254
00255 double QMCBasisFunction::
00256 radialFunctionFirstDerivative(QMCBasisFunctionCoefficients& BFC,
00257 int orbital, double r_sq)
00258 {
00259 double temp = 0.0;
00260
00261 for(int i=0; i<BFC.N_Gauss(orbital); i++)
00262 {
00263 temp += BFC.Coeffs(orbital,i,1)*BFC.Coeffs(orbital,i,0)
00264 *exp(-BFC.Coeffs(orbital,i,0)*r_sq);
00265 }
00266
00267 temp *= (-2*sqrt(r_sq));
00268
00269 return temp;
00270 }
00271
00272 double QMCBasisFunction::radialFunctionSecondDerivative
00273 (QMCBasisFunctionCoefficients& BFC, int orbital, double r_sq)
00274 {
00275 double temp = 0.0;
00276
00277 for(int i=0; i<BFC.N_Gauss(orbital); i++)
00278 {
00279 temp += ( -2*BFC.Coeffs(orbital,i,0) + 4 * BFC.Coeffs(orbital,i,0) *
00280 BFC.Coeffs(orbital,i,0) * r_sq ) * BFC.Coeffs(orbital,i,1) *
00281 exp(-BFC.Coeffs(orbital,i,0)*r_sq);
00282 }
00283
00284 return temp;
00285 }
00286
00287 void QMCBasisFunction::evaluateBasisFunctions(Array2D<double>& X,
00288 int start, int stop,
00289 Array2D<qmcfloat>& chi_val,
00290 Array2D<qmcfloat>& chi_grx,
00291 Array2D<qmcfloat>& chi_gry,
00292 Array2D<qmcfloat>& chi_grz,
00293 Array2D<qmcfloat>& chi_lap)
00294 {
00295 int el = 0, bf;
00296 int a, b, c;
00297
00298 qmcfloat r_sq;
00299 qmcfloat p0, exp_term, temp1, temp2, temp3x, temp3y, temp3z;
00300 qmcfloat x_val, x_grx, x_gry, x_grz, x_lap;
00301
00302 temp1 = 0;
00303 temp2 = 0;
00304 temp3x = 0;
00305 temp3y = 0;
00306 temp3z = 0;
00307 for (int idx=start; idx<=stop; idx++)
00308 {
00309 bf = 0;
00310 p0 = 0.0;
00311 for (int atom=0; atom<flags->Natoms; atom++)
00312 {
00313 for (int xyz=0; xyz<3; xyz++)
00314 Xcalc(xyz) = X(idx,xyz) - Molecule->Atom_Positions(atom,xyz);
00315
00316 const int numl = BFCoeffs(atom).lmax + 1;
00317 const int numn = max(3,numl);
00318
00319
00320
00321
00322
00323
00324 double xyz_abc[3][numn][3];
00325 for(int xyz=0;xyz<3;xyz++)
00326 {
00327 xyz_abc[xyz][0][0] = 1.0;
00328 xyz_abc[xyz][1][0] = Xcalc(xyz);
00329 for(int abc=2; abc<numn; abc++)
00330 xyz_abc[xyz][abc][0] = xyz_abc[xyz][1][0] * xyz_abc[xyz][abc-1][0];
00331
00332 xyz_abc[xyz][0][1] = 0.0;
00333 xyz_abc[xyz][0][2] = 0.0;
00334 for(int abc=1; abc<numn; abc++)
00335 {
00336 xyz_abc[xyz][abc][1] = abc / xyz_abc[xyz][1][0];
00337 xyz_abc[xyz][abc][2] = abc*(abc-1.0)/xyz_abc[xyz][2][0];
00338 }
00339 }
00340 r_sq = xyz_abc[0][2][0]+xyz_abc[1][2][0]+xyz_abc[2][2][0];
00341
00342 double xyzA[numl][numl][numl][2];
00343 for(int ai=0; ai<numl; ai++)
00344 for(int bi=0; bi<numl; bi++)
00345 for(int ci=0; ci<numl; ci++)
00346 {
00347 int sum = ai+bi+ci;
00348 if(sum>numl) continue;
00349 xyzA[ai][bi][ci][0] =
00350 xyz_abc[0][ai][0]*
00351 xyz_abc[1][bi][0]*
00352 xyz_abc[2][ci][0];
00353 xyzA[ai][bi][ci][1] = 4.0*sum+6.0;
00354 }
00355
00356 const int numBF = BFCoeffs(atom).getNumberBasisFunctions();
00357 for (int j=0; j<numBF; j++)
00358 {
00359 a = BFCoeffs(atom).xyz_powers(j,0);
00360 b = BFCoeffs(atom).xyz_powers(j,1);
00361 c = BFCoeffs(atom).xyz_powers(j,2);
00362 qmcfloat** coeffs = BFCoeffs(atom).Coeffs.array()[j];
00363
00364 x_val = 0;
00365 x_grx = 0;
00366 x_gry = 0;
00367 x_grz = 0;
00368 x_lap = 0;
00369 const int nGaussians = BFCoeffs(atom).N_Gauss(j);
00370 for (int i=0; i<nGaussians; i++)
00371 {
00372 if(fabs(p0 - coeffs[i][0]) > 1e-10){
00373 p0 = coeffs[i][0];
00374 temp1 = exp(-p0*r_sq);
00375 temp2 = 4.0*r_sq*p0*p0;
00376 temp3x = -2.0*p0*xyz_abc[0][1][0];
00377 temp3y = -2.0*p0*xyz_abc[1][1][0];
00378 temp3z = -2.0*p0*xyz_abc[2][1][0];
00379 }
00380
00381 exp_term = temp1*coeffs[i][1]*xyzA[a][b][c][0];
00382
00383 x_val += exp_term;
00384 x_grx += exp_term * (xyz_abc[0][a][1] + temp3x);
00385 x_gry += exp_term * (xyz_abc[1][b][1] + temp3y);
00386 x_grz += exp_term * (xyz_abc[2][c][1] + temp3z);
00387 x_lap += exp_term * (xyz_abc[0][a][2] +
00388 xyz_abc[1][b][2] +
00389 xyz_abc[2][c][2] -
00390 p0*xyzA[a][b][c][1]+temp2);
00391 }
00392
00393 chi_val(el,bf) = (qmcfloat)x_val;
00394 chi_grx(el,bf) = (qmcfloat)x_grx;
00395 chi_gry(el,bf) = (qmcfloat)x_gry;
00396 chi_grz(el,bf) = (qmcfloat)x_grz;
00397 chi_lap(el,bf) = (qmcfloat)x_lap;
00398 bf++;
00399 }
00400 }
00401 el++;
00402 }
00403 }
00404
00405 void QMCBasisFunction::evaluateBasisFunctions(Array2D<double>& X,
00406 Array2D<qmcfloat>& chi_val)
00407 {
00408 int bf;
00409 int a, b, c;
00410
00411 qmcfloat r_sq;
00412 qmcfloat p0, temp1;
00413 qmcfloat x_val;
00414
00415 temp1 = 0;
00416 for (int idx=0; idx<X.dim1(); idx++)
00417 {
00418 bf = 0;
00419 p0 = 0.0;
00420 for (int atom=0; atom<flags->Natoms; atom++)
00421 {
00422 for (int xyz=0; xyz<3; xyz++)
00423 Xcalc(xyz) = X(idx,xyz) - Molecule->Atom_Positions(atom,xyz);
00424
00425 const int numl = BFCoeffs(atom).lmax + 1;
00426
00427
00428
00429
00430
00431
00432
00433 double xyz_abc[3][numl];
00434 for(int xyz=0;xyz<3;xyz++)
00435 {
00436 xyz_abc[xyz][0] = 1.0;
00437 xyz_abc[xyz][1] = Xcalc(xyz);
00438 for(int abc=2; abc<numl; abc++)
00439 xyz_abc[xyz][abc] = xyz_abc[xyz][1] * xyz_abc[xyz][abc-1];
00440 }
00441 r_sq = xyz_abc[0][2]+xyz_abc[1][2]+xyz_abc[2][2];
00442
00443 double xyzA[numl][numl][numl];
00444 for(int ai=0; ai<numl; ai++)
00445 for(int bi=0; bi<numl; bi++)
00446 for(int ci=0; ci<numl; ci++)
00447 {
00448 int sum = ai+bi+ci;
00449 if(sum>numl) continue;
00450 xyzA[ai][bi][ci] =
00451 xyz_abc[0][ai]*
00452 xyz_abc[1][bi]*
00453 xyz_abc[2][ci];
00454 }
00455
00456 const int numBF = BFCoeffs(atom).getNumberBasisFunctions();
00457 for (int j=0; j<numBF; j++)
00458 {
00459 a = BFCoeffs(atom).xyz_powers(j,0);
00460 b = BFCoeffs(atom).xyz_powers(j,1);
00461 c = BFCoeffs(atom).xyz_powers(j,2);
00462 qmcfloat** coeffs = BFCoeffs(atom).Coeffs.array()[j];
00463
00464 x_val = 0;
00465 const int nGaussians = BFCoeffs(atom).N_Gauss(j);
00466 for (int i=0; i<nGaussians; i++)
00467 {
00468 if(fabs(p0 - coeffs[i][0]) > 1e-10){
00469 p0 = coeffs[i][0];
00470 temp1 = exp(-p0*r_sq);
00471 temp1 = MathFunctions::fast_exp(-p0*r_sq);
00472 }
00473
00474 x_val += temp1*coeffs[i][1];
00475 }
00476
00477 chi_val(idx,bf) = (qmcfloat)x_val*xyzA[a][b][c];
00478 bf++;
00479 }
00480 }
00481 }
00482 }
00483
00484 void QMCBasisFunction::basisFunctionsOnGrid(Array2D<double>& grid,
00485 int nuc,
00486 Array2D< Array1D<double> > & angularCi,
00487 Array2D<qmcfloat>& chi_val)
00488 {
00489 int bf;
00490
00491 qmcfloat p0, temp1;
00492 temp1 = 0;
00493
00494 for (int idx=0; idx<grid.dim1(); idx++)
00495 {
00496 bf = 0;
00497 p0 = 0.0;
00498 for (int atom=0; atom<flags->Natoms; atom++)
00499 {
00500 if(atom == nuc && idx > 0){
00501
00502 const int numBF = BFCoeffs(atom).getNumberBasisFunctions();
00503 for (int j=0; j<numBF; j++)
00504 {
00505
00506
00507 chi_val(idx,bf) = chi_val(0,bf);
00508 bf++;
00509 }
00510
00511 } else {
00512
00513 double r_sq = 0.0;
00514 for (int xyz=0; xyz<3; xyz++){
00515 Xcalc(xyz) = grid(idx,xyz) - Molecule->Atom_Positions(atom,xyz);
00516 r_sq += Xcalc(xyz)*Xcalc(xyz);
00517 }
00518
00519 const int numBF = BFCoeffs(atom).getNumberBasisFunctions();
00520 for (int j=0; j<numBF; j++)
00521 {
00522 qmcfloat** coeffs = BFCoeffs(atom).Coeffs.array()[j];
00523
00524 double x_val = 0;
00525 const int nGaussians = BFCoeffs(atom).N_Gauss(j);
00526 for (int i=0; i<nGaussians; i++)
00527 {
00528 if(fabs(p0 - coeffs[i][0]) > 1e-10){
00529 p0 = coeffs[i][0];
00530 double x = -p0*r_sq;
00531 temp1 = exp(x);
00532 }
00533
00534 x_val += temp1*coeffs[i][1];
00535 }
00536
00537 chi_val(idx,bf) = (qmcfloat)x_val;
00538 bf++;
00539 }
00540 }
00541 }
00542 }
00543
00544
00545 double r = 0.0;
00546 for (int xyz=0; xyz<3; xyz++)
00547 {
00548 Xcalc(xyz) = grid(0,xyz) - Molecule->Atom_Positions(nuc,xyz);
00549 r += Xcalc(xyz)*Xcalc(xyz);
00550 }
00551 r = sqrt(r);
00552
00553 const int maxrn = 4;
00554 double rn[maxrn];
00555 rn[0] = 1.0;
00556 for(int i=1; i<maxrn; i++)
00557 rn[i] = rn[i-1]*r;
00558
00559 Array2D<double> ang(angularCi.dim1(),angularCi.dim2());
00560 ang = 0.0;
00561 double * chi_p = chi_val.array();
00562 Array1D<double> * angci_p = angularCi.array();
00563 for(int i=0; i<angularCi.dim1()*angularCi.dim2(); i++)
00564 {
00565 double * ang_p = angci_p[i].array();
00566 register double sum = ang_p[0];
00567 for(int l=1; l<angci_p[i].dim1(); l++)
00568 sum += ang_p[l] * rn[l];
00569 chi_p[i] *= sum;
00570 }
00571 }
00572
00573
00574 void QMCBasisFunction::angularGrid(Array2D<double>& grid,
00575 int nuc,
00576 Array2D< Array1D<double> > & angularCi)
00577 {
00578 int bf;
00579 int a, b, c;
00580
00581 angularCi.allocate(grid.dim1(),N_BasisFunctions);
00582
00583 for (int idx=0; idx<grid.dim1(); idx++)
00584 {
00585 bf = 0;
00586
00587 double x = grid(idx,0);
00588 double y = grid(idx,1);
00589 double z = grid(idx,2);
00590
00591
00592 for (int atom=0; atom<flags->Natoms; atom++)
00593 {
00594 double x0 = Molecule->Atom_Positions(atom,0) - Molecule->Atom_Positions(nuc,0);
00595 double y0 = Molecule->Atom_Positions(atom,1) - Molecule->Atom_Positions(nuc,1);
00596 double z0 = Molecule->Atom_Positions(atom,2) - Molecule->Atom_Positions(nuc,2);
00597
00598 const int numBF = BFCoeffs(atom).getNumberBasisFunctions();
00599 for (int j=0; j<numBF; j++)
00600 {
00601 a = BFCoeffs(atom).xyz_powers(j,0);
00602 b = BFCoeffs(atom).xyz_powers(j,1);
00603 c = BFCoeffs(atom).xyz_powers(j,2);
00604 const int numl = a+b+c+1;
00605 Array1D<double> poly(numl);
00606 poly = 0.0;
00607 poly(0) = 1.0;
00608
00609 bool print = !true;
00610 if(idx != 0) print = false;
00611 if(print){
00612 if(a > 0) printf("(%8.5f r-%8.5f)^%i ",x,x0,a);
00613 else printf("%24s","");
00614 if(b > 0) printf("(%8.5f r-%8.5f)^%i ",y,y0,b);
00615 else printf("%24s","");
00616 if(c > 0) printf("(%8.5f r-%8.5f)^%i ",z,z0,c);
00617 else printf("%24s","");
00618 printf(" %i%i%i = ",a,b,c);
00619 }
00620
00621 for(int ai=0; ai<a; ai++)
00622 {
00623 Array1D<double> temp = poly;
00624 for(int l=1; l<numl; l++)
00625 poly(l) = x*temp(l-1) - x0*temp(l);
00626 poly(0) = - x0*temp(0);
00627 }
00628
00629 for(int bi=0; bi<b; bi++)
00630 {
00631 Array1D<double> temp = poly;
00632 for(int l=1; l<numl; l++)
00633 poly(l) = y*temp(l-1) - y0*temp(l);
00634 poly(0) = - y0*temp(0);
00635 }
00636
00637 for(int ci=0; ci<c; ci++)
00638 {
00639 Array1D<double> temp = poly;
00640 for(int l=1; l<numl; l++)
00641 poly(l) = z*temp(l-1) - z0*temp(l);
00642 poly(0) = - z0*temp(0);
00643 }
00644
00645 int firstNonZero = 0;
00646 for(int i=poly.dim1()-1; i>=0; i--)
00647 if(fabs(poly(i)) > 1e-15) {
00648 firstNonZero = i;
00649 break;
00650 }
00651
00652 Array1D<double> temp(firstNonZero+1);
00653 for(int i=0; i<temp.dim1(); i++)
00654 temp(i) = poly(i);
00655 poly = temp;
00656
00657 if(print) cout << poly << endl;
00658 angularCi(idx,bf) = poly;
00659 bf++;
00660 }
00661 }
00662 }
00663 }
00664
00665