00001
00002
00003
00004 #include "QMCSurfer.h"
00005 #include "QMCInput.h"
00006
00007 using namespace std;
00008
00009 QMCSurfer::QMCSurfer()
00010 {
00011 QMF = 0;
00012 walkerData.initialize(3,-1,-1);
00013 }
00014
00015 QMCSurfer::~QMCSurfer()
00016 {
00017 QMF = 0;
00018 R.deallocate();
00019 }
00020
00021 int QMCSurfer::mainMenu(QMCFunctions * useQMF, int iteration,
00022 Array2D<double> newR)
00023 {
00024
00025
00026
00027
00028
00029 R = newR;
00030 QMF = useQMF;
00031 static bool done = false;
00032 static char ok = 's';
00033 static int iteration_to_stop = iteration + 100 - 1;
00034 cout << "iteration_to_stop = " << iteration_to_stop << endl;
00035 string prompt = "[e]xit [c]usp toggle [j]astrow toggle [d]etailed [r]eset [n]ext [s]can [p]ositions [a]nother walker [i]terations ";
00036 if( iteration >= iteration_to_stop)
00037 {
00038 iteration_to_stop += 1000;
00039 done = true;
00040 cout << "We're at iteration " << iteration << ", next stop will be at " << iteration_to_stop << endl;
00041
00042 string mystr;
00043 cout << prompt << "[" << ok << "]: ";
00044 getline(cin,mystr);
00045 if(mystr != "") ok = (mystr.c_str())[0];
00046 ok = tolower(ok);
00047
00048 while(ok != 'n' && ok != 'N' && ok != 'a' && ok != 'A')
00049 {
00050 int skip;
00051 switch(ok)
00052 {
00053 case 'e':
00054 exit(0);
00055 break;
00056
00057 case 'p':
00058 interparticleDistanceMatrix();
00059 break;
00060
00061 case 'r':
00062 R = newR;
00063 walkerData.whichE = -1;
00064 walkerData.updateDistances(R);
00065 QMF->evaluate(R,walkerData);
00066 break;
00067
00068 case 'n':
00069
00070 break;
00071
00072 case 's':
00073 surfaceExplorer();
00074 break;
00075
00076 case 'a':
00077 iteration_to_stop -= 1000;
00078 done = false;
00079 break;
00080
00081 case 'i':
00082 skip = 10000;
00083 cout << "Iterations to skip [" << skip << "]: ";
00084 getline(cin,mystr);
00085 if(mystr != "") stringstream(mystr) >> skip;
00086
00087 iteration_to_stop -= 1000;
00088 iteration_to_stop += skip;
00089 cout << "Next stop will be at iteration " << iteration_to_stop << endl;
00090 break;
00091
00092 case 'c':
00093 if(globalInput.flags.replace_electron_nucleus_cusps == 1)
00094 {
00095 cout << "Turning cusp replacement off..." << endl;
00096 globalInput.flags.replace_electron_nucleus_cusps = 0;
00097 } else {
00098 cout << "Turning cusp replacement on..." << endl;
00099 globalInput.flags.replace_electron_nucleus_cusps = 1;
00100 }
00101 break;
00102
00103 case 'j':
00104 if(globalInput.flags.use_jastrow == 1)
00105 {
00106 cout << "Turning jastrows off..." << endl;
00107 globalInput.flags.use_jastrow = 0;
00108 } else {
00109 cout << "Turning jastrows on..." << endl;
00110 globalInput.flags.use_jastrow = 1;
00111 }
00112 break;
00113
00114 case 'd':
00115 if(globalInput.flags.detailed_energies > -1)
00116 {
00117 cout << "Turning off detailed energy printing..." << endl;
00118 globalInput.flags.detailed_energies = -1;
00119 } else {
00120 cout << "Turning on detailed energy printing..." << endl;
00121 globalInput.flags.detailed_energies = 1;
00122 }
00123 break;
00124
00125 default:
00126 cout << "Error: selected \'" << ok << "\'" << endl;
00127 break;
00128 }
00129
00130 string mystr;
00131 cout << prompt << "[" << ok << "]: ";
00132 getline(cin,mystr);
00133 if(mystr != "") ok = (mystr.c_str())[0];
00134 }
00135 } else {
00136 if( (iteration + globalInput.flags.equilibration_steps) % 1000 != 0)
00137 done = false;
00138 }
00139 return iteration_to_stop;
00140 }
00141
00142 void QMCSurfer::interparticleDistanceMatrix()
00143 {
00144 int numE = R.dim1();
00145 int numZ = globalInput.Molecule.getNumberAtoms();
00146 int numA = globalInput.WF.getNumberElectrons(true);
00147 double dist_hilight = 0.3;
00148 for(int i=0; i<numA; i++){
00149 for(int j=0; j<i; j++){
00150 double x = R(i,0) - R(j,0);
00151 double y = R(i,1) - R(j,1);
00152 double z = R(i,2) - R(j,2);
00153 double dist = sqrt(x*x + y*y + z*z);
00154 if( (i-numA+0.5)*(j-numA+0.5) > 0.0)
00155 {
00156 cout << "\033[0;35m";
00157 } else {
00158 cout << "\033[0;31m";
00159 }
00160 if(dist < dist_hilight) cout << "\033[0;36m";
00161 if(j%5 == 0) cout << endl;
00162 printf("(%2i,%2i %24.16f) ",i,j,dist);
00163 }
00164 }
00165 for(int i=numA; i<numE; i++){
00166 for(int j=numA; j<i; j++){
00167 double x = R(i,0) - R(j,0);
00168 double y = R(i,1) - R(j,1);
00169 double z = R(i,2) - R(j,2);
00170 double dist = sqrt(x*x + y*y + z*z);
00171 if( (i-numA+0.5)*(j-numA+0.5) > 0.0)
00172 {
00173 cout << "\033[0;35m";
00174 } else {
00175 cout << "\033[0;31m";
00176 }
00177 if((j-numA)%5 == 0) cout << endl;
00178 if(dist < dist_hilight) cout << "\033[0;36m";
00179 printf("(%2i,%2i %24.16f) ",i,j,dist);
00180 }
00181 }
00182 for(int i=0; i<numA; i++){
00183 for(int j=numA; j<numE; j++){
00184 double x = R(i,0) - R(j,0);
00185 double y = R(i,1) - R(j,1);
00186 double z = R(i,2) - R(j,2);
00187 double dist = sqrt(x*x + y*y + z*z);
00188 if( (i-numA+0.5)*(j-numA+0.5) > 0.0)
00189 {
00190 cout << "\033[0;35m";
00191 } else {
00192 cout << "\033[0;31m";
00193 }
00194 if((j-numA)%5 == 0) cout << endl;
00195 if(dist < dist_hilight) cout << "\033[0;36m";
00196 printf("(%2i,%2i %24.16f) ",i,j,dist);
00197 }
00198 }
00199 cout << "\033[0m" << endl;
00200 for(int i=0; i<numZ; i++){
00201 for(int j=0; j<numE; j++){
00202 double x = globalInput.Molecule.Atom_Positions(i,0) - R(j,0);
00203 double y = globalInput.Molecule.Atom_Positions(i,1) - R(j,1);
00204 double z = globalInput.Molecule.Atom_Positions(i,2) - R(j,2);
00205 double dist = sqrt(x*x + y*y + z*z);
00206 if(j%5 == 0) cout << endl;
00207 if(dist < dist_hilight)
00208 cout << "\033[0;36m";
00209 else
00210 cout << "\033[0m";
00211 printf("(%2s,%2i %24.16f) ",globalInput.Molecule.Atom_Labels(i).data(),j,dist);
00212 }
00213 }
00214 cout << "\033[0m" << endl;
00215 }
00216
00217 void QMCSurfer::equipotentialSurface()
00218 {
00219 int numE = R.dim1();
00220 int numZ = globalInput.Molecule.getNumberAtoms();
00221
00222 for(int i=0; i<numE; i++){
00223 double potential = 0.0;
00224 for(int j=0; j<numE; j++){
00225 if(i == j) continue;
00226 double x = R(i,0) - R(j,0);
00227 double y = R(i,1) - R(j,1);
00228 double z = R(i,2) - R(j,2);
00229 double dist = sqrt(x*x + y*y + z*z);
00230 potential += 1.0/dist;
00231 }
00232 for(int j=0; j<numZ; j++){
00233 double x = globalInput.Molecule.Atom_Positions(j,0) - R(i,0);
00234 double y = globalInput.Molecule.Atom_Positions(j,1) - R(i,1);
00235 double z = globalInput.Molecule.Atom_Positions(j,2) - R(i,2);
00236 double dist = sqrt(x*x + y*y + z*z);
00237 potential -= globalInput.Molecule.Z(j) / dist;
00238 }
00239 printf("(%2i) %20.10f ",i,potential);
00240 if((i+1)%5 == 0 || i == numE - 1) printf("\n");
00241 }
00242 }
00243
00244 void QMCSurfer::scanEnergies(int moveE, int nucStart, int nucStop, int numSteps,
00245 double startFrac, double stopFrac, double perturb)
00246 {
00247 bool printXYZ = false;
00248 bool allKE = true;
00249 bool printPE = false;
00250
00251
00252 double pi = acos(-1.0);
00253 double r=0, theta=0, phi=0;
00254 double x, y, z;
00255 double dx=-1, dy=-1, dz=-1;
00256 int numA = globalInput.Molecule.getNumberAtoms();
00257
00258 perturb = 1e-10;
00259
00260 if(nucStart - numA > R.dim1()){
00261 cout << "Start index of " << nucStart << " is outside available range." << endl;
00262 return;
00263 }
00264 if(nucStop - numA > R.dim1()){
00265 cout << "Stop index of " << nucStop << " is outside available range." << endl;
00266 return;
00267 }
00268
00269 if(nucStart < numA){
00270 x = globalInput.Molecule.Atom_Positions(nucStart,0);
00271 y = globalInput.Molecule.Atom_Positions(nucStart,1);
00272 z = globalInput.Molecule.Atom_Positions(nucStart,2);
00273 } else {
00274 x = R(nucStart-numA,0);
00275 y = R(nucStart-numA,1);
00276 z = R(nucStart-numA,2);
00277 }
00278
00279 if(globalInput.flags.detailed_energies > -1)
00280 globalInput.flags.detailed_energies = moveE;
00281
00282 if(nucStart != nucStop && nucStop != -2){
00283 if(nucStart < numA){
00284 cout << "Moving electron " << moveE << " from atom " << nucStart << "\n " << globalInput.Molecule.Atom_Labels(nucStart);
00285 } else {
00286 cout << "Moving electron " << moveE << " from electron\ne" << (nucStart-numA);
00287 }
00288 cout << " at " << x << ", " << y << ", " << z;
00289
00290 if(nucStop < numA){
00291 cout << "\nto atom " << nucStop << "\n " << globalInput.Molecule.Atom_Labels(nucStop) << " at ";
00292 dx = globalInput.Molecule.Atom_Positions(nucStop,0);
00293 dy = globalInput.Molecule.Atom_Positions(nucStop,1);
00294 dz = globalInput.Molecule.Atom_Positions(nucStop,2);
00295 } else {
00296 cout << "\nto electron\ne" << (nucStop-numA);
00297 dx = R(nucStop-numA,0);
00298 dy = R(nucStop-numA,1);
00299 dz = R(nucStop-numA,2);
00300 }
00301 cout << " at " << dx << ", " << dy << ", " << dz << endl;
00302 } else {
00303
00304 if(nucStart < numA){
00305 cout << "Moving electron " << moveE << " relative to atom " << nucStart << "\n" << globalInput.Molecule.Atom_Labels(nucStart);
00306 } else {
00307 cout << "Moving electron " << moveE << " relative to electron\ne" << (nucStart-numA);
00308 }
00309 cout << " at " << x << ", " << y << ", " << z << endl;
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 }
00328
00329 double delta;
00330 if(nucStop != -2)
00331 {
00332 dx = dx - x;
00333 dy = dy - y;
00334 dz = dz - z;
00335
00336
00337
00338 delta = (stopFrac - startFrac)/(numSteps);
00339 printf("scan distance = %10.5e (dx = %10.5f dy = %10.5f dz = %10.5f) delta = %10.5f\n",
00340 sqrt(dx*dx+dy*dy+dz*dz),dx,dy,dz,delta);
00341
00342 printf(" %10s %10s","step","dist");
00343 } else {
00344 r = startFrac;
00345 phi = stopFrac;
00346
00347 delta = 2.0*pi/(numSteps);
00348 startFrac = 0.0;
00349 stopFrac = 2.0*pi;
00350 printf("circumference = %10.5e, phi = %10.5f, dr = %10.5e\n",stopFrac*r,phi,delta);
00351 printf(" %10s %10s","theta","%");
00352 }
00353 if(printXYZ) printf(" %10s %10s %10s","x","y","z");
00354
00355 printf(" %20s %20s %20s","TE","KE","Grad_J.SCF_term");
00356 if(allKE)
00357 printf(" %20s %20s","Lap_SCF_term","Jastrow_term");
00358
00359 printf(" %20s %20s","PE","Psi");
00360 if(printPE)
00361 printf(" %20s %20s %20s","NE","EE","Virial");
00362
00363 printf("\n");
00364 double ee_start = 0;
00365 bool odd = true;
00366 for(double frac=startFrac; (frac - stopFrac) < delta; frac += delta)
00367 {
00368 double dist;
00369 if(nucStop != -2)
00370 {
00371
00372 R(moveE,0) = x + (frac+perturb)*dx;
00373 R(moveE,1) = y + (frac+perturb)*dy;
00374 R(moveE,2) = z + (frac+perturb)*dz;
00375
00376 dist = (dx*dx + dy*dy + dz*dz);
00377 dist = sqrt(dist)*(frac+perturb);
00378 } else {
00379 theta = frac;
00380
00381 R(moveE,0) = x + r*cos(theta)*sin(phi);
00382 R(moveE,1) = y + r*sin(theta)*sin(phi);
00383 R(moveE,2) = z + r*cos(phi);
00384
00385 dist = r*frac;
00386 }
00387
00388
00389
00390
00391
00392
00393 for(int xyz=0; xyz<3; xyz++)
00394 if(R(moveE,xyz) == 0.0)
00395 R(moveE,xyz) = perturb;
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 int swapE = -1;
00409
00410 if(odd && swapE > -1)
00411 for(int xyz=0; xyz<3; xyz++)
00412 {
00413 double temp = R(moveE,xyz);
00414 R(moveE,xyz) = R(swapE,xyz);
00415 R(swapE,xyz) = temp;
00416 }
00417
00418 walkerData.whichE = -1;
00419 walkerData.updateDistances(R);
00420 QMF->evaluate(R,walkerData);
00421
00422 if(odd && swapE > -1)
00423 for(int xyz=0; xyz<3; xyz++)
00424 {
00425 double temp = R(moveE,xyz);
00426 R(moveE,xyz) = R(swapE,xyz);
00427 R(swapE,xyz) = temp;
00428 }
00429 odd = !odd;
00430
00431 if((double)walkerData.psi > 0)
00432 {
00433
00434 cout << "\033[0;32m";
00435 } else {
00436 cout << "\033[0;33m";
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 if(frac >= 0)
00470 {
00471 printf(" %10.8f %10.4e",
00472 frac,
00473 dist);
00474 } else {
00475 printf(" %10.7f %10.4e",
00476 frac,
00477 dist);
00478 }
00479
00480 if(printXYZ) printf(" %10.3e %10.3e %10.3e",R(moveE,0),R(moveE,1),R(moveE,2));
00481
00482 if(fabs(walkerData.localEnergy) >= 1e4)
00483 {
00484 printf(" %20.10e",
00485 walkerData.localEnergy);
00486 } else {
00487 printf(" %20.14f",
00488 walkerData.localEnergy);
00489 }
00490
00491
00492 double grade = walkerData.D_xx + walkerData.U_xx;
00493 grade *= -0.5;
00494 grade = walkerData.kineticEnergy - grade;
00495 if(fabs(walkerData.kineticEnergy) >= 1e4 ||
00496 fabs(walkerData.potentialEnergy) >= 1e4)
00497 {
00498 printf(" %20.10e %20.7e",
00499 walkerData.kineticEnergy,
00500 grade);
00501 if(allKE)
00502 {
00503 printf(" %20.7e %20.7e",
00504 -0.5*walkerData.D_xx,
00505 -0.5*walkerData.U);
00506 }
00507 printf(" %20.10e",
00508 walkerData.potentialEnergy);
00509
00510 } else {
00511 printf(" %20.14f %20.10f",
00512 walkerData.kineticEnergy,
00513 grade);
00514 if(allKE)
00515 {
00516 printf(" %20.10f %20.10f",
00517 -0.5*walkerData.D_xx,
00518 -0.5*walkerData.U);
00519 }
00520 printf(" %20.14f",
00521 walkerData.potentialEnergy);
00522 }
00523 printf(" %20.10e",
00524 (double)walkerData.psi);
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 if(ee_start == 0) ee_start = walkerData.eeEnergy;
00535 double deeddist = (walkerData.eeEnergy - ee_start)/(dist*delta);
00536
00537 if(false)
00538 if(deeddist >= 0)
00539 {
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 cout << "\033[0;35m";
00552 } else {
00553 cout << "\033[0;31m";
00554 }
00555
00556 if(printPE)
00557 {
00558 if(fabs(walkerData.eeEnergy) >= 1e4 ||
00559 fabs(walkerData.neEnergy) >= 1e4)
00560 {
00561 printf(" %20.10e %20.10e",
00562 walkerData.eeEnergy,
00563 walkerData.neEnergy);
00564 } else {
00565 printf(" %20.14f %20.14f",
00566 walkerData.eeEnergy,
00567 walkerData.neEnergy);
00568
00569 }
00570 printf(" %20.10f",
00571 (-1.0*walkerData.potentialEnergy/walkerData.kineticEnergy));
00572 }
00573
00574 if(false)
00575 {
00576 if((double)walkerData.psi > 0)
00577 {
00578
00579 cout << "\033[0;32m";
00580 } else {
00581 cout << "\033[0;33m";
00582 }
00583 }
00584
00585 ee_start = walkerData.eeEnergy;
00586 printf("\n");
00587 cout << "\033[0m";
00588 }
00589 cout.flush();
00590 }
00591
00592 void QMCSurfer::surfaceExplorer()
00593 {
00594 int heaviest = 0;
00595 int lightest = 0;
00596 for(int i=0; i<globalInput.Molecule.getNumberAtoms(); i++)
00597 {
00598 if(globalInput.Molecule.Z(heaviest) < globalInput.Molecule.Z(i))
00599 heaviest = i;
00600 if(globalInput.Molecule.Z(lightest) > globalInput.Molecule.Z(i))
00601 lightest = i;
00602 }
00603 static double startFrac = 0.0;
00604 static double stopFrac = 1.0;
00605 static int moveE = 0;
00606 static int startAtom = heaviest;
00607 static int stopAtom = lightest;
00608 if(startAtom == stopAtom)
00609 stopAtom = -2;
00610
00611 static int steps = 50;
00612 static double defR = 0.0000001;
00613 static double defP = acos(-1.0)/2.0;
00614
00615
00616 char ok = 'n';
00617
00618 while(ok == 'n' || ok == 'N')
00619 {
00620 string mystr;
00621
00622 cout << "Enter electron to move [" << moveE << "]: ";
00623 getline(cin,mystr);
00624 if(mystr != "") stringstream(mystr) >> moveE;
00625
00626 cout << "Atom indices are 0:" << globalInput.Molecule.getNumberAtoms()-1
00627 << "; electron indicies " << globalInput.Molecule.getNumberAtoms()
00628 << ":" << globalInput.Molecule.getNumberAtoms()+globalInput.WF.getNumberElectrons()
00629 << "; -1 for all" << endl;
00630 cout << "Enter starting particle [" << startAtom << "]: ";
00631 getline(cin,mystr);
00632 if(mystr != "") stringstream(mystr) >> startAtom;
00633
00634 cout << "New option: -2 for ring" << endl;
00635 cout << "Enter stopping particle [" << stopAtom << "]: ";
00636 getline(cin,mystr);
00637 if(mystr != "") stringstream(mystr) >> stopAtom;
00638
00639 cout << "Selected electron " << moveE << " to move from " << startAtom << " to " << stopAtom << endl;
00640 if(startAtom <= -2 || moveE < 0 || moveE >= globalInput.WF.getNumberElectrons())
00641 {
00642 cerr << "Bad values, try again\n";
00643 } else {
00644 ok = 'y';
00645
00646
00647 }
00648 }
00649 ok = 'n';
00650 while(ok == 'n' || ok == 'N')
00651 {
00652 string mystr;
00653 cout << "Enter steps [" << steps << "]: ";
00654 getline(cin,mystr);
00655 if(mystr != "") stringstream(mystr) >> steps;
00656
00657 if(stopAtom != -2)
00658 {
00659 cout << "Enter starting fraction [" << startFrac << "]: ";
00660 getline(cin,mystr);
00661 if(mystr != "") stringstream(mystr) >> startFrac;
00662 cout << "Enter stopping fraction [" << stopFrac << "]: ";
00663 getline(cin,mystr);
00664 if(mystr != "") stringstream(mystr) >> stopFrac;
00665 cout << "Selected " << startFrac << " to " << stopFrac << " in " << steps << " steps" << endl;
00666 } else {
00667 startFrac = defR;
00668 stopFrac = defP;
00669 cout << "Enter radius [" << startFrac << "]: ";
00670 getline(cin,mystr);
00671 if(mystr != "") stringstream(mystr) >> startFrac;
00672 cout << "Enter phi [" << stopFrac << "]: ";
00673 getline(cin,mystr);
00674 if(mystr != "") stringstream(mystr) >> stopFrac;
00675 cout << "Selected radius " << startFrac << ", phi = " << stopFrac << " in " << steps << " steps" << endl;
00676 }
00677
00678 if(stopFrac == startFrac || (stopAtom == -2 && startFrac < 0.0))
00679 {
00680 cerr << "Bad values, try again\n";
00681 } else {
00682 ok = 'y';
00683 if(stopAtom == -2)
00684 {
00685 defR = startFrac;
00686 defP = stopFrac;
00687 }
00688
00689
00690 }
00691 }
00692
00693 for(int i=0; i<globalInput.Molecule.getNumberAtoms(); i++)
00694 {
00695 for(int j=0; j<globalInput.Molecule.getNumberAtoms(); j++)
00696 {
00697 bool run = false;
00698 if( startAtom == i && stopAtom == j)
00699 run = true;
00700
00701 if(startAtom >= globalInput.Molecule.getNumberAtoms() || stopAtom >= globalInput.Molecule.getNumberAtoms())
00702 {
00703 if(i==0 && j==0){
00704 if(startAtom >= globalInput.Molecule.getNumberAtoms() &&
00705 stopAtom >= globalInput.Molecule.getNumberAtoms())
00706 run = true;
00707 if( startAtom == -2 || stopAtom == -2)
00708 run = true;
00709 }
00710 if(i==j){
00711 if(startAtom == -1 || stopAtom == -1)
00712 run = true;
00713 if(startAtom == i || stopAtom == j)
00714 run = true;
00715 }
00716 }
00717
00718 if(startAtom == stopAtom && startAtom >= 0)
00719 run = true;
00720
00721 if(startAtom == -1 && stopAtom == j && i != j)
00722 run = true;
00723
00724 if(stopAtom == -1 && startAtom == i && i != j)
00725 run = true;
00726
00727 if(stopAtom == -1 && startAtom == -1 && i < j)
00728 run = true;
00729
00730 if(stopAtom == -2 && startAtom == i && i == j)
00731 run = true;
00732
00733 if(stopAtom == -2 && startAtom == -1 && i == j)
00734 run = true;
00735
00736 if(run){
00737 int indexi = i, indexj = j;
00738 if(stopAtom == -2) indexj = -2;
00739 if(startAtom >= globalInput.Molecule.getNumberAtoms()) indexi = startAtom;
00740 if(stopAtom >= globalInput.Molecule.getNumberAtoms()) indexj = stopAtom;
00741 scanEnergies(moveE,indexi,indexj,steps,startFrac,stopFrac,0);
00742 }
00743 }
00744 }
00745 }