00001
00002
00003
00004
00005
00006
00007
00008 #include "QMCNuclearForces.h"
00009
00010 QMCNuclearForces::QMCNuclearForces()
00011 {}
00012
00013 QMCNuclearForces::~QMCNuclearForces()
00014 {
00015 waveValuesHFSpline.deallocate();
00016 numPolyBasisF.deallocate();
00017 nucleusContributions.deallocate();
00018 orbitals.deallocate();
00019
00020 for(int i=0; i<radialPoints.dim1(); i++)
00021 radialPoints(i).deallocate();
00022 radialPoints.deallocate();
00023
00024 for(int i=0; i<waveValuesHF.dim1(); i++)
00025 for(int j=0; j<waveValuesHF.dim2(); j++)
00026 waveValuesHF(i,j).deallocate();
00027 waveValuesHF.deallocate();
00028
00029 for(int i=0; i<basisCoeffs.dim1(); i++)
00030 for(int j=0; j<basisCoeffs.dim2(); j++)
00031 basisCoeffs(i,j).deallocate();
00032 basisCoeffs.deallocate();
00033 }
00034
00035 void QMCNuclearForces::initialize(QMCInput *Ip)
00036 {
00037 if(Ip->flags.nuclear_derivatives == "none")
00038 return;
00039
00040 Input = Ip;
00041 BF = & Input->BF;
00042 WF = & Input->WF;
00043
00044 int constNumBF = 5;
00045
00046
00047 fittingWeightM = 2.0;
00048 int numNuc = Input->Molecule.getNumberAtoms();
00049 numSamplesPerArea = 1e3;
00050
00051 numPolyBasisF.allocate(numNuc);
00052 basisCoeffs.allocate(numNuc,3);
00053 radialPoints.allocate(numNuc);
00054 waveValuesHF.allocate(numNuc,4);
00055 waveValuesHFSpline.allocate(numNuc,3);
00056
00057 for(int i=0; i<numNuc; i++)
00058 {
00059 numPolyBasisF(i) = constNumBF;
00060 for(int q=0; q<3; q++)
00061 basisCoeffs(i,q).allocate(numPolyBasisF(i));
00062 radialPoints(i).allocate(1);
00063 (radialPoints(i))(0) = 0.6;
00064 }
00065
00066 calculateNuclearContributions();
00067
00068 for(int nuc=0; nuc<numNuc; nuc++)
00069 {
00070 calcCoefficients(nuc);
00071
00072
00073 if(!false){
00074 double weight = fittingWeightM;
00075 if(Input->flags.nuclear_derivatives == "poly_hellmann_feynman")
00076 weight++;
00077
00078 cout << "Basis set coefficient terms for " << Input->Molecule.Atom_Labels(nuc) << ":\n";
00079 for(int q=0; q<3; q++)
00080 {
00081 cout << " q=" << q << " ";
00082 for(int j=basisCoeffs(nuc,q).dim1()-1; j>=0; j--)
00083 printf(" %15.7e * r^%.2g ",(basisCoeffs(nuc,q))(j),j+weight);
00084 cout << endl;
00085 }
00086 cout << endl;
00087
00088 if(Input->flags.nuclear_derivatives == "slaterpoly_hellmann_feynman")
00089 {
00090 printf("%15s %15s %15s %15s %15s %15s %15s %15s\n",
00091 "rAi",
00092 "Slater_s","Slater_px","Slater_py","Slater_pz",
00093 "Temper_x","Temper_y","Temper_z");
00094 } else {
00095 printf("%15s %15s %15s %15s\n",
00096 "rAi",
00097 "Temper_x","Temper_y","Temper_z");
00098 }
00099
00100 spliner.initializeWithFunctionValues(radialPoints(nuc),
00101 waveValuesHF(nuc,0),0.0,0.0);
00102 int numSamples = 58;
00103 double dr = (radialPoints(nuc))(radialPoints(nuc).dim1()-1)/(numSamples-1);
00104
00105 Array1D<double> temperPoints(numSamples);
00106 Array1D< Array1D<double> > temperData(3);
00107 for(int i=0; i<3; i++)
00108 temperData(i).allocate(numSamples);
00109
00110 for(int rIndex = 0; rIndex<numSamples; rIndex++)
00111 {
00112 double rad = rIndex*dr;
00113 temperPoints(rIndex) = rad;
00114 (temperData(0))(rIndex) = getTemperTerm(nuc,0,rad);
00115 (temperData(1))(rIndex) = getTemperTerm(nuc,1,rad);
00116 (temperData(2))(rIndex) = getTemperTerm(nuc,2,rad);
00117
00118 if(Input->flags.nuclear_derivatives == "slaterpoly_hellmann_feynman")
00119 {
00120 spliner.evaluate(rad);
00121 waveValuesHFSpline(nuc,0).evaluate(rad);
00122 waveValuesHFSpline(nuc,1).evaluate(rad);
00123 waveValuesHFSpline(nuc,2).evaluate(rad);
00124 printf("%15.7e %15.7e %15.7e %15.7e %15.7e %15.7e %15.7e %15.7e\n",
00125 rad,
00126 spliner.getFunctionValue(),
00127 waveValuesHFSpline(nuc,0).getFunctionValue(),
00128 waveValuesHFSpline(nuc,1).getFunctionValue(),
00129 waveValuesHFSpline(nuc,2).getFunctionValue(),
00130 getTemperTerm(nuc,0,rad),
00131 getTemperTerm(nuc,1,rad),
00132 getTemperTerm(nuc,2,rad));
00133 } else {
00134 printf("%15.7e %15.7e %15.7e %15.7e\n",
00135 rad,
00136 getTemperTerm(nuc,0,rad),
00137 getTemperTerm(nuc,1,rad),
00138 getTemperTerm(nuc,2,rad));
00139 }
00140 }
00141
00142 CubicSpline temper;
00143 printf("\n%s\n %15s %15s %15s\n ",
00144 "Temper Integrated",
00145 "Temper_x","Temper_y","Temper_z");
00146 for(int i=0; i<3; i++)
00147 {
00148 temper.initializeWithFunctionValues(temperPoints, temperData(i), 0.0, 0.0);
00149 printf("%15.7e ",temper.integrate(0,numSamples));
00150 }
00151
00152 if(Input->flags.nuclear_derivatives == "slaterpoly_hellmann_feynman")
00153 {
00154 printf("\nValues at knot points:\n%15s %15s %15s %15s %15s\n","rad","s","px","py","pz");
00155 for(int j=0; j<radialPoints(nuc).dim1(); j++)
00156 printf("%15.7f %15.7e %15.7e %15.7e %15.7e\n",
00157 (radialPoints(nuc))(j),
00158 (waveValuesHF(nuc,0))(j),
00159 (waveValuesHF(nuc,1))(j),
00160 (waveValuesHF(nuc,2))(j),
00161 (waveValuesHF(nuc,3))(j));
00162 }
00163 }
00164 cout << endl << endl;
00165 }
00166 }
00167
00168 void QMCNuclearForces::evaluate(QMCWalkerData &walkerData, Array2D<double> &xData)
00169 {
00170 Array1D<QMCWalkerData *> oneWalker = Array1D<QMCWalkerData *>(1);
00171 Array1D<Array2D<double> * > oneX = Array1D<Array2D<double> * >(1);
00172 oneWalker(0) = & walkerData;
00173 oneX(0) = & xData;
00174 evaluate(oneWalker,oneX,1);
00175 oneWalker.deallocate();
00176 oneX.deallocate();
00177 }
00178
00179 double QMCNuclearForces::getTemperTerm(int nuc, int q, double r)
00180 {
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 double radialCutoff = (radialPoints(nuc))(radialPoints(nuc).dim1()-1);
00191 if(r > radialCutoff ||
00192 (Input->flags.nuclear_derivatives != "slaterpoly_hellmann_feynman" &&
00193 Input->flags.nuclear_derivatives != "poly_hellmann_feynman"))
00194 {
00195 return 1.0;
00196 }
00197
00198
00199
00200 int numBF = basisCoeffs(nuc,q).dim1();
00201 double temperTerm = (basisCoeffs(nuc,q))(numBF-1);
00202 for(int i=numBF-2; i >= 0; i--)
00203 {
00204 temperTerm = temperTerm*r + (basisCoeffs(nuc,q))(i);
00205 }
00206
00207 if(Input->flags.nuclear_derivatives == "poly_hellmann_feynman")
00208 {
00209
00210 temperTerm *= pow(r,fittingWeightM + 1.0);
00211 } else {
00212
00213 waveValuesHFSpline(nuc,q).evaluate(r);
00214 temperTerm *= waveValuesHFSpline(nuc,q).getFunctionValue() *
00215 pow(r,fittingWeightM);
00216 }
00217
00218 return temperTerm;
00219 }
00220
00221
00222
00223
00224
00225 void QMCNuclearForces::evaluate(Array1D<QMCWalkerData *> &walkerData,
00226 Array1D<Array2D<double> * > &xData, int num)
00227 {
00228 if(Input->flags.nuclear_derivatives == "bin_force_density")
00229 {
00230 for(int walker=0; walker<num; walker++)
00231 {
00232 walkerData(walker)->nuclearDerivatives = 0;
00233
00234 int nucA = 0;
00235 double radialCutoff = (radialPoints(nucA))(radialPoints(nucA).dim1()-1);
00236
00237 for(int eleI=0; eleI<xData(0)->dim1(); eleI++)
00238 {
00239 double rAi = 0;
00240 for(int q=0; q<3; q++)
00241 {
00242 rAi +=
00243 ( (*xData(walker))(eleI,q) -
00244 Input->Molecule.Atom_Positions(nucA,q) ) *
00245 ( (*xData(walker))(eleI,q) -
00246 Input->Molecule.Atom_Positions(nucA,q) );
00247 }
00248 rAi = sqrt(rAi);
00249
00250 int binIndex = (int)( min(rAi/radialCutoff,1.0)*( getNumBins() - 1) );
00251 walkerData(walker)->nuclearDerivatives(binIndex,1) += 1;
00252 }
00253 }
00254 return;
00255 }
00256
00257 for(int walker=0; walker<num; walker++)
00258 {
00259 walkerData(walker)->nuclearDerivatives = nucleusContributions;
00260 for(int nucA=0; nucA<Input->Molecule.getNumberAtoms(); nucA++)
00261 {
00262 for(int eleI=0; eleI<xData(0)->dim1(); eleI++)
00263 {
00264 double rAi = 0;
00265 for(int q=0; q<3; q++)
00266 {
00267 rAi +=
00268 ( (*xData(walker))(eleI,q) -
00269 Input->Molecule.Atom_Positions(nucA,q) ) *
00270 ( (*xData(walker))(eleI,q) -
00271 Input->Molecule.Atom_Positions(nucA,q) );
00272 }
00273 rAi = sqrt(rAi);
00274
00275 double nuclearForce = 0;
00276 for(int q=0; q<3; q++)
00277 {
00278
00279 nuclearForce =
00280 Input->Molecule.Atom_Positions(nucA,q) -
00281 (*xData(walker))(eleI,q);
00282 nuclearForce *= Input->Molecule.Z(nucA);
00283 nuclearForce *= -1.0 / (rAi * rAi * rAi);
00284 nuclearForce *= getTemperTerm(nucA,q,rAi);
00285 walkerData(walker)->nuclearDerivatives(nucA,q) += nuclearForce;
00286 }
00287 }
00288 }
00289 }
00290
00291 if(false)
00292 {
00293 cout << "\ncalculated force:\n";
00294 for(int w=0; w<num; w++){
00295 for(int i=0; i<4; i++)
00296 printf("%s: %17.7f %17.7f %17.7f\n",
00297 Input->Molecule.Atom_Labels(i).c_str(),
00298 walkerData(w)->nuclearDerivatives(i,0),
00299 walkerData(w)->nuclearDerivatives(i,1),
00300 walkerData(w)->nuclearDerivatives(i,2));
00301 cout << endl;
00302 }
00303 }
00304
00305 }
00306
00307 void QMCNuclearForces::calcCoefficients(int whichNucleus)
00308 {
00309 if(Input->flags.nuclear_derivatives == "none" ||
00310 Input->flags.nuclear_derivatives == "bare_hellmann_feynman" ||
00311 Input->flags.nuclear_derivatives == "bin_force_density")
00312 {
00313
00314 return;
00315 }
00316
00317 double radialCutoff = (radialPoints(whichNucleus))(radialPoints(whichNucleus).dim1()-1);
00318 int numBF = numPolyBasisF(whichNucleus);
00319 Array2D<double> hilbertMatrix = Array2D<double> (numBF,numBF);
00320 Array2D<double> inverseMatrix = Array2D<double> (numBF,numBF);
00321 Array2D<double> residualVector = Array2D<double> (numBF, 1);
00322 Array2D<double> coeffs = Array2D<double> (numBF, 1);
00323 double det=0; bool isOK=true;
00324
00325 if(Input->flags.nuclear_derivatives == "poly_hellmann_feynman")
00326 {
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 for(int j=1; j<=numBF; j++)
00339 {
00340
00341
00342
00343
00344
00345
00346 residualVector(j-1,0) = pow(radialCutoff, j + 1.0) / ( j + 1.0 );
00347 for(int k=1; k<=numBF; k++)
00348 {
00349
00350
00351
00352
00353
00354 hilbertMatrix(j-1,k-1) = pow(radialCutoff, fittingWeightM + k + j + 1.0) /
00355 ( fittingWeightM + k + j + 1.0 );
00356 }
00357 }
00358
00359 hilbertMatrix.determinant_and_inverse(inverseMatrix,det,&isOK);
00360
00361 if(!isOK)
00362 {
00363 cerr << "ERROR: Hilbert matrix is not ok\n";
00364 exit(0);
00365 }
00366
00367
00368 inverseMatrix.gemm(residualVector,coeffs,false);
00369
00370 for(int i=0; i<numBF; i++)
00371 for(int coord=0; coord<3; coord++)
00372 (basisCoeffs(whichNucleus,coord))(i) = coeffs(i,0);
00373
00374 }
00375 else if(Input->flags.nuclear_derivatives == "slaterpoly_hellmann_feynman")
00376 {
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 int numPT = 100;
00388 waveMemorization(whichNucleus, numPT, radialCutoff);
00389
00390 Array1D<double> radialValues = Array1D<double>(numPT);
00391
00392 for(int coord=0; coord<3; coord++)
00393 {
00394
00395
00396
00397
00398
00399 for(int powerI=0; powerI<numBF; powerI++)
00400 {
00401 radialValues = waveValuesHF(whichNucleus,coord+1);
00402 for(int rIndex=0; rIndex<numPT; rIndex++)
00403 {
00404 radialValues(rIndex) *= fastPower((radialPoints(whichNucleus))(rIndex),powerI);
00405 }
00406
00407
00408 spliner.initializeWithFunctionValues(radialPoints(whichNucleus), radialValues, 0.0, 0.0);
00409 residualVector(powerI,0) = spliner.integrate(0, numPT);
00410 }
00411
00412
00413
00414
00415
00416 for(int powerI=0; powerI<numBF; powerI++)
00417 {
00418 for(int powerJ=0; powerJ<=powerI; powerJ++)
00419 {
00420 radialValues = waveValuesHF(whichNucleus,coord+1);
00421 for(int rIndex=0; rIndex<numPT; rIndex++)
00422 {
00423 radialValues(rIndex) *= radialValues(rIndex) *
00424 pow((radialPoints(whichNucleus))(rIndex),
00425 powerI + powerJ + fittingWeightM);
00426 }
00427
00428 spliner.initializeWithFunctionValues(radialPoints(whichNucleus), radialValues, 0.0, 0.0);
00429 hilbertMatrix(powerI,powerJ) = spliner.integrate(0,numPT);
00430
00431
00432
00433
00434
00435
00436
00437 if(powerI != powerJ) hilbertMatrix(powerJ,powerI) = hilbertMatrix(powerI,powerJ);
00438 }
00439 }
00440
00441
00442 hilbertMatrix.determinant_and_inverse(inverseMatrix,det,&isOK);
00443
00444 if(!isOK)
00445 {
00446 cerr << "ERROR: Hilbert matrix was not inverted.\n";
00447 exit(1);
00448 }
00449
00450 inverseMatrix.gemm(residualVector,coeffs,false);
00451
00452 for(int i=0; i<numBF; i++)
00453 (basisCoeffs(whichNucleus,coord))(i) = coeffs(i,0);
00454
00455 }
00456 }
00457 else
00458 {
00459 cerr << "ERROR: \"" << Input->flags.nuclear_derivatives <<
00460 "\" is an unknown nuclear force method.\n";
00461 cerr << "The choices are:\n" <<
00462 "\tnone\n" <<
00463 "\tbin_force_density\n" <<
00464 "\tbare_hellmann_feynman\n" <<
00465 "\tpoly_hellmann_feynman\n" <<
00466 "\tslaterpoly_hellmann_feynman\n" << endl;
00467 exit(1);
00468 }
00469
00470 coeffs.deallocate();
00471 hilbertMatrix.deallocate();
00472 inverseMatrix.deallocate();
00473 residualVector.deallocate();
00474 }
00475
00476 void QMCNuclearForces::waveMemorization(int whichNucleus, int numKnots, double radialCutoff)
00477 {
00478 if(numKnots <= 1)
00479 {
00480 cout << "Error: we need more than 1 shell to memorize the wavefunction!\n";
00481 exit(1);
00482 }
00483 double pi = acos(-1.0);
00484 double dr = radialCutoff/(numKnots-1);
00485
00486
00487 radialPoints(whichNucleus).allocate(numKnots);
00488 for(int i=0; i<4; i++)
00489 {
00490 waveValuesHF(whichNucleus,i).allocate(numKnots);
00491 waveValuesHF(whichNucleus,i) = 0;
00492 }
00493
00494 Array1D<double> center = Array1D<double>(3);
00495 for(int i=0; i<3; i++)
00496 center(i) = Input->Molecule.Atom_Positions(whichNucleus,i);
00497
00498 Array2D<double> cube = Array2D<double>(8,3);
00499 Array1D<qmcfloat> densities = Array1D<qmcfloat>(8);
00500 for(int irad=0; irad<numKnots; irad++)
00501 {
00502 double rad = irad*dr;
00503 (radialPoints(whichNucleus))(irad) = rad;
00504 int numSamples = (int)(rad*rad*numSamplesPerArea + 1.0);
00505
00506 double aveSurfacePerPoint = 8.0*numSamples/(4.0*pi);
00507
00508 for(int sample = 0; sample < numSamples; sample++)
00509 {
00510 generateCube(cube,rad);
00511 randomlyRotate(cube,1.0);
00512
00513 for(int i=0; i<cube.dim1(); i++)
00514 for(int coord=0; coord<3; coord++)
00515 cube(i,coord) += center(coord);
00516
00517 getDensities(cube,densities);
00518
00519
00520
00521
00522
00523
00524 for(int i=0; i<densities.dim1(); i++)
00525 {
00526 (waveValuesHF(whichNucleus,0))(irad) += densities(i);
00527 for(int j=0; j<3; j++)
00528 (waveValuesHF(whichNucleus,j+1))(irad) += densities(i)*(cube(i,j)-center(j))/rad;
00529 }
00530
00531 if(irad == 0)
00532 for(int j=0; j<3; j++)
00533 (waveValuesHF(whichNucleus,j+1))(irad) = 0;
00534 }
00535
00536 for(int i=0; i<4; i++)
00537 (waveValuesHF(whichNucleus,i))(irad) /= aveSurfacePerPoint;
00538
00539 }
00540
00541
00542 for(int q=0; q<3; q++)
00543 waveValuesHFSpline(whichNucleus,q).initializeWithFunctionValues(radialPoints(whichNucleus),
00544 waveValuesHF(whichNucleus,q+1),0.0,0.0);
00545
00546 center.deallocate();
00547 cube.deallocate();
00548 densities.deallocate();
00549 orbitals.deallocate();
00550 Chi.deallocate();
00551 }
00552
00553 void QMCNuclearForces::getDensities(Array2D<double> & X, Array1D<qmcfloat> & densities)
00554 {
00555 int nBasisFun = WF->getNumberBasisFunctions();
00556 int nOrbitals = WF->getNumberOrbitals();
00557
00558
00559 densities.allocate(X.dim1());
00560 Chi.allocate(X.dim1(),nBasisFun);
00561 orbitals.allocate(X.dim1(),nOrbitals);
00562
00563 BF->evaluateBasisFunctions(X,Chi);
00564
00565
00566 Chi.gemm(Input->WF.OrbitalCoeffs,orbitals,true);
00567
00568 densities = 0;
00569 for(int i=0; i<X.dim1(); i++)
00570 {
00571 for(int j=0; j<WF->getNumberDeterminants(); j++)
00572 {
00573 double detSum = 0.0;
00574 for(int k=0; k<nOrbitals; k++)
00575 {
00576 if(Input->WF.AlphaOccupation(j,k) != Input->WF.getUnusedIndicator())
00577 detSum += orbitals(i,k)*orbitals(i,k);
00578 if(Input->WF.BetaOccupation(j,k) != Input->WF.getUnusedIndicator())
00579 detSum += orbitals(i,k)*orbitals(i,k);
00580 }
00581 densities(i) += detSum*WF->CI_coeffs(j);
00582 }
00583 }
00584 }
00585
00586 void QMCNuclearForces::printPoints(Array2D<double> & points)
00587 {
00588 for(int i=0; i<points.dim1(); i++)
00589 {
00590 printf("%10.7f %10.7f %10.7f\n",points(i,0),points(i,1),points(i,2));
00591 }
00592 cout << endl;
00593 }
00594
00595 void QMCNuclearForces::printCubeLengths(Array2D<double> & points)
00596 {
00597 double dist;
00598 for(int i=0; i<points.dim1(); i++)
00599 {
00600 dist = sqrt( points(i,0)*points(i,0)
00601 + points(i,1)*points(i,1)
00602 + points(i,2)*points(i,2) );
00603 printf("ORG %3i %10.7f\n",i,dist);
00604
00605 for(int j=i+1; j<points.dim1(); j++)
00606 {
00607 dist = sqrt( (points(i,0)-points(j,0))*(points(i,0)-points(j,0))
00608 + (points(i,1)-points(j,1))*(points(i,1)-points(j,1))
00609 + (points(i,2)-points(j,2))*(points(i,2)-points(j,2)) );
00610 printf("%3i %3i %10.7f\n",i,j,dist);
00611 }
00612 }
00613 cout << endl;
00614 }
00615
00616 void QMCNuclearForces::generateCube(Array2D<double> & cube, double length)
00617 {
00618
00619 cube.allocate(8,3);
00620 double pos = length/sqrt(3.0);
00621 cube(0,0) = pos; cube(0,1) = pos; cube(0,2) = pos;
00622 cube(1,0) = pos; cube(1,1) = pos; cube(1,2) = -pos;
00623 cube(2,0) = pos; cube(2,1) = -pos; cube(2,2) = pos;
00624 cube(3,0) = pos; cube(3,1) = -pos; cube(3,2) = -pos;
00625 cube(4,0) = -pos; cube(4,1) = pos; cube(4,2) = pos;
00626 cube(5,0) = -pos; cube(5,1) = pos; cube(5,2) = -pos;
00627 cube(6,0) = -pos; cube(6,1) = -pos; cube(6,2) = pos;
00628 cube(7,0) = -pos; cube(7,1) = -pos; cube(7,2) = -pos;
00629 }
00630
00631 void QMCNuclearForces::randomlyRotate(Array2D<double> & points, double scale)
00632 {
00633
00634 Array2D<double> rotmat = Array2D<double>(3,3);
00635 double pi = acos(-1.0);
00636
00637 double phi = 2.0*pi*ran.unidev();
00638
00639 double theta = acos(2.0*(ran.unidev() - 0.5));
00640
00641 double psi = 2.0*pi*ran.unidev();
00642
00643 double sinpsi, cospsi, sinthe, costhe, sinphi, cosphi;
00644 sinphi = sin(phi); cosphi = cos(phi);
00645 sinpsi = sin(psi); cospsi = cos(psi);
00646 sinthe = sin(theta); costhe = cos(theta);
00647
00648
00649 rotmat(0,0) = cosphi*costhe*cospsi - sinphi*sinpsi;
00650 rotmat(0,1) = sinphi*costhe*cospsi + cosphi*sinpsi;
00651 rotmat(0,2) = -sinthe*cospsi;
00652 rotmat(1,0) = -cosphi*costhe*sinpsi - sinphi*cospsi;
00653 rotmat(1,1) = -sinphi*costhe*sinpsi + cosphi*cospsi;
00654 rotmat(1,2) = sinthe*sinpsi;
00655 rotmat(2,0) = cosphi*sinthe;
00656 rotmat(2,1) = sinphi*sinthe;
00657 rotmat(2,2) = costhe;
00658
00659 double x, y, z;
00660 for(int i=0; i<points.dim1(); i++)
00661 {
00662 x = points(i,0);
00663 y = points(i,1);
00664 z = points(i,2);
00665 for(int j=0; j<3; j++)
00666 {
00667 points(i,j) = x*rotmat(j,0)
00668 + y*rotmat(j,1)
00669 + z*rotmat(j,2);
00670 points(i,j) *= scale;
00671 }
00672 }
00673 rotmat.deallocate();
00674 }
00675
00676 void QMCNuclearForces::calculateNuclearContributions()
00677 {
00678 int numNuc = Input->Molecule.getNumberAtoms();
00679 nucleusContributions.allocate(numNuc,3);
00680 nucleusContributions = 0;
00681
00682 for(int nucA=0; nucA<numNuc; nucA++)
00683 {
00684 for(int nucB=0; nucB<numNuc; nucB++)
00685 {
00686 if( nucA == nucB ) continue;
00687
00688 double rAB = 0;
00689 for(int q=0; q<3; q++)
00690 {
00691 rAB +=
00692 (Input->Molecule.Atom_Positions(nucA,q) -
00693 Input->Molecule.Atom_Positions(nucB,q) ) *
00694 (Input->Molecule.Atom_Positions(nucA,q) -
00695 Input->Molecule.Atom_Positions(nucB,q) );
00696 }
00697 rAB = sqrt(rAB);
00698
00699 double nuclearForce = 0;
00700 for(int q=0; q<3; q++)
00701 {
00702
00703 nuclearForce =
00704 Input->Molecule.Atom_Positions(nucA,q) -
00705 Input->Molecule.Atom_Positions(nucB,q);
00706 nuclearForce *=
00707 Input->Molecule.Z(nucA) *
00708 Input->Molecule.Z(nucB);
00709 nuclearForce *=
00710 1.0 / (rAB * rAB * rAB);
00711
00712 nucleusContributions(nucA,q) += nuclearForce;
00713 }
00714 }
00715 }
00716 }
00717
00718
00719
00720