00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "QMCWalker.h"
00014 #include "QMCSurfer.h"
00015 #include "QMCPotential_Energy.h"
00016 #include "math.h"
00017
00018 const double QMCWalker::maxFWAsymp = 1.0;
00019 long int QMCWalker::nextID = 0;
00020
00021 QMCWalker::QMCWalker()
00022 {
00023 TrialWalker = 0;
00024 OriginalWalker = 0;
00025
00026 dW = 1.0;
00027 weight = 1.0;
00028 age = 0;
00029 dR2 = 0.0;
00030 ageMoved = -1;
00031 numWarnings = 0;
00032 }
00033
00034 void QMCWalker::branchID()
00035 {
00036 for(int i=numAncestors-1; i > 0; i--)
00037 genealogy[i] = genealogy[i-1];
00038 genealogy[0] = ++nextID;
00039 }
00040
00041 void QMCWalker::newID()
00042 {
00043 genealogy[0] = ++nextID;
00044 for(int i=1; i < numAncestors; i++)
00045 genealogy[i] = -1;
00046 }
00047
00048 QMCWalker::QMCWalker( const QMCWalker & rhs )
00049 {
00050 TrialWalker = 0;
00051 OriginalWalker = 0;
00052
00053 *this = rhs;
00054 }
00055
00056 QMCWalker::~QMCWalker()
00057 {
00058 TrialWalker = 0;
00059
00060 delete OriginalWalker;
00061 OriginalWalker = 0;
00062
00063 Input = 0;
00064
00065 R.deallocate();
00066
00067 numFWSteps.clear();
00068
00069 isCollectingFWResults.deallocate();
00070 fwNormalization.deallocate();
00071 fwR12.deallocate();
00072 fwR2.deallocate();
00073 fwiR12.deallocate();
00074 fwiR.deallocate();
00075 fwEnergy.deallocate();
00076 fwKineticEnergy.deallocate();
00077 fwKineticEnergy_grad.deallocate();
00078 fwPotentialEnergy.deallocate();
00079
00080 cs_Energies.deallocate();
00081 cs_Weights.deallocate();
00082 p3_xxa.deallocate();
00083 rp_a.deallocate();
00084
00085 for(int d1=0; d1<fwNuclearForces.dim1(); d1++)
00086 for(int d2=0; d2<fwNuclearForces.dim2(); d2++)
00087 fwNuclearForces(d1,d2).deallocate();
00088 fwNuclearForces.deallocate();
00089 }
00090
00091 void QMCWalker::operator=( const QMCWalker & rhs )
00092 {
00093
00094
00095
00096
00097
00098 weight = rhs.weight;
00099 age = rhs.age;
00100 ageMoved = rhs.ageMoved;
00101 numWarnings = rhs.numWarnings;
00102
00103 for(int i=0; i<numAncestors; i++)
00104 genealogy[i] = rhs.genealogy[i];
00105
00106 Input = rhs.Input;
00107 move_accepted = rhs.move_accepted;
00108 AcceptanceProbability = rhs.AcceptanceProbability;
00109 localEnergy = rhs.localEnergy;
00110 kineticEnergy = rhs.kineticEnergy;
00111 potentialEnergy = rhs.potentialEnergy;
00112 neEnergy = rhs.neEnergy;
00113 eeEnergy = rhs.eeEnergy;
00114
00115 fwNormalization = rhs.fwNormalization;
00116 fwR12 = rhs.fwR12;
00117 fwR2 = rhs.fwR2;
00118 fwiR12 = rhs.fwiR12;
00119 fwiR = rhs.fwiR;
00120 fwEnergy = rhs.fwEnergy;
00121 fwKineticEnergy = rhs.fwKineticEnergy;
00122 fwKineticEnergy_grad = rhs.fwKineticEnergy_grad;
00123 fwPotentialEnergy = rhs.fwPotentialEnergy;
00124 isCollectingFWResults = rhs.isCollectingFWResults;
00125 numFWSteps = rhs.numFWSteps;
00126
00127 if(Input->flags.nuclear_derivatives != "none"){
00128 fwNuclearForces.allocate(rhs.fwNuclearForces.dim1(),
00129 rhs.fwNuclearForces.dim2());
00130
00131 for (int d1=0; d1<fwNuclearForces.dim1(); d1++)
00132 {
00133 for (int d2=0; d2<fwNuclearForces.dim2(); d2++)
00134 {
00135 fwNuclearForces(d1,d2).allocate(rhs.fwNuclearForces.get(d1,d2).dim1(),2);
00136 fwNuclearForces(d1,d2) = rhs.fwNuclearForces.get(d1,d2);
00137 }
00138 }
00139 }
00140
00141 cs_Energies.allocate(rhs.cs_Energies.dim1());
00142 cs_Weights.allocate(rhs.cs_Weights.dim1());
00143 p3_xxa.allocate(rhs.p3_xxa.dim1());
00144 rp_a.allocate(rhs.rp_a.dim1());
00145
00146 distanceMovedAccepted = rhs.distanceMovedAccepted;
00147 dR2 = rhs.dR2;
00148 R = rhs.R;
00149 walkerData = rhs.walkerData;
00150 }
00151
00152 void QMCWalker::initializePropagation(QMCWalkerData * &data,
00153 Array2D<double> * &rToCalc,
00154 int iteration)
00155 {
00156 this->iteration = iteration;
00157 createChildWalkers();
00158
00159 int step = iteration + Input->flags.equilibration_steps - 1;
00160
00161 int whichE = -1;
00162 if(globalInput.flags.one_e_per_iter != 0)
00163 whichE = step % R.dim1();
00164
00165 TrialWalker->walkerData.whichE = whichE;
00166 OriginalWalker->walkerData.whichE = whichE;
00167
00168 forwardGreensFunction = TrialWalker->moveElectrons();
00169 data = & TrialWalker->walkerData;
00170 rToCalc = & TrialWalker->R;
00171 }
00172
00173 void QMCWalker::processPropagation(QMCFunctions & QMF, bool writeConfigs)
00174 {
00175 if(globalInput.flags.use_surfer == 1)
00176 {
00177 static int iteration_to_stop = iteration;
00178
00179 if(iteration == iteration_to_stop)
00180 {
00181 static QMCSurfer s;
00182 cout << "\n**** Surfing walker " << ID(false);
00183 iteration_to_stop = s.mainMenu(&QMF, iteration, R);
00184 }
00185 }
00186
00187
00188 QMCDouble reverseGreensFunction =
00189 calculateReverseGreensFunction();
00190 double GreensFunctionRatio =
00191 (double)(reverseGreensFunction/forwardGreensFunction);
00192
00193 if (IeeeMath::isNaN(GreensFunctionRatio)){
00194 cout << "Error: bad Green's ratio " << GreensFunctionRatio << endl;
00195 cout << " Forward = " << forwardGreensFunction << endl;
00196 cout << " Reverse = " << reverseGreensFunction << endl;
00197 calculateMoveAcceptanceProbability(0.0);
00198 }
00199 else
00200 calculateMoveAcceptanceProbability(GreensFunctionRatio);
00201
00202 acceptOrRejectMove();
00203
00204
00205
00206 if(walkerData.whichE == -1 ||
00207 walkerData.whichE == 0)
00208 reweight_walker();
00209
00210 if(getWeight() == 0)
00211 return;
00212
00213 if(move_accepted == false)
00214 {
00215 dR2 = OriginalWalker->dR2;
00216 }
00217
00218 if(writeConfigs)
00219 {
00220
00221
00222
00223
00224
00225 double p = TrialWalker->AcceptanceProbability;
00226 double q = 1.0 - p;
00227
00228 TrialWalker->walkerData.writeConfigs(TrialWalker->R,p);
00229 OriginalWalker->walkerData.writeConfigs(OriginalWalker->R,q);
00230 }
00231
00232 calculateObservables();
00233
00234 if(move_accepted == false)
00235 {
00236 R = OriginalWalker->R;
00237 AcceptanceProbability = OriginalWalker->AcceptanceProbability;
00238
00239 if(globalInput.flags.one_e_per_iter == 0)
00240 {
00241 walkerData = OriginalWalker->walkerData;
00242 } else {
00243 walkerData.updateDistances(R);
00244 QMF.evaluate(R,walkerData);
00245 }
00246 }
00247
00248 if( TrialWalker->isSingular() )
00249 {
00250 cerr << "WARNING: Reinitializing a singular walker!! " << ID(true) << endl;
00251 initializeWalkerPosition(QMF);
00252 }
00253
00254 if(writeConfigs)
00255 {
00256
00257
00258
00259
00260
00261 }
00262 }
00263
00264 QMCDouble QMCWalker::moveElectrons()
00265 {
00266
00267 if( Input->flags.dt <= 0 )
00268 {
00269 cerr << "ERROR: Negative dt value! (" << Input->flags.dt << ")" << endl;
00270 exit(0);
00271 }
00272 QMCDouble gr = QMCDouble();
00273
00274 if(Input->flags.sampling_method == "no_importance_sampling")
00275 gr = moveElectronsNoImportanceSampling();
00276 else if(Input->flags.sampling_method == "importance_sampling" )
00277 gr = moveElectronsImportanceSampling();
00278 else if(Input->flags.sampling_method == "umrigar93_importance_sampling")
00279 gr = moveElectronsUmrigar93ImportanceSampling();
00280 else if(Input->flags.sampling_method == "umrigar93_accelerated_sampling")
00281 gr = moveElectronsUmrigar93AcceleratedSampling();
00282 else
00283 {
00284 cerr << "ERROR: Improper value for sampling_method set ("
00285 << Input->flags.sampling_method << ")!" << endl;
00286 exit(0);
00287 }
00288
00289 walkerData.updateDistances(R);
00290 return gr;
00291 }
00292
00293 QMCDouble QMCWalker::moveElectronsNoImportanceSampling()
00294 {
00295 int whichE = walkerData.whichE;
00296
00297
00298 double sigma = sqrt(Input->flags.dt);
00299 dR2 = 0;
00300
00301
00302 for(int i=0; i<R.dim1(); i++)
00303 {
00304 if(whichE != -1 && i != whichE)
00305 continue;
00306
00307 for(int j=0; j<R.dim2(); j++)
00308 {
00309
00310 double drift = sigma*ran.gasdev();
00311
00312
00313 dR2 += drift * drift;
00314
00315
00316 R(i,j) += drift;
00317 }
00318 }
00319
00320 return QMCDouble(1.0);
00321 }
00322
00323 QMCDouble QMCWalker::moveElectronsImportanceSampling()
00324 {
00325 Array2D<double> Displacement(R.dim1(),R.dim2());
00326 double tau = Input->flags.dt;
00327 double sigma = sqrt(tau);
00328 double greens = 0.0;
00329 bool toMove;
00330
00331
00332
00333 Displacement = walkerData.modifiedGradPsiRatio;
00334 Displacement *= tau;
00335 dR2 = 0.0;
00336 for(int i=0; i<R.dim1(); i++)
00337 {
00338 toMove = true;
00339 if(walkerData.whichE != -1 && i != walkerData.whichE)
00340 toMove = false;
00341
00342 if(toMove)
00343 {
00344 for(int j=0; j<R.dim2(); j++)
00345 {
00346
00347 double drift = sigma*ran.gasdev();
00348
00349
00350 Displacement(i,j) += drift;
00351
00352
00353 dR2 += Displacement(i,j) * Displacement(i,j);
00354
00355
00356 R(i,j) += Displacement(i,j);
00357
00358
00359
00360 greens += drift*drift;
00361 }
00362 }
00363 else
00364 {
00365 for(int j=0; j<R.dim2(); j++)
00366
00367 greens += Displacement(i,j) * Displacement(i,j);
00368 }
00369 }
00370
00371
00372 double k = 1.0;
00373 double a = 2.0*pi*tau;
00374 double b = -0.5*R.dim1()*R.dim2();
00375 double c = -greens/(2.0*tau);
00376
00377 return QMCDouble(k,a,b,c);
00378 }
00379
00380 QMCDouble QMCWalker::moveElectronsUmrigar93ImportanceSampling()
00381 {
00382 int whichE = walkerData.whichE;
00383 double tau = Input->flags.dt;
00384 bool toMove;
00385
00386 dR2 = 0.0;
00387 Array2D<double> & Displacement = walkerData.modifiedGradPsiRatio;
00388
00389 Array1D<double> zUnitVector(3);
00390 Array1D<double> radialUnitVector(3);
00391 Array1D<double> newPosition(3);
00392
00393 QMCDouble GF(1.0);
00394 QMCDouble GaussianGF;
00395 QMCDouble SlaterGF;
00396 QMCDouble OneE;
00397
00398 for(int electron=0; electron<Input->WF.getNumberElectrons(); electron++)
00399 {
00400 toMove = true;
00401 if(whichE != -1 && electron != whichE)
00402 toMove = false;
00403
00404
00405 int nearestNucleus = Input->Molecule.findClosestNucleusIndex(walkerData.riA,electron);
00406 double distanceFromNucleus = walkerData.riA(electron,nearestNucleus);
00407
00408 for(int i=0; i<3; i++)
00409 zUnitVector(i) = walkerData.riA_uvec(electron,nearestNucleus,i);
00410
00411
00412
00413
00414 double zComponentQF = 0.0;
00415
00416 for(int i=0; i<3; i++)
00417 zComponentQF += zUnitVector(i)*Displacement(electron,i);
00418
00419 double radialComponentQF = 0.0;
00420
00421 for(int i=0; i<3; i++)
00422 {
00423 radialUnitVector(i) = Displacement(electron,i) -
00424 zComponentQF * zUnitVector(i);
00425
00426 radialComponentQF += radialUnitVector(i)*radialUnitVector(i);
00427 }
00428
00429 radialComponentQF = sqrt(radialComponentQF);
00430
00431 if (radialComponentQF > 1e-15)
00432 radialUnitVector /= radialComponentQF;
00433
00434
00435 double zCoordinate = max(distanceFromNucleus + zComponentQF * tau,0.0);
00436
00437 double radialCoordinate = 2.0 * radialComponentQF * tau *
00438 zCoordinate / ( distanceFromNucleus + zCoordinate );
00439
00440
00441
00442 double expParam = Input->Molecule.Z(nearestNucleus);
00443 expParam = expParam*expParam + 1.0/tau;
00444 expParam = sqrt(expParam);
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 if (probabilitySlaterTypeMove > 1.0)
00459 {
00460 cerr << "Warning: probabilitySlaterTypeMove = ";
00461 cerr << probabilitySlaterTypeMove << endl;
00462 probabilitySlaterTypeMove = 1.0;
00463 }
00464 if (probabilitySlaterTypeMove < 0.0)
00465 {
00466 cerr << "Warning: probabilitySlaterTypeMove = ";
00467 cerr << probabilitySlaterTypeMove << endl;
00468 probabilitySlaterTypeMove = 0.0;
00469 }
00470
00471 double probabilityGaussianTypeMove = 1.0 - probabilitySlaterTypeMove;
00472
00473 if(toMove)
00474 {
00475
00476 if( probabilityGaussianTypeMove > ran.unidev() )
00477 {
00478
00479
00480
00481
00482
00483
00484 for(int i=0; i<3; i++)
00485 newPosition(i) = Input->Molecule.Atom_Positions(nearestNucleus,i)
00486 + radialCoordinate * radialUnitVector(i)
00487 + zCoordinate * zUnitVector(i)
00488 + sqrt(tau)*ran.gasdev();
00489 }
00490 else
00491 {
00492
00493
00494 for(int i=0; i<3; i++)
00495 newPosition(i) = Input->Molecule.Atom_Positions(nearestNucleus,i);
00496
00497
00498
00499 double r = ran.randomDistribution1()/(2.0*expParam);
00500 double phi = 2*pi*ran.unidev();
00501 double theta = ran.sindev();
00502
00503 newPosition(0) += r*sin(theta)*cos(phi);
00504 newPosition(1) += r*sin(theta)*sin(phi);
00505 newPosition(2) += r*cos(theta);
00506 }
00507 } else {
00508
00509
00510 for(int i=0; i<3; i++)
00511 newPosition(i) = R(electron,i);
00512 }
00513
00514 double temp;
00515
00516 for(int i=0; i<3; i++)
00517 {
00518 temp = newPosition(i) - R(electron,i);
00519 dR2 += temp*temp;
00520 R(electron,i) = newPosition(i);
00521 }
00522
00523
00524 double distance1Sq = 0.0;
00525
00526 for(int i=0; i<3; i++)
00527 {
00528 temp = newPosition(i) -
00529 ( Input->Molecule.Atom_Positions(nearestNucleus,i) +
00530 radialCoordinate * radialUnitVector(i) + zCoordinate * zUnitVector(i) );
00531
00532 distance1Sq += temp*temp;
00533 }
00534
00535 double ga = 2*pi*tau;
00536 double gb = -1.5;
00537 double gc = -distance1Sq/(2*tau);
00538
00539 GaussianGF=QMCDouble(probabilityGaussianTypeMove,ga,gb,gc);
00540
00541
00542
00543
00544
00545
00546
00547
00548 double distance2Sq = 0.0;
00549
00550 for(int i=0; i<3; i++)
00551 {
00552 temp = newPosition(i) -
00553 Input->Molecule.Atom_Positions(nearestNucleus,i);
00554
00555 distance2Sq += temp*temp;
00556 }
00557
00558 double sk = probabilitySlaterTypeMove/pi;
00559 double sa = expParam;
00560 double sb = 3.0;
00561 double sc = -2.0*expParam*sqrt(distance2Sq);
00562
00563 SlaterGF = QMCDouble(sk,sa,sb,sc);
00564
00565
00566
00567 OneE = SlaterGF + GaussianGF;
00568
00569 GF *= OneE;
00570 }
00571 return GF;
00572 }
00573
00574 QMCDouble QMCWalker::moveElectronsUmrigar93AcceleratedSampling()
00575 {
00576 int whichE = walkerData.whichE;
00577 double cos_tm = cos(globalInput.flags.accel_tm);
00578 double delta = globalInput.flags.accel_delta;
00579 bool toMove;
00580
00581 dR2 = 0.0;
00582 Array2D<double> & Fk = walkerData.modifiedGradPsiRatio;
00583
00584
00585 Array1D<double> riA_hat(3);
00586 Array1D<double> Fx(3);
00587 Array1D<double> newPosition(3);
00588
00589 QMCDouble GF(1.0);
00590 for(int electron=0; electron<Input->WF.getNumberElectrons(); electron++)
00591 {
00592 toMove = true;
00593 if(whichE != -1 && electron != whichE)
00594 toMove = false;
00595 if(!toMove) continue;
00596
00597
00598 int nearestNucleus = Input->Molecule.findClosestNucleusIndex(walkerData.riA,electron);
00599 double Z = Input->Molecule.Z(nearestNucleus);
00600 double riA = walkerData.riA(electron,nearestNucleus);
00601
00602 for(int xyz=0; xyz<3; xyz++)
00603 riA_hat(xyz) = walkerData.riA_uvec(electron,nearestNucleus,xyz);
00604
00605
00606
00607
00608
00609
00610 double Frk = 0.0;
00611 for(int xyz=0; xyz<3; xyz++)
00612 Frk += riA_hat(xyz)*Fk(electron,xyz);
00613
00614
00615 double zeta, a, I;
00616 MathFunctions::fitU(Z,Frk,riA,delta,zeta,a,I);
00617
00618
00619 double rkf;
00620 if(toMove) rkf = ran.randomDistribution2(a,zeta,riA/delta,riA*delta);
00621 else rkf = riA;
00622 double rav = (riA + rkf)/2.0;
00623
00624
00625
00626
00627 double tM, cos_tM;
00628 cos_tM = cos_tm - (1.0 + cos_tm)/(1.0 + Z*Z*rav*rav);
00629 tM = acos(cos_tM);
00630
00631 double tkf;
00632 if(toMove){
00633 tkf = ran.sindev(tM);
00634 } else {
00635 tkf = 0.0;
00636 }
00637 double s_tkf = sin(tkf);
00638 double c_tkf = cos(tkf);
00639
00640
00641
00642
00643
00644 double Fxk = 0.0;
00645 for(int xyz=0; xyz<3; xyz++)
00646 {
00647 Fx(xyz) = Fk(electron,xyz) - Frk*riA_hat(xyz);
00648 Fxk += Fx(xyz)*Fx(xyz);
00649 }
00650 Fxk = sqrt(Fxk);
00651
00652 double Fpk = Fxk*rav*s_tkf;
00653 double pkf;
00654 if(toMove) pkf = ran.randomDistribution3(Fpk);
00655 else pkf = 0.0;
00656
00657
00658 for(int xyz=0; xyz<3; xyz++)
00659 newPosition(xyz) = c_tkf*riA_hat(xyz) + s_tkf*Fx(xyz)/Fxk;
00660
00661
00662 newPosition.rotate(riA_hat,pkf);
00663 newPosition *= rkf;
00664
00665 double temp;
00666 for(int xyz=0; xyz<3; xyz++)
00667 {
00668
00669 temp = newPosition(xyz) - R(electron,xyz);
00670 R(electron,xyz) = newPosition(xyz);
00671 dR2 += temp*temp;
00672 }
00673
00674
00675
00676
00677
00678
00679
00680 double S = 1.0;
00681 S *= (1.0 + a*rkf)*exp(-zeta*rkf);
00682 S *= 1.0 + min(Fpk,1.0)*cos(pkf);
00683 S *= pow(rkf,-1.5);
00684 S = fabs(S);
00685
00686 I *= (1.0 - cos_tM);
00687 I *= 2*pi;
00688
00689
00690 if(fabs(I) > 1e-50)
00691 GF *= QMCDouble(S/I);
00692
00693 if(GF.isNotValid()){
00694 printf("move electron=%i age=%i\n",electron,age);
00695 printf("rki=%20.10f a=%20.10f zeta=%20.10f i=%20.10f o=%20.10f tM=%20.10e\n",riA,a,zeta,riA/delta,riA*delta,tM);
00696 printf("Frk=%20.10f Fxk=%20.10f Fpk=%20.10f\n",Frk,Fxk,Fpk);
00697 printf("rkf=%20.10f tkf=%20.10f pkf=%20.10f\n",rkf,tkf,pkf);
00698 printf("S=%20.10e I=%20.10e T=%20.10e\n",S,I,(double)(GF));
00699 }
00700 }
00701 return GF;
00702 }
00703
00704 QMCDouble QMCWalker::calculateReverseGreensFunction()
00705 {
00706
00707 if( Input->flags.dt <= 0 )
00708 {
00709 cerr << "ERROR: Negative dt value! (" << Input->flags.dt << ")" << endl;
00710 exit(0);
00711 }
00712
00713 if(Input->flags.sampling_method == "no_importance_sampling")
00714 return calculateReverseGreensFunctionNoImportanceSampling();
00715 else if(Input->flags.sampling_method == "importance_sampling" )
00716 return calculateReverseGreensFunctionImportanceSampling();
00717 else if(Input->flags.sampling_method == "umrigar93_importance_sampling")
00718 return calculateReverseGreensFunctionUmrigar93ImportanceSampling();
00719 else if(Input->flags.sampling_method == "umrigar93_accelerated_sampling")
00720 return calculateReverseGreensFunctionUmrigar93AcceleratedSampling();
00721 else
00722 {
00723 cerr << "ERROR: Improper value for sampling_method set ("
00724 << Input->flags.sampling_method << ")!" << endl;
00725 exit(0);
00726 }
00727
00728
00729
00730 QMCDouble TRASH = QMCDouble();
00731 return TRASH;
00732 }
00733
00734 QMCDouble \
00735 QMCWalker::calculateReverseGreensFunctionNoImportanceSampling()
00736 {
00737 return QMCDouble(1.0);
00738 }
00739
00740 QMCDouble \
00741 QMCWalker::calculateReverseGreensFunctionImportanceSampling()
00742 {
00743 double tau = Input->flags.dt;
00744 double greens = 0.0;
00745
00746 for(int i=0; i<R.dim1(); i++)
00747 {
00748 for(int j=0; j<R.dim2(); j++)
00749 {
00750 double temp = OriginalWalker->R(i,j) - TrialWalker->R(i,j) -
00751 tau*TrialWalker->walkerData.modifiedGradPsiRatio(i,j);
00752
00753 greens += temp*temp;
00754 }
00755 }
00756
00757
00758 double k = 1.0;
00759 double a = 2.0*pi*tau;
00760 double b = -0.5*R.dim1()*R.dim2();
00761 double c = -greens/(2.0*tau);
00762
00763 return QMCDouble(k,a,b,c);
00764 }
00765
00766 QMCDouble \
00767 QMCWalker::calculateReverseGreensFunctionUmrigar93ImportanceSampling()
00768 {
00769 int whichE = walkerData.whichE;
00770 bool moved;
00771
00772 double tau = Input->flags.dt;
00773 Array1D<double> zUnitVector(3);
00774 Array1D<double> radialUnitVector(3);
00775
00776 QMCDouble GF(1.0);
00777 QMCDouble GaussianGF;
00778 QMCDouble SlaterGF;
00779 QMCDouble OneE;
00780
00781 for(int electron=0; electron<Input->WF.getNumberElectrons(); electron++)
00782 {
00783 moved = true;
00784 if(whichE != -1 && electron != whichE)
00785 moved = false;
00786
00787
00788 int nearestNucleus = Input->Molecule.findClosestNucleusIndex(TrialWalker->walkerData.riA,electron);
00789 double distanceFromNucleus = walkerData.riA(electron,nearestNucleus);
00790
00791 for(int i=0; i<3; i++)
00792 zUnitVector(i) = walkerData.riA_uvec(electron,nearestNucleus,i);
00793
00794
00795
00796
00797 double zComponentQF = 0.0;
00798
00799 for(int i=0; i<3; i++)
00800 zComponentQF += zUnitVector(i)*
00801 TrialWalker->walkerData.modifiedGradPsiRatio(electron,i);
00802
00803 double radialComponentQF = 0.0;
00804
00805 for(int i=0; i<3; i++)
00806 {
00807 radialUnitVector(i) =
00808 TrialWalker->walkerData.modifiedGradPsiRatio(electron,i) -
00809 zComponentQF * zUnitVector(i);
00810
00811 radialComponentQF += radialUnitVector(i)*radialUnitVector(i);
00812 }
00813
00814 radialComponentQF = sqrt(radialComponentQF);
00815
00816 if (radialComponentQF > 1e-15)
00817 radialUnitVector /= radialComponentQF;
00818
00819
00820 double zCoordinate = max(distanceFromNucleus + zComponentQF * tau,0.0);
00821
00822 double radialCoordinate = 2.0 * radialComponentQF * tau *
00823 zCoordinate / ( distanceFromNucleus + zCoordinate );
00824
00825
00826
00827 double expParam = Input->Molecule.Z(nearestNucleus);
00828 expParam = expParam*expParam + 1.0/tau;
00829 expParam = sqrt(expParam);
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 if (probabilitySlaterTypeMove > 1.0)
00844 {
00845 cerr << "Warning: probabilitySlaterTypeMove = ";
00846 cerr << probabilitySlaterTypeMove << endl;
00847 probabilitySlaterTypeMove = 1.0;
00848 }
00849 if (probabilitySlaterTypeMove < 0.0)
00850 {
00851 cerr << "Warning: probabilitySlaterTypeMove = ";
00852 cerr << probabilitySlaterTypeMove << endl;
00853 probabilitySlaterTypeMove = 0.0;
00854 }
00855
00856 double probabilityGaussianTypeMove = 1.0 - probabilitySlaterTypeMove;
00857
00858
00859
00860 double distance1Sq = 0.0;
00861 double temp;
00862
00863 for(int i=0; i<3; i++)
00864 {
00865 temp = OriginalWalker->R(electron,i) -
00866 ( Input->Molecule.Atom_Positions(nearestNucleus,i) +
00867 radialCoordinate * radialUnitVector(i) + zCoordinate * zUnitVector(i) );
00868
00869 distance1Sq += temp*temp;
00870 }
00871
00872 double ga = 2*pi*tau;
00873 double gb = -1.5;
00874 double gc = -distance1Sq/(2*tau);
00875
00876 GaussianGF=QMCDouble(probabilityGaussianTypeMove,ga,gb,gc);
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 double distance2Sq = 0.0;
00887
00888 for(int i=0; i<3; i++)
00889 {
00890 temp = OriginalWalker->R(electron,i) - \
00891 Input->Molecule.Atom_Positions(nearestNucleus,i);
00892
00893 distance2Sq += temp*temp;
00894 }
00895
00896 double sk = probabilitySlaterTypeMove/pi;
00897 double sa = expParam;
00898 double sb = 3.0;
00899 double sc = -2.0*expParam*sqrt(distance2Sq);
00900
00901 SlaterGF = QMCDouble(sk,sa,sb,sc);
00902
00903
00904
00905 OneE = SlaterGF + GaussianGF;
00906
00907 GF *= OneE;
00908 }
00909 return GF;
00910 }
00911
00912 QMCDouble QMCWalker::calculateReverseGreensFunctionUmrigar93AcceleratedSampling()
00913 {
00914 int whichE = walkerData.whichE;
00915 bool moved;
00916
00917 double cos_tm = cos(globalInput.flags.accel_tm);
00918 double delta = globalInput.flags.accel_delta;
00919
00920 Array1D<double> riA_hat(3);
00921 Array1D<double> rfA_hat(3);
00922
00923 Array1D<double> Fx(3);
00924 Array2D<double> & Fk = TrialWalker->walkerData.modifiedGradPsiRatio;
00925
00926
00927 QMCDouble GF(1.0);
00928 for(int electron=0; electron<Input->WF.getNumberElectrons(); electron++)
00929 {
00930 moved = true;
00931 if(whichE != -1 && electron != whichE)
00932 moved = false;
00933 if(!moved) continue;
00934
00935
00936 int nearestNucleus = Input->Molecule.findClosestNucleusIndex(TrialWalker->walkerData.riA,electron);
00937 double Z = Input->Molecule.Z(nearestNucleus);
00938 double rkf = OriginalWalker->walkerData.riA(electron,nearestNucleus);
00939 double riA = TrialWalker->walkerData.riA(electron,nearestNucleus);
00940 double rav = (riA + rkf)/2.0;
00941 for(int xyz=0; xyz<3; xyz++)
00942 {
00943 riA_hat(xyz) = TrialWalker->walkerData.riA_uvec(electron,nearestNucleus,xyz);
00944 rfA_hat(xyz) = OriginalWalker->walkerData.riA_uvec(electron,nearestNucleus,xyz);
00945 }
00946
00947
00948
00949
00950
00951 double Frk = 0.0;
00952 for(int xyz=0; xyz<3; xyz++)
00953 Frk += riA_hat(xyz)*Fk(electron,xyz);
00954
00955
00956 double zeta, a, I;
00957 MathFunctions::fitU(Z,Frk,riA,delta,zeta,a,I);
00958
00959 if(rkf > riA*delta || rkf < riA/delta){
00960 printf("Warning: rkf is outside range! rkf=%20.10f l=%20.10f u=%20.10f\n",
00961 rkf,riA/delta,riA*delta);
00962 GF *= QMCDouble(0.0);
00963 return GF;
00964 }
00965
00966
00967
00968
00969 double tM, cos_tM;
00970 cos_tM = cos_tm - (1.0 + cos_tm)/(1.0 + Z*Z*rav*rav);
00971 tM = acos(cos_tM);
00972
00973
00974 double ri_dot_rf = riA_hat * rfA_hat;
00975 double tkf;
00976 if(fabs(ri_dot_rf-1.0) < 1e-10) tkf = 0.0;
00977 else tkf = acos(riA_hat * rfA_hat);
00978
00979 if(tkf > tM){
00980 printf("Warning: tkf is outside range! tkf = %20.10f tM=%20.10f\n",tkf,tM);
00981 GF *= QMCDouble(0.0);
00982 return GF;
00983 }
00984
00985 double s_tkf = sin(tkf);
00986
00987
00988
00989
00990 double Fxk = 0.0;
00991 for(int i=0; i<3; i++)
00992 {
00993 Fx(i) = Fk(electron,i) - Frk*riA_hat(i);
00994 Fxk += Fx(i)*Fx(i);
00995 }
00996 Fxk = sqrt(Fxk);
00997 double Fpk = Fxk*rav*s_tkf;
00998 double pkf;
00999 double rf_dot_Fx = rfA_hat * Fx;
01000 if(fabs(rf_dot_Fx) < 1e-10) pkf = 0.5*pi;
01001 else pkf = acos((rfA_hat * Fx)/(s_tkf*Fxk));
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 double S = 1.0;
01020 S *= (1.0 + a*rkf)*exp(-zeta*rkf);
01021 S *= 1.0 + min(Fpk,1.0)*cos(pkf);
01022 S *= pow(rkf,-1.5);
01023 S = fabs(S);
01024
01025 I *= (1.0 - cos_tM);
01026 I *= 2*pi;
01027
01028 if( fabs(I) < 1e-50)
01029 GF *= 0.0;
01030 else
01031 GF *= QMCDouble(S/I);
01032
01033 if(GF.isNotValid()){
01034 printf("moved electron=%i age=%i\n",electron,age);
01035 printf("a=%20.10f zeta=%20.10f i=%20.10f o=%20.10f cos_tM=%20.10f\n",a,zeta,riA/delta,riA*delta,cos_tM);
01036 printf("Frk=%20.10f Fxk=%20.10f Fpk=%20.10f\n",Frk,Fxk,Fpk);
01037 printf("rkf=%20.10f tkf=%20.10f pkf=%20.10f\n",rkf,tkf,pkf);
01038 printf("S=%20.10e I=%20.10e T=%20.10e\n",S,I,(double)(GF));
01039 }
01040 }
01041 return GF;
01042 }
01043
01044 void QMCWalker::reweight_walker()
01045 {
01046 dW = 0.0;
01047 double S_trial = 0.0;
01048 double S_original = 0.0;
01049 double trialEnergy = TrialWalker->walkerData.localEnergy;
01050 double originalEnergy = OriginalWalker->walkerData.localEnergy;
01051
01052
01053
01054 bool weightIsNaN = false;
01055
01056 if( Input->flags.run_type == "variational")
01057
01058 dW = 1.0;
01059
01060 else
01061 {
01062 if( IeeeMath::isNaN(trialEnergy) )
01063 {
01064 cerr << "WARNING: trial energy = ";
01065 cerr << TrialWalker->walkerData.localEnergy << "!" << endl;
01066 weightIsNaN = true;
01067 }
01068 else if( Input->flags.energy_modification_type == "none" )
01069 {
01070 S_trial = Input->flags.energy_trial - trialEnergy;
01071 S_original = Input->flags.energy_trial - originalEnergy;
01072 }
01073 else
01074 {
01075 Array2D<double> * tMGPR =
01076 & TrialWalker->walkerData.modifiedGradPsiRatio;
01077 Array2D<double> * tGPR = & TrialWalker->walkerData.gradPsiRatio;
01078 Array2D<double> * oMGPR =
01079 & OriginalWalker->walkerData.modifiedGradPsiRatio;
01080 Array2D<double> * oGPR = & OriginalWalker->walkerData.gradPsiRatio;
01081
01082 double lengthGradTrialModified =
01083 sqrt((*tMGPR).dotAllElectrons(*tMGPR));
01084 double lengthGradTrialUnmodified =
01085 sqrt((*tGPR).dotAllElectrons(*tGPR));
01086 double lengthGradOriginalModified =
01087 sqrt((*oMGPR).dotAllElectrons(*oMGPR));
01088 double lengthGradOriginalUnmodified =
01089 sqrt((*oGPR).dotAllElectrons(*oGPR));
01090
01091 if(Input->flags.energy_modification_type=="modified_umrigar93")
01092 {
01093 S_trial = (Input->flags.energy_trial - trialEnergy)*
01094 (lengthGradTrialModified/lengthGradTrialUnmodified);
01095
01096 S_original = (Input->flags.energy_trial - originalEnergy) *
01097 (lengthGradOriginalModified/lengthGradOriginalUnmodified);
01098 }
01099 else if( Input->flags.energy_modification_type == "umrigar93" )
01100 {
01101 S_trial =
01102 (Input->flags.energy_trial - Input->flags.energy_estimated)
01103 +(Input->flags.energy_estimated - trialEnergy)*
01104 (lengthGradTrialModified/lengthGradTrialUnmodified);
01105
01106 S_original =
01107 (Input->flags.energy_trial - Input->flags.energy_estimated)
01108 +(Input->flags.energy_estimated - originalEnergy) *
01109 (lengthGradOriginalModified/lengthGradOriginalUnmodified);
01110 }
01111 else
01112 {
01113 cerr << "ERROR: unknown energy modification method!" << endl;
01114 exit(0);
01115 }
01116 }
01117
01118 if (IeeeMath::isNaN(S_trial) || IeeeMath::isNaN(S_original))
01119 {
01120 cerr << "Error: S_trial = " << S_trial << endl;
01121 cerr << " S_original = " << S_original << endl;
01122 cerr << " energy_trial = " << Input->flags.energy_trial << endl;
01123 cerr << " energy_estimated = " << Input->flags.energy_estimated << endl;
01124 cerr << " trialEnergy = " << TrialWalker->walkerData.localEnergy << endl;
01125 cerr << " originalEnergy = " << OriginalWalker->walkerData.localEnergy << endl;
01126 }
01127
01128 if( Input->flags.walker_reweighting_method == "simple_symmetric" )
01129 {
01130
01131
01132
01133
01134 double temp = 0.5*(S_trial+S_original)*Input->flags.dt_effective;
01135
01136 if (IeeeMath::isNaN(temp) || weightIsNaN == true)
01137 {
01138 cerr << "WARNING: dW = exp(" << temp << ")" << endl;
01139 cerr << "Walker's weight is being set to zero so that it does"
01140 << " not ruin the whole calculation." << endl;
01141 dW = 0.0;
01142 }
01143 else
01144 dW = exp(temp);
01145 }
01146 else if( Input->flags.walker_reweighting_method == "simple_asymmetric" )
01147 {
01148
01149
01150
01151
01152 double temp;
01153 if( move_accepted )
01154 temp = 0.5*(S_trial+S_original)*Input->flags.dt_effective;
01155 else
01156 temp = S_original*Input->flags.dt_effective;
01157
01158 if (IeeeMath::isNaN(temp) || weightIsNaN == true)
01159 {
01160 cerr << "WARNING: dW = exp(" << temp << ")" << endl;
01161 cerr << "Walker's weight is being set to zero so that it does"
01162 << " not ruin the whole calculation." << endl;
01163 dW = 0.0;
01164 }
01165 else
01166 dW = exp(temp);
01167 }
01168 else if( Input->flags.walker_reweighting_method ==
01169 "umrigar93_probability_weighted" )
01170 {
01171
01172
01173
01174
01175 double p = TrialWalker->getAcceptanceProbability();
01176 double q = 1.0 - p;
01177
01178 double temp = (p*0.5*(S_original+S_trial) + q*S_original) *
01179 Input->flags.dt_effective;
01180
01181 if (IeeeMath::isNaN(temp) || weightIsNaN == true)
01182 {
01183 cerr << "WARNING: dW = exp(" << temp << ")" << endl;
01184 cerr << "Walker's weight is being set to zero so that it does"
01185 << " not ruin the whole calculation." << endl;
01186 cerr << " p = " << p << "; q = " << q << endl;
01187 dW = 0.0;
01188 }
01189 else
01190 dW = exp(temp);
01191 }
01192 else
01193 {
01194 cerr << "ERROR: unknown reweighting method!" << endl;
01195 exit(0);
01196 }
01197 }
01198
01199
01200 setWeight( getWeight() * dW );
01201
01202 if(getWeight() <= 0.0 || Input->flags.run_type == "variational")
01203 return;
01204
01205
01206
01207
01208
01209
01210 double rel_diff;
01211 if(move_accepted)
01212 {
01213 rel_diff = fabs( (TrialWalker->walkerData.localEnergy -
01214 Input->flags.energy_estimated_original)/
01215 Input->flags.energy_estimated_original);
01216 }
01217 else
01218 {
01219 rel_diff = fabs( (OriginalWalker->walkerData.localEnergy -
01220 Input->flags.energy_estimated_original)/
01221 Input->flags.energy_estimated_original);
01222 }
01223
01224 if(iteration < -100)
01225 {
01226
01227
01228
01229
01230
01231
01232
01233
01234 int steps = iteration + Input->flags.equilibration_steps;
01235
01236 int min_steps = 5;
01237
01238 if(getWeight() > 1.5*Input->flags.branching_threshold)
01239 {
01240 if(steps > min_steps)
01241 {
01242 cerr << "WARNING: Deleting heavy walker " << ID(move_accepted);
01243 cerr.flush();
01244 }
01245 setWeight(0.0);
01246 return;
01247 }
01248
01249 if(getWeight() < 0.1)
01250 {
01251 if(steps > min_steps)
01252 {
01253 cerr << "WARNING: Deleting light walker " << ID(move_accepted);
01254 cerr.flush();
01255 }
01256 setWeight(0.0);
01257 return;
01258 }
01259
01260 if(dW > 1.5 || dW < 0.5)
01261 {
01262 if(steps > min_steps)
01263 {
01264
01265 if(dW > 2.0 || dW < 0.25)
01266 {
01267 double p = TrialWalker->getAcceptanceProbability();
01268 double q = 1.0 - p;
01269
01270 cerr << "WARNING: Deleting walker with bad dW " << ID(move_accepted);
01271 cerr << " p = " << p << "; q = " << q;
01272 cerr << " energy_trial = " << Input->flags.energy_trial << endl;
01273 cerr << " energy_estimated = " << Input->flags.energy_estimated << endl;
01274 cerr << " S_trial = " << S_trial << endl;
01275 cerr << " S_original = " << S_original << endl;
01276 cerr << "TrialWalker:" << endl << TrialWalker->walkerData;
01277 cerr << "OriginalWalker:" << endl << OriginalWalker->walkerData;
01278 cerr << endl;
01279 }
01280 else
01281 {
01282
01283 }
01284 cerr.flush();
01285 }
01286 setWeight(0.0);
01287 return;
01288 }
01289
01290 double rel_cutoff = Input->flags.rel_cutoff;
01291 if(rel_diff > rel_cutoff && steps > min_steps)
01292 {
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 if(rel_diff > rel_cutoff && steps > 2*min_steps){
01305 cerr << "WARNING: Deleting walker with bad energy " << ID(move_accepted);
01306 cerr.flush();
01307 }
01308 setWeight(0.0);
01309 return;
01310 }
01311
01312 int age_cutoff = 30;
01313 if(age >= age_cutoff)
01314 {
01315
01316 if(steps > age_cutoff && false)
01317 {
01318 cerr << "WARNING: Deleting aged walker " << ID(move_accepted);
01319 cerr.flush();
01320 }
01321 setWeight(0.0);
01322 return;
01323 }
01324 }
01325 else
01326 {
01327
01328
01329
01330
01331
01332
01333
01334 if(getWeight() > 50.0)
01335 {
01336 cerr << "ERROR: Deleting heavy walker " << ID(move_accepted);
01337 cerr.flush();
01338 setWeight(0.0);
01339 return;
01340 }
01341
01342 if(rel_diff > globalInput.flags.rel_cutoff)
01343 {
01344 cerr << "ERROR: Deleting walker with bad energy " << ID(move_accepted);
01345 cerr.flush();
01346 setWeight(0.0);
01347 return;
01348 }
01349
01350 if(dW > 4.0)
01351 {
01352 stringstream strm;
01353 double p = TrialWalker->getAcceptanceProbability();
01354 double q = 1.0 - p;
01355
01356 strm << "ERROR: Deleting fast growth walker " << ID(move_accepted);
01357 strm << " p = " << p << "; q = " << q;
01358 strm << " energy_trial = " << Input->flags.energy_trial << endl;
01359 strm << " energy_estimated = " << Input->flags.energy_estimated << endl;
01360 strm << " S_trial = " << S_trial << endl;
01361 strm << " S_original = " << S_original << endl;
01362 strm << "TrialWalker:" << endl << TrialWalker->walkerData;
01363 strm << "OriginalWalker:" << endl << OriginalWalker->walkerData;
01364 strm << endl;
01365 cerr << strm.str();
01366 cerr.flush();
01367 setWeight(0.0);
01368 return;
01369 }
01370 }
01371 }
01372
01373 bool QMCWalker::branchRecommended()
01374 {
01375 if(globalInput.flags.limit_branching == 0)
01376 return true;
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402 bool shouldRecommend = true;
01403 bool shouldWarn = false;
01404
01405
01406 if(age > 4)
01407 {
01408 shouldRecommend = false;
01409 if(age >= Input->flags.old_walker_acceptance_parameter && age%10 == 0)
01410 shouldWarn = true;
01411 }
01412 if(dW > 1.5)
01413 {
01414 shouldRecommend = false;
01415 if(iteration%10 == 0 && getWeight() > 2.0*Input->flags.branching_threshold)
01416 shouldWarn = true;
01417 if(dW > 2.0)
01418 shouldWarn = true;
01419 }
01420 if(getWeight() > 2.0*Input->flags.branching_threshold)
01421 {
01422 shouldRecommend = false;
01423 if(iteration%50 == 0 &&
01424 getWeight() > 2.0*Input->flags.branching_threshold &&
01425 dW > 1.0)
01426 shouldWarn = true;
01427 }
01428
01429 double virial = -TrialWalker->walkerData.potentialEnergy/TrialWalker->walkerData.kineticEnergy;
01430
01431
01432
01433 if(fabs(virial) < 0.1)
01434 {
01435 shouldRecommend = false;
01436
01437 if(age == 0)
01438 shouldWarn = true;
01439 }
01440
01441 double rel_diff = fabs( (TrialWalker->walkerData.localEnergy -
01442 Input->flags.energy_estimated_original)/
01443 Input->flags.energy_estimated_original);
01444
01445
01446 if(rel_diff > 1.0)
01447 {
01448 shouldRecommend = false;
01449 if(age == 0)
01450 shouldWarn = true;
01451 }
01452
01453 if(shouldWarn && !shouldRecommend && iteration > 0)
01454 {
01455 cerr << "WARNING: Not recommending a branch for walker " << ID(move_accepted);
01456 cerr.flush();
01457 }
01458
01459 return shouldRecommend;
01460 }
01461
01462 string QMCWalker::ID(bool showTrial)
01463 {
01464
01465
01466
01467
01468
01469
01470 QMCWalkerData * wd;
01471 if(showTrial)
01472 wd = & TrialWalker->walkerData;
01473 else
01474 wd = & OriginalWalker->walkerData;
01475
01476 int w = 25;
01477 int p = 15;
01478
01479 double virial = 0;
01480 if(fabs(wd->kineticEnergy) > 1e-30)
01481 virial = -wd->potentialEnergy/wd->kineticEnergy;
01482
01483
01484
01485
01486
01487
01488 stringstream id;
01489
01490 id << "(" << genealogy[0];
01491 for(int i=1; i<numAncestors; i++)
01492 {
01493 if(genealogy[i] == -1)
01494 break;
01495 id << "<" << genealogy[i];
01496 }
01497
01498 id << "::" << Input->flags.my_rank << ")" << endl;
01499
01500 id << *wd;
01501
01502 if(globalInput.flags.run_type != "variational")
01503 {
01504 id.width(10);
01505 id << "weight= "
01506 << setw(w) << setprecision(p)
01507 << scientific << getWeight();
01508 id.width(10);
01509 id << " dW = "
01510 << setw(w) << setprecision(p)
01511 << fixed << dW;
01512 id.width(10);
01513 id << endl;
01514 }
01515
01516 id.width(10);
01517 id << " iter = "
01518 << setw(w) << setprecision(p)
01519 << fixed << iteration;
01520 id.width(10);
01521 id << " age = "
01522 << setw(w) << setprecision(p)
01523 << scientific << age;
01524 id.width(10);
01525 id << endl;
01526
01527 return id.str();
01528 }
01529
01530 void QMCWalker::calculateMoveAcceptanceProbability(double GreensRatio)
01531 {
01532
01533 double PsiRatio = TrialWalker->walkerData.psi/OriginalWalker->walkerData.psi;
01534
01535
01536 double p = PsiRatio * PsiRatio * GreensRatio;
01537
01538
01539
01540
01541
01542
01543
01544 if( !(IeeeMath::isNaN(p)))
01545 {
01546
01547 if(age - Input->flags.old_walker_acceptance_parameter > 1000)
01548 {
01549
01550 p = 1.0;
01551 }
01552 else if(age - Input->flags.old_walker_acceptance_parameter > 500)
01553 {
01554 p = 1.0;
01555 }
01556 else if(age - Input->flags.old_walker_acceptance_parameter > 0)
01557 {
01558 p *= pow(1.1,age-Input->flags.old_walker_acceptance_parameter);
01559 }
01560
01561 } else {
01562
01563 numWarnings++;
01564 cerr << "WARNING: Rejecting trial walker with NaN p! " << ID(true);
01565 cerr << " PsiRatio = " << PsiRatio << endl;
01566 cerr << " GreensRatio = " << GreensRatio << endl;
01567 p = 0.0;
01568
01569
01570 TrialWalker->walkerData.zero();
01571 }
01572
01573
01574 if( TrialWalker->isSingular() )
01575 {
01576 numWarnings++;
01577 cerr << "WARNING: Rejecting singular trial walker! " << ID(true);
01578 p = 0.0;
01579 TrialWalker->walkerData.zero();
01580 }
01581
01582 if(numWarnings >= 10){
01583
01584
01585
01586
01587 cerr << "ERROR: There have been " << numWarnings << " warnings, so I'm quitting." << endl;
01588
01589 #ifdef PARALLEL
01590 MPI_Abort(MPI_COMM_WORLD,1);
01591 #endif
01592 exit(0);
01593 }
01594
01595
01596 if( PsiRatio < 0 && Input->flags.run_type == "diffusion" )
01597 {
01598
01599 p = 0.0;
01600 }
01601
01602
01603 if( p > 1.0)
01604 {
01605 p = 1.0;
01606 }
01607
01608
01609
01610 TrialWalker->setAcceptanceProbability(p);
01611 }
01612
01613 void QMCWalker::acceptOrRejectMove()
01614 {
01615 if( TrialWalker->getAcceptanceProbability() > ran.unidev() )
01616 {
01617
01618 ageMoved = age;
01619 age = 0;
01620 move_accepted = true;
01621 }
01622 else
01623 {
01624
01625
01626 age++;
01627 move_accepted = false;
01628 }
01629
01630
01631 if( iteration > 0)
01632 {
01633 if(ageMoved > Input->flags.old_walker_acceptance_parameter + 15)
01634 {
01635
01636 cerr << "WARNING: Old walker moved after " << ageMoved << " iterations." << endl;
01637 }
01638
01639
01640
01641
01642
01643
01644 }
01645 }
01646
01647 void QMCWalker::createChildWalkers()
01648 {
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658 if( OriginalWalker == 0 )
01659 {
01660 OriginalWalker = new QMCWalker();
01661 }
01662
01663
01664 OriginalWalker->R = R;
01665 OriginalWalker->dR2 = dR2;
01666 OriginalWalker->AcceptanceProbability = AcceptanceProbability;
01667
01668 if(globalInput.flags.one_e_per_iter == 0)
01669 {
01670 OriginalWalker->walkerData = walkerData;
01671 } else {
01672
01673 OriginalWalker->walkerData.partialCopy(walkerData);
01674 }
01675
01676
01677 TrialWalker = this;
01678 }
01679
01680 void QMCWalker::initialize(QMCInput *INPUT)
01681 {
01682 Input = INPUT;
01683
01684 int numFW = Input->flags.future_walking.size();
01685 int numElectrons = Input->WF.getNumberElectrons();
01686 int numDimensions;
01687 int numNucForceDim1 = -1;
01688 int numNucForceDim2 = -1;
01689
01690 if(Input->flags.trial_function_type == "restricted" ||
01691 Input->flags.trial_function_type == "unrestricted"){
01692 numDimensions = 3;
01693 } else {
01694
01695 numDimensions = Input->flags.Nbasisfunc;
01696 }
01697
01698 if(Input->flags.nuclear_derivatives != "none")
01699 {
01700 if(Input->flags.nuclear_derivatives != "bin_force_density")
01701 {
01702 numNucForceDim1 = Input->Molecule.getNumberAtoms();
01703 numNucForceDim2 = 3;
01704 } else {
01705 numNucForceDim1 = QMCNuclearForces::getNumBins();
01706 numNucForceDim2 = 1;
01707 }
01708
01709 fwNuclearForces.allocate(numNucForceDim1,numNucForceDim2);
01710
01711 for(int d1=0; d1<fwNuclearForces.dim1(); d1++)
01712 for(int d2=0; d2<fwNuclearForces.dim2(); d2++)
01713 fwNuclearForces(d1,d2).allocate(numFW,2);
01714 }
01715
01716 R.allocate(numElectrons,numDimensions);
01717
01718 walkerData.initialize(numDimensions,
01719 numNucForceDim1,numNucForceDim2);
01720
01721 numFWSteps.resize(numFW);
01722
01723 isCollectingFWResults.allocate(numFW,2);
01724 fwNormalization.allocate(numFW,2);
01725 fwR12.allocate(numFW,2);
01726 fwR2.allocate(numFW,2);
01727 fwiR12.allocate(numFW,2);
01728 fwiR.allocate(numFW,2);
01729 fwEnergy.allocate(numFW,2);
01730 fwKineticEnergy.allocate(numFW,2);
01731 fwKineticEnergy_grad.allocate(numFW,2);
01732 fwPotentialEnergy.allocate(numFW,2);
01733 resetFutureWalking();
01734
01735
01736 setAcceptanceProbability(0.0);
01737 }
01738
01739 void QMCWalker::calculateElectronDensities(double max_pair_distance, double dr,
01740 Array1D<double> &pll_spin, Array1D<double> &opp_spin,
01741 Array1D< Array1D<double> > &alpha_density,
01742 Array1D< Array1D<double> > &beta_density)
01743 {
01744 int nalpha = Input->WF.getNumberElectrons(true);
01745 int nbeta = Input->WF.getNumberElectrons(false);
01746
01747 double dist = 0.0;
01748 int index = 0;
01749
01750
01751
01752 if (nalpha > 1)
01753 {
01754 for (int i=0; i<nalpha-1; i++)
01755 for (int j=i+1; j<nalpha; j++)
01756 {
01757 dist = sqrt( (R(i,0) - R(j,0)) * (R(i,0) - R(j,0)) +
01758 (R(i,1) - R(j,1)) * (R(i,1) - R(j,1)) +
01759 (R(i,2) - R(j,2)) * (R(i,2) - R(j,2)) );
01760 if (dist < max_pair_distance)
01761 {
01762 index = int(dist/dr);
01763 pll_spin(index) += weight;
01764 }
01765 }
01766 }
01767
01768 if (nbeta > 1)
01769 {
01770 for (int i=nalpha; i<nalpha+nbeta-1; i++)
01771 for (int j=i+1; j<nalpha+nbeta; j++)
01772 {
01773 dist = sqrt( (R(i,0) - R(j,0)) * (R(i,0) - R(j,0)) +
01774 (R(i,1) - R(j,1)) * (R(i,1) - R(j,1)) +
01775 (R(i,2) - R(j,2)) * (R(i,2) - R(j,2)) );
01776 if (dist < max_pair_distance)
01777 {
01778 index = int(dist/dr);
01779 pll_spin(index) += weight;
01780 }
01781 }
01782 }
01783
01784
01785
01786 if (nalpha > 0 && nbeta > 0)
01787 {
01788 for (int i=0; i<nalpha; i++)
01789 for (int j=nalpha; j<nalpha+nbeta; j++)
01790 {
01791 dist = sqrt( (R(i,0) - R(j,0)) * (R(i,0) - R(j,0)) +
01792 (R(i,1) - R(j,1)) * (R(i,1) - R(j,1)) +
01793 (R(i,2) - R(j,2)) * (R(i,2) - R(j,2)) );
01794 if (dist < max_pair_distance)
01795 {
01796 index = int(dist/dr);
01797 opp_spin(index) += weight;
01798 }
01799 }
01800 }
01801
01802 for (int i=0; i<Input->flags.Natoms; i++)
01803 {
01804 string NucleusType = Input->Molecule.Atom_Labels(i);
01805
01806 int nuc_index = -1;
01807 for (int j=0; j<Input->Molecule.NucleiTypes.dim1(); j++)
01808 if (Input->Molecule.NucleiTypes(j) == NucleusType)
01809 {
01810 nuc_index = j;
01811 break;
01812 }
01813
01814 double nuc_x = Input->Molecule.Atom_Positions(i,0);
01815 double nuc_y = Input->Molecule.Atom_Positions(i,1);
01816 double nuc_z = Input->Molecule.Atom_Positions(i,2);
01817
01818 for (int k=0; k<nalpha; k++)
01819 {
01820 dist = sqrt( (R(k,0) - nuc_x) * (R(k,0) - nuc_x) +
01821 (R(k,1) - nuc_y) * (R(k,1) - nuc_y) +
01822 (R(k,2) - nuc_z) * (R(k,2) - nuc_z) );
01823 if (dist < max_pair_distance)
01824 {
01825 index = int(dist/dr);
01826 (alpha_density(nuc_index))(index) += weight;
01827 }
01828 }
01829
01830 for (int l=nalpha; l<nalpha+nbeta; l++)
01831 {
01832 dist = sqrt( (R(l,0) - nuc_x) * (R(l,0) - nuc_x) +
01833 (R(l,1) - nuc_y) * (R(l,1) - nuc_y) +
01834 (R(l,2) - nuc_z) * (R(l,2) - nuc_z) );
01835 if (dist < max_pair_distance)
01836 {
01837 index = int(dist/dr);
01838 (beta_density(nuc_index))(index) += weight;
01839 }
01840 }
01841 }
01842 }
01843
01844 void QMCWalker::calculatePllCorrelationDiagram(int coord, double min,
01845 double max, Array1D< Array1D<double> > &CorrelationDiagram)
01846 {
01847 int nalpha = Input->WF.getNumberElectrons(true);
01848 int nbeta = Input->WF.getNumberElectrons(false);
01849
01850 double dr = (max-min)/CorrelationDiagram.dim1();
01851 int index1 = -1;
01852 int index2 = -1;
01853
01854 for (int i=0; i<nalpha-1; i++)
01855 for (int j=i+1; j<nalpha; j++)
01856 if ( (R(i,coord) >= min) && (R(i,coord) <=max) )
01857 if ( (R(j,coord) >= min) && (R(j,coord) <= max) )
01858 {
01859 index1 = int((R(i,coord)-min)/dr);
01860 index2 = int((R(j,coord)-min)/dr);
01861 (CorrelationDiagram(index1))(index2) += weight;
01862 }
01863
01864 for (int i=nalpha; i<nalpha+nbeta-1; i++)
01865 for (int j=i+1; j<nalpha+nbeta; j++)
01866 if ( (R(i,coord) >= min) && (R(i,coord) <=max) )
01867 if ( (R(j,coord) >= min) && (R(j,coord) <= max) )
01868 {
01869 index1 = int((R(i,coord)-min)/dr);
01870 index2 = int((R(j,coord)-min)/dr);
01871 (CorrelationDiagram(index1))(index2) += weight;
01872 }
01873 }
01874
01875 void QMCWalker::calculateOppCorrelationDiagram(int coord, double min,
01876 double max, Array1D< Array1D<double> > &CorrelationDiagram)
01877 {
01878 int nalpha = Input->WF.getNumberElectrons(true);
01879 int nbeta = Input->WF.getNumberElectrons(false);
01880
01881 double dr = (max-min)/CorrelationDiagram.dim1();
01882 int index1 = 0;
01883 int index2 = 0;
01884
01885 for (int i=0; i<nalpha; i++)
01886 for (int j=nalpha; j<nalpha+nbeta; j++)
01887 if ( (R(i,coord) >= min) && (R(i,coord) <=max) )
01888 if ( (R(j,coord) >= min) && (R(j,coord) <= max) )
01889 {
01890 index1 = int((R(i,coord)-min)/dr);
01891 index2 = int((R(j,coord)-min)/dr);
01892 (CorrelationDiagram(index1))(index2) += weight;
01893 }
01894 }
01895
01896 void QMCWalker::toXML(ostream& strm)
01897 {
01898 strm << "<QMCWalker>" << endl;
01899 strm << "\t<Position>" <<endl;
01900 for(int ep=0; ep<R.dim1(); ep++)
01901 {
01902 strm << "\t\t";
01903 for(int j=0;j<R.dim2();j++)
01904 strm << R(ep,j) << "\t";
01905 strm << endl;
01906 }
01907 strm << "\t</Position>" << endl;
01908
01909 strm << "\t<Weight>\n\t\t" << getWeight() << "\n\t</Weight>" << endl;
01910 strm << "\t<Age>\n\t\t" << getAge() << "\n\t</Age>" << endl;
01911 strm << "</QMCWalker>\n" << endl;
01912 }
01913
01914 bool QMCWalker::readXML(istream& strm, QMCFunctions & QMF)
01915 {
01916 string temp;
01917 strm >> temp;
01918
01919 if (temp != "<QMCWalker>")
01920 return false;
01921
01922
01923 strm >> temp;
01924 if (temp != "<Position>")
01925 return false;
01926
01927 for(int ep=0; ep<R.dim1(); ep++)
01928 for(int j=0;j<R.dim2();j++)
01929 strm >> R(ep,j);
01930
01931 strm >> temp;
01932 if (temp != "</Position>")
01933 return false;
01934
01935
01936 strm >> temp;
01937 if (temp != "<Weight>")
01938 return false;
01939 strm >> temp;
01940 weight = atof(temp.c_str());
01941 strm >> temp;
01942 if (temp != "</Weight>")
01943 return false;
01944
01945
01946 strm >> temp;
01947 if (temp != "<Age>")
01948 return false;
01949 strm >> temp;
01950 age = atoi(temp.c_str());
01951 strm >> temp;
01952 if (temp != "</Age>")
01953 return false;
01954
01955 strm >> temp;
01956 if (temp != "</QMCWalker>")
01957 return false;
01958
01959 walkerData.updateDistances(R);
01960 QMF.evaluate(R,walkerData);
01961 newID();
01962
01963 return true;
01964 }
01965
01966 void QMCWalker::initializeWalkerPosition(QMCFunctions & QMF)
01967 {
01968 QMCInitializeWalker * IW =
01969 QMCInitializeWalkerFactory::initializeWalkerFactory(Input,
01970 Input->flags.walker_initialization_method);
01971
01972 setR(IW->initializeWalkerPosition());
01973 QMF.evaluate(R,walkerData);
01974
01975 int initilization_try = 1;
01976 while( isSingular() )
01977 {
01978 cerr << "Regenerating Walker..." << endl;
01979
01980 if( initilization_try > 10 )
01981 {
01982 cerr << "ERROR: 10 consecutive singular configurations while "
01983 << "trying to initilize walker!" << endl;
01984 exit(0);
01985 }
01986
01987 setR(IW->initializeWalkerPosition());
01988 QMF.evaluate(R,walkerData);
01989 initilization_try++;
01990 }
01991
01992 delete IW;
01993 IW = 0;
01994 }
01995
01996 double QMCWalker::getWeight()
01997 {
01998 return weight;
01999 }
02000
02001 void QMCWalker::setWeight(double val)
02002 {
02003 weight = val;
02004 }
02005
02006 int QMCWalker::getAge()
02007 {
02008 return age;
02009 }
02010
02011 double QMCWalker::getAcceptanceProbability()
02012 {
02013 return AcceptanceProbability;
02014 }
02015
02016 void QMCWalker::setAcceptanceProbability(double val)
02017 {
02018 AcceptanceProbability = val;
02019 }
02020
02021 Array2D<double> * QMCWalker::getR()
02022 {
02023 return &R;
02024 }
02025
02026 bool QMCWalker::setR(Array2D<double> temp_R)
02027 {
02028 bool ok = true;
02029 for(int i=0; i<temp_R.dim1(); i++)
02030 for(int j=0; j<temp_R.dim2(); j++)
02031 if(IeeeMath::isNaN(temp_R(i,j)) || temp_R(i,j) == 0 || fabs(temp_R(i,j)) > 500.0 )
02032 {
02033
02034 ok = false;
02035 }
02036 if(ok)
02037 {
02038 R = temp_R;
02039 walkerData.updateDistances(R);
02040 }
02041 return ok;
02042 }
02043
02044 QMCWalkerData* QMCWalker::getWalkerData()
02045 {
02046 return &walkerData;
02047 }
02048
02049 void QMCWalker::calculateObservables()
02050 {
02051 double p = TrialWalker->AcceptanceProbability;
02052 double q = 1.0 - p;
02053
02054
02055 localEnergy = p * TrialWalker->walkerData.localEnergy +
02056 q * OriginalWalker->walkerData.localEnergy;
02057
02058
02059 kineticEnergy = p * TrialWalker->walkerData.kineticEnergy +
02060 q * OriginalWalker->walkerData.kineticEnergy;
02061
02062
02063 potentialEnergy = p * TrialWalker->walkerData.potentialEnergy +
02064 q * OriginalWalker->walkerData.potentialEnergy;
02065
02066
02067 neEnergy = p * TrialWalker->walkerData.neEnergy +
02068 q * OriginalWalker->walkerData.neEnergy;
02069 eeEnergy = p * TrialWalker->walkerData.eeEnergy +
02070 q * OriginalWalker->walkerData.eeEnergy;
02071
02072
02073 if(globalInput.cs_Parameters.dim1() > 1)
02074 {
02075 cs_Energies.allocate(TrialWalker->walkerData.cs_LocalEnergy.dim1());
02076 cs_Weights.allocate(TrialWalker->walkerData.cs_Weights.dim1());
02077
02078 if(OriginalWalker->walkerData.cs_LocalEnergy.dim1() ==
02079 TrialWalker->walkerData.cs_LocalEnergy.dim1())
02080 {
02081 for(int cs=0; cs<cs_Energies.dim1(); cs++)
02082 {
02083 cs_Energies(cs) = p * TrialWalker->walkerData.cs_LocalEnergy(cs) +
02084 q * OriginalWalker->walkerData.cs_LocalEnergy(cs);
02085 cs_Weights(cs) = p * TrialWalker->walkerData.cs_Weights(cs) +
02086 q * OriginalWalker->walkerData.cs_Weights(cs);
02087
02088 }
02089 } else {
02090 cs_Energies = 0.0;
02091 cs_Weights = 0.0;
02092 }
02093 }
02094
02095 if(globalInput.flags.calculate_Derivatives == 1)
02096 {
02097 p3_xxa.allocate(TrialWalker->walkerData.p3_xxa.dim1());
02098 rp_a.allocate(TrialWalker->walkerData.rp_a.dim1());
02099
02100 if(iteration == 1)
02101 {
02102
02103
02104
02105
02106 for(int ai=0; ai<rp_a.dim1(); ai++)
02107 {
02108 p3_xxa(ai) = TrialWalker->walkerData.p3_xxa(ai);
02109
02110 rp_a(ai) = TrialWalker->walkerData.rp_a(ai);
02111 }
02112 } else {
02113 for(int ai=0; ai<rp_a.dim1(); ai++)
02114 {
02115 p3_xxa(ai) = p * TrialWalker->walkerData.p3_xxa(ai) +
02116 q * OriginalWalker->walkerData.p3_xxa(ai);
02117
02118 rp_a(ai) = p * TrialWalker->walkerData.rp_a(ai) +
02119 q * OriginalWalker->walkerData.rp_a(ai);
02120 }
02121 }
02122 }
02123
02124
02125
02126 distanceMovedAccepted = p * dR2;
02127
02128 if (Input->flags.calculate_bf_density == 1)
02129 {
02130 for (int i=0; i<Input->WF.getNumberBasisFunctions(); i++)
02131 walkerData.chiDensity(i) =
02132 p * TrialWalker->walkerData.chiDensity(i) +
02133 q * OriginalWalker->walkerData.chiDensity(i);
02134 }
02135
02136 if(Input->flags.nuclear_derivatives != "none")
02137 {
02138 for (int d1=0; d1<walkerData.nuclearDerivatives.dim1(); d1++)
02139 for (int d2=0; d2<walkerData.nuclearDerivatives.dim2(); d2++)
02140 walkerData.nuclearDerivatives(d1,d2) =
02141 p * TrialWalker->walkerData.nuclearDerivatives(d1,d2) +
02142 q * OriginalWalker->walkerData.nuclearDerivatives(d1,d2);
02143 }
02144
02145
02146
02147 double calcR12_T=0, calcR12_O=0;
02148 double calcR1_T=0, calcR1_O=0;
02149 double calcR2_T=0, calcR2_O=0;
02150 r2 = 0.0;
02151 for(int i=0; i<R.dim2(); i++)
02152 {
02153
02154
02155
02156 calcR1_T += TrialWalker->R(0,i)*TrialWalker->R(0,i);
02157 calcR2_T += TrialWalker->R(1,i)*TrialWalker->R(1,i);
02158 calcR1_O += OriginalWalker->R(0,i)*OriginalWalker->R(0,i);
02159 calcR2_O += OriginalWalker->R(1,i)*OriginalWalker->R(1,i);
02160
02161 double tempT, tempO;
02162 tempT = TrialWalker->R(0,i) - TrialWalker->R(1,i);
02163 tempO = OriginalWalker->R(0,i) - OriginalWalker->R(1,i);
02164
02165 calcR12_T += tempT*tempT;
02166 calcR12_O += tempO*tempO;
02167 }
02168 r12 = p*sqrt(calcR12_T) + q*sqrt(calcR12_O);
02169 ir12 = p/sqrt(calcR12_T) + q/sqrt(calcR12_O);
02170 ir = (p*(1.0/sqrt(calcR1_T) + 1.0/sqrt(calcR2_T))
02171 + q*(1.0/sqrt(calcR1_O) + 1.0/sqrt(calcR2_O)))/2.0;
02172 r2 = (p*(calcR1_T + calcR2_T)
02173 + q*(calcR1_O + calcR2_O))/2.0;
02174
02175
02176
02177
02178 double kineticEnergy_grad_O = 0.0;
02179 double kineticEnergy_grad_T = 0.0;
02180 kineticEnergy_grad_O = OriginalWalker->walkerData.gradPsiRatio.dotAllElectrons(OriginalWalker->walkerData.gradPsiRatio);
02181 kineticEnergy_grad_T = TrialWalker->walkerData.gradPsiRatio.dotAllElectrons(TrialWalker->walkerData.gradPsiRatio);
02182 kineticEnergy_grad = p*kineticEnergy_grad_T*TrialWalker->walkerData.psi
02183 + q*kineticEnergy_grad_O*OriginalWalker->walkerData.psi;
02184
02185
02186
02187
02188
02189
02190
02191
02192 double aWeight = 1.0;
02193 double pWeight = 1.0;
02194
02195
02196 for(int i=0; i<isCollectingFWResults.dim1(); i++)
02197 {
02198 for(int j=0; j<isCollectingFWResults.dim2(); j++)
02199 {
02200
02201 if(Input->flags.future_walking[i] == 0)
02202 continue;
02203
02204 if( isCollectingFWResults(i,j) != DONE)
02205 {
02206 fwNormalization(i,j) *= pWeight;
02207 fwR12(i,j) *= pWeight;
02208 fwR2(i,j) *= pWeight;
02209 fwiR12(i,j) *= pWeight;
02210 fwiR(i,j) *= pWeight;
02211 fwEnergy(i,j) *= pWeight;
02212 fwKineticEnergy(i,j) *= pWeight;
02213 fwKineticEnergy_grad(i,j)*= pWeight;
02214 fwPotentialEnergy(i,j) *= pWeight;
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226 }
02227
02228 if(isCollectingFWResults(i,j) == ACCUM )
02229 {
02230
02231 fwNormalization(i,j) += aWeight;
02232 fwR12(i,j) += aWeight * r12;
02233 fwR2(i,j) += aWeight * r2;
02234 fwiR12(i,j) += aWeight * ir12;
02235 fwiR(i,j) += aWeight * ir;
02236 fwEnergy(i,j) += aWeight * localEnergy;
02237 fwKineticEnergy(i,j) += aWeight * kineticEnergy;
02238 fwKineticEnergy_grad(i,j) += aWeight * kineticEnergy_grad;
02239 fwPotentialEnergy(i,j) += aWeight * potentialEnergy;
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249 }
02250 }
02251 }
02252 }
02253
02254 void QMCWalker::calculateObservables( QMCProperties & props )
02255 {
02256 if(getWeight() <= 0.0)
02257 return;
02258
02259 if(walkerData.whichE != -1 &&
02260 walkerData.whichE != 0)
02261 {
02262
02263
02264
02265
02266
02267
02268
02269
02270 return;
02271 }
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281 if(iteration > 0 && ageMoved > Input->flags.old_walker_acceptance_parameter){
02282 props.walkerAge.newSample(ageMoved,1.0);
02283 }
02284 ageMoved = -1;
02285
02286
02287 props.weightChange.newSample(dW,1.0);
02288
02289 double rel_diff = fabs( (localEnergy -
02290 Input->flags.energy_estimated_original)/
02291 Input->flags.energy_estimated_original);
02292 if(rel_diff < Input->flags.rel_cutoff)
02293 {
02294
02295 props.energy.newSample( localEnergy, getWeight() );
02296
02297
02298 props.kineticEnergy.newSample( kineticEnergy, getWeight() );
02299
02300
02301 props.potentialEnergy.newSample( potentialEnergy, getWeight() );
02302
02303
02304 props.neEnergy.newSample( neEnergy, getWeight() );
02305 props.eeEnergy.newSample( eeEnergy, getWeight() );
02306 }
02307 else
02308 {
02309 if(age == 0)
02310 {
02311 bool shouldWarn = false;
02312 switch(Input->flags.warn_verbosity)
02313 {
02314 case 0: break;
02315 case 1: if(rel_diff > 5.0) shouldWarn = true; break;
02316 case 2: if(rel_diff > 2.0) shouldWarn = true; break;
02317 case 3: if(rel_diff > 1.0) shouldWarn = true; break;
02318 default:shouldWarn = true; break;
02319 }
02320
02321 if(shouldWarn && iteration + Input->flags.equilibration_steps > 5){
02322 cerr << "ERROR: Not including walker in average " << ID(move_accepted);
02323 cerr << " localEnergy = " << localEnergy << endl;
02324 cerr.flush();
02325 }
02326 }
02327 }
02328
02329
02330 props.acceptanceProbability.newSample( getAcceptanceProbability(), getWeight() );
02331
02332
02333
02334 props.distanceMovedAccepted.newSample( distanceMovedAccepted, getWeight() );
02335
02336
02337
02338 props.distanceMovedTrial.newSample( dR2, getWeight() );
02339
02340
02341 props.logWeights.newSample(getWeight(),1);
02342 }
02343
02344 void QMCWalker::calculateObservables( QMCPropertyArrays & fwProps )
02345 {
02346
02347 double rel_diff = fabs( (localEnergy -
02348 Input->flags.energy_estimated_original)/
02349 Input->flags.energy_estimated_original);
02350
02351 double fWeight = getWeight();
02352
02353
02354 for(int i=0; i<isCollectingFWResults.dim1(); i++)
02355 {
02356 numFWSteps[i]++;
02357
02358
02359 if(Input->flags.future_walking[i] == 0)
02360 {
02361
02362 if(Input->flags.nuclear_derivatives != "none")
02363 for (int d1=0; d1<walkerData.nuclearDerivatives.dim1(); d1++)
02364 for (int d2=0; d2<walkerData.nuclearDerivatives.dim2(); d2++)
02365 (fwProps.nuclearForces(i))(d1,d2).newSample( walkerData.nuclearDerivatives(d1,d2), fWeight );
02366
02367 (fwProps.props[FW_It])(i).newSample(1.0, fWeight);
02368 (fwProps.props[FW_R12])(i).newSample(r12, fWeight);
02369 (fwProps.props[FW_R2])(i).newSample(r2, fWeight);
02370 (fwProps.props[FW_iR12])(i).newSample(ir12, fWeight);
02371 (fwProps.props[FW_iR])(i).newSample(ir, fWeight);
02372 (fwProps.props[FW_TE])(i).newSample(localEnergy, fWeight);
02373 (fwProps.props[FW_KE])(i).newSample(kineticEnergy, fWeight);
02374 (fwProps.props[FW_KEg])(i).newSample(kineticEnergy_grad, fWeight);
02375 (fwProps.props[FW_PE])(i).newSample(potentialEnergy, fWeight);
02376
02377 (fwProps.props[FW_R12_2])(i).newSample(r12*r12, fWeight);
02378 (fwProps.props[FW_R2_2])(i).newSample(r2*r2, fWeight);
02379 (fwProps.props[FW_iR12_2])(i).newSample(ir12*ir12, fWeight);
02380 (fwProps.props[FW_iR_2])(i).newSample(ir*ir, fWeight);
02381 (fwProps.props[FW_TE_2])(i).newSample(localEnergy*localEnergy, fWeight);
02382 (fwProps.props[FW_KE_2])(i).newSample(kineticEnergy*kineticEnergy, fWeight);
02383 (fwProps.props[FW_KEg_2])(i).newSample(kineticEnergy_grad*kineticEnergy_grad, fWeight);
02384 (fwProps.props[FW_PE_2])(i).newSample(potentialEnergy*potentialEnergy, fWeight);
02385 continue;
02386 }
02387
02388
02389
02390 if(numFWSteps[i] > Input->flags.future_walking[i])
02391 {
02392 int whichIsDone = isCollectingFWResults(i,0) == DONE ? 0 : 1;
02393 int otherStage = (whichIsDone+1)%2;
02394 isCollectingFWResults(i,whichIsDone) = ACCUM;
02395 isCollectingFWResults(i,otherStage) = ASYMP;
02396 numFWSteps[i] = 0;
02397 }
02398 else if(numFWSteps[i] == int(maxFWAsymp*Input->flags.future_walking[i]+0.5))
02399 {
02400
02401
02402
02403
02404 int whichIsDone = isCollectingFWResults(i,0) == ACCUM ? 1 : 0;
02405
02406 if(isCollectingFWResults(i,whichIsDone) == DONE)
02407 break;
02408 isCollectingFWResults(i,whichIsDone) = DONE;
02409
02410 double norm = 1.0/fwNormalization(i,whichIsDone);
02411 (fwProps.props[FW_It])(i).newSample(fwNormalization(i,whichIsDone)/numFWSteps[i],fWeight);
02412 (fwProps.props[FW_R12])(i).newSample(fwR12(i,whichIsDone)*norm,fWeight);
02413 (fwProps.props[FW_R2])(i).newSample(fwR2(i,whichIsDone)*norm,fWeight);
02414 (fwProps.props[FW_iR12])(i).newSample(fwiR12(i,whichIsDone)*norm,fWeight);
02415 (fwProps.props[FW_iR])(i).newSample(fwiR(i,whichIsDone)*norm,fWeight);
02416 (fwProps.props[FW_TE])(i).newSample(fwEnergy(i,whichIsDone)*norm,fWeight);
02417 (fwProps.props[FW_KE])(i).newSample(fwKineticEnergy(i,whichIsDone)*norm,fWeight);
02418 (fwProps.props[FW_KEg])(i).newSample(fwKineticEnergy_grad(i,whichIsDone)*norm,fWeight);
02419 (fwProps.props[FW_PE])(i).newSample(fwPotentialEnergy(i,whichIsDone)*norm,fWeight);
02420
02421 (fwProps.props[FW_R12_2])(i).newSample(fwR12(i,whichIsDone)*norm*r12,fWeight);
02422 (fwProps.props[FW_R2_2])(i).newSample(fwR2(i,whichIsDone)*norm*r2,fWeight);
02423 (fwProps.props[FW_iR12_2])(i).newSample(fwiR12(i,whichIsDone)*norm*ir12,fWeight);
02424 (fwProps.props[FW_iR_2])(i).newSample(fwiR(i,whichIsDone)*norm*ir,fWeight);
02425 (fwProps.props[FW_TE_2])(i).newSample(fwEnergy(i,whichIsDone)*norm*localEnergy,fWeight);
02426 (fwProps.props[FW_KE_2])(i).newSample(fwKineticEnergy(i,whichIsDone)*norm*kineticEnergy,fWeight);
02427 (fwProps.props[FW_KEg_2])(i).newSample(fwKineticEnergy_grad(i,whichIsDone)*norm*kineticEnergy,fWeight);
02428 (fwProps.props[FW_PE_2])(i).newSample(fwPotentialEnergy(i,whichIsDone)*norm*potentialEnergy,fWeight);
02429
02430
02431 if(Input->flags.nuclear_derivatives != "none")
02432 for (int d1=0; d1<walkerData.nuclearDerivatives.dim1(); d1++)
02433 for (int d2=0; d2<walkerData.nuclearDerivatives.dim2(); d2++)
02434 (fwProps.nuclearForces(i))(d1,d2).newSample( (fwNuclearForces(d1,d2))(i,whichIsDone)*norm, fWeight );
02435
02436 resetFutureWalking(i,whichIsDone);
02437 }
02438 }
02439
02440
02441 if(rel_diff > Input->flags.rel_cutoff)
02442 return;
02443
02444 if(globalInput.cs_Parameters.dim1() > 1)
02445 {
02446 for(int cs=0; cs<cs_Energies.dim1(); cs++)
02447 {
02448 fwProps.cs_Energies(cs).newSample( cs_Energies(cs), getWeight() * cs_Weights(cs));
02449 }
02450 }
02451 else
02452 {
02453 cs_Energies.deallocate();
02454 cs_Weights.deallocate();
02455 }
02456
02457
02458 if (Input->flags.calculate_bf_density == 1)
02459 for (int i=0; i<Input->WF.getNumberBasisFunctions(); i++)
02460 fwProps.chiDensity(i).newSample( walkerData.chiDensity(i), getWeight() );
02461 }
02462
02463 void QMCWalker::calculateDerivatives( QMCPropertyArrays & props )
02464 {
02465
02466 double rel_diff = fabs( (localEnergy -
02467 Input->flags.energy_estimated_original)/
02468 Input->flags.energy_estimated_original);
02469 if(rel_diff > Input->flags.rel_cutoff)
02470 return;
02471
02472 if(globalInput.flags.calculate_Derivatives == 1)
02473 {
02474 props.numDerHessSamples++;
02475
02476 int numAI = rp_a.dim1();
02477 for(int ai=0; ai<numAI; ai++)
02478 {
02479
02480
02481
02482
02483 double e2 = localEnergy * localEnergy;
02484 props.der(ai,0) += rp_a(ai);
02485 props.der(ai,1) += rp_a(ai) * localEnergy;
02486 props.der(ai,2) += rp_a(ai) * e2;
02487 props.der(ai,3) += p3_xxa(ai);
02488 props.der(ai,4) += p3_xxa(ai) * localEnergy;
02489 }
02490
02491 if(globalInput.flags.optimize_Psi_criteria == "analytical_energy_variance")
02492 {
02493 for(int ai=0; ai<numAI; ai++)
02494 for(int aj=0; aj<=ai; aj++)
02495 (props.hess(0))(ai,aj) += p3_xxa(ai) * p3_xxa(aj);
02496
02497 } else if(globalInput.flags.optimize_Psi_criteria == "generalized_eigenvector") {
02498
02499 for(int ai=0; ai<numAI; ai++)
02500 for(int aj=0; aj<numAI; aj++)
02501 {
02502 (props.hess(0))(ai,aj) += rp_a(ai) * rp_a(aj) * localEnergy;
02503 (props.hess(1))(ai,aj) += rp_a(ai) * rp_a(aj);
02504 (props.hess(2))(ai,aj) += rp_a(ai) * p3_xxa(aj);
02505 }
02506 }
02507 } else {
02508 rp_a.deallocate();
02509 p3_xxa.deallocate();
02510 }
02511 }
02512
02513 void QMCWalker::resetFutureWalking(int whichBlock, int whichIsDone)
02514 {
02515 if(whichIsDone > 1 || whichIsDone < 0)
02516 {
02517 cerr << "Error: There are only 2 FW stages!\n";
02518 exit(1);
02519 }
02520
02521 fwNormalization(whichBlock,whichIsDone) = 0;
02522 fwR12(whichBlock,whichIsDone) = 0;
02523 fwR2(whichBlock,whichIsDone) = 0;
02524 fwiR12(whichBlock,whichIsDone) = 0;
02525 fwiR(whichBlock,whichIsDone) = 0;
02526 fwEnergy(whichBlock,whichIsDone) = 0;
02527 fwKineticEnergy(whichBlock,whichIsDone) = 0;
02528 fwKineticEnergy_grad(whichBlock,whichIsDone) = 0;
02529 fwPotentialEnergy(whichBlock,whichIsDone) = 0;
02530
02531 if(Input->flags.nuclear_derivatives != "none")
02532 for (int d1=0; d1<fwNuclearForces.dim1(); d1++)
02533 for (int d2=0; d2<fwNuclearForces.dim2(); d2++)
02534 (fwNuclearForces(d1,d2))(whichBlock,whichIsDone) = 0;
02535 }
02536
02537 void QMCWalker::resetFutureWalking()
02538 {
02539 numFWSteps = 0;
02540 for(int i=0; i<isCollectingFWResults.dim1(); i++)
02541 {
02542 isCollectingFWResults(i,0) = ACCUM;
02543 isCollectingFWResults(i,1) = DONE;
02544 for(int j=0; j<isCollectingFWResults.dim2(); j++)
02545 resetFutureWalking(i,j);
02546 }
02547 }
02548
02549
02550 bool QMCWalker::isSingular()
02551 {
02552 return walkerData.isSingular();
02553 }
02554
02555 double QMCWalker::getLocalEnergyEstimator()
02556 {
02557 return localEnergy;
02558 }
02559