1 /*
2 
3 Copyright (C) 2007 Michal Bajdich
4 Copyright (C) 2012 Shuming Hu
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 
20 */
21 
22 #include "Nodes_method.h"
23 #include "qmc_io.h"
24 #include "System.h"
25 #include "Program_options.h"
26 /*!
27 Read the "words" from the method section in the input file
28 via doinput() parsing, and store section information in private
29 variables isoses, resolution, and minmax.
30 Set up MO_matrix and Sample_point objects for wavefunction from input
31 */
read(vector<string> words,unsigned int & pos,Program_options & options)32 void Nodes_method::read(vector <string> words,
33                        unsigned int & pos,
34                        Program_options & options)
35 {
36   pos=0;	//always start from first word
37   doublevar Tres;
38   vector <string> Torbs;
39   vector <string> Tminmax;
40   vector <string> orbtext;
41   vector <string> Tdxyz;
42 
43 
44   allocate(options.systemtext[0], sysprop);
45   sysprop->generateSample(mywalker);
46 
47   allocate(options.twftext[0], sysprop, wfdata);
48   wfdata->generateWavefunction(wf);
49 
50   mywalker->attachObserver(wf);
51 
52   pos=0;
53   if(readsection(words,pos=0,Torbs,"CONTOURS")){
54     //   error("Need CONTOURS in METHOD section");
55   plots.Resize(Torbs.size());
56   for(unsigned int i=0; i<Torbs.size(); i++){
57         plots(i)=atoi(Torbs[i].c_str());
58       }
59   }
60   else {
61     cout <<"WARNING: All electrons are used for scanning!"<<endl;
62     plots.Resize(mywalker->electronSize());
63     for(int i=0; i<plots.GetSize(); i++){
64       plots(i)=i+1;
65       }
66   }
67 
68   pos=0;
69   if(! readvalue(words,pos,Tres,"RESOLUTION"))
70     error("Need RESOLUTION in METHOD section");
71   resolution=Tres;
72 
73 
74   pos=0;
75   minmax.Resize(6);
76   if(readsection(words,pos,Tminmax,"MINMAX")) {
77     if(Tminmax.size() != 6)
78       error("MINMAX needs 6 values");
79     for(unsigned int i=0; i<Tminmax.size(); i++)
80     {
81       minmax(i)=atof(Tminmax[i].c_str());
82     }
83   }
84   else  {
85     minmax=0.0;
86 
87     int nions=sysprop->nIons();
88     Array1 <doublevar> ionpos(3);
89     for(int i=0; i< nions; i++) {
90       sysprop->getIonPos(i,ionpos);
91       for(int d=0; d< 3; d++) {
92         if(ionpos(d) < minmax(2*d)) minmax(2*d) = ionpos(d);
93         if(ionpos(d) > minmax(2*d+1)) minmax(2*d+1)=ionpos(d);
94       }
95     }
96 
97     for(int d=0; d< 3; d++) {
98       minmax(2*d)-=4.0;
99       minmax(2*d+1)+=4.0;
100       cout << "minmax " << minmax(2*d) << " " << minmax(2*d+1) << endl;
101     }
102   }
103 
104 
105 
106 
107   // Makes the Nodes methods use the current implementation of Nodes
108   if(readvalue(words, pos=0, readconfig, "READCONFIG")){
109     Array1 <Config_save_point> config_pos;
110     config_pos.Resize(0);
111     if(readconfig!="") {
112       read_configurations(readconfig, config_pos);
113     }
114     if(config_pos.GetDim(0)<1)
115       error("Could not read a single walker from config file");
116     //take a first one
117     config_pos(0).restorePos(mywalker);
118   }
119   else {
120     mywalker->randomGuess();
121     debug_write(cout, 0, " configs read ", 1,
122                 " configs randomly generated \n");
123   }
124 
125   pos=0;
126   doublemove=false;
127   if( readsection(words,pos,Tdxyz,"DOUBLEMOVES")){
128     doublemove=true;
129     if(plots.GetSize()%2)
130       error("Needs pairs of countours for doublemoves");
131     unsigned int dummy=3*plots.GetSize()/2;
132     if(Tdxyz.size()!=dummy)
133       error("DOUBLEMOVES needs 3 x # of vectors values");
134     dxyz.Resize(plots.GetSize()/2,3);
135     for(int i=0; i<plots.GetSize()/2; i++){
136       for (int j=0; j<3;j++)
137         dxyz(i,j)=atof(Tdxyz[i*3+j].c_str());
138     }
139   }
140 }
141 
142 
run(Program_options & options,ostream & output)143 void Nodes_method::run(Program_options & options, ostream & output)
144 {
145   ofstream os; //for writing to *.plt files
146   string pltfile; //name of plotfile being written
147   string confile; //name of configuration of electrons to be  being written
148   double max_value,min_value;
149   int count;
150   Array1 <doublevar> xyz(3), xyz2(3),
151     resolution_array(3); //position of electron "in" MO
152   Array1 <int> D_array1(3); //dummy array1
153   Array2 <doublevar> oldpos(mywalker->electronSize(),3);
154   Array1 <doublevar> tmp(3);
155   D_array1=0; //sets all 3 components to 0. use as counter for gridpoints
156 
157 
158   D_array1(0)=roundoff((minmax(1)-minmax(0))/resolution);
159   D_array1(1)=roundoff((minmax(3)-minmax(2))/resolution);
160   D_array1(2)=roundoff((minmax(5)-minmax(4))/resolution);
161 
162   resolution_array(0)=(minmax(1)-minmax(0))/(D_array1(0)-1);
163   resolution_array(1)=(minmax(3)-minmax(2))/(D_array1(1)-1);
164   resolution_array(2)=(minmax(5)-minmax(4))/(D_array1(2)-1);
165 
166   Array2 <doublevar> grid(plots.GetSize(),D_array1(0)*D_array1(1)*D_array1(2));
167   Wf_return wfvals(wf->nfunc(), 2); //where wfval fist index labels
168     //wf number ie. ground state
169     // excited state and so on, and second label is for two values, sign and log(wf).
170 
171  //scan electron positions
172   cout << "Using these electron positions:"<<endl;
173   for(int i=0; i<mywalker->electronSize(); i++){
174     mywalker->getElectronPos(i, tmp);
175     cout.precision(5);
176     cout.width(8);
177     cout <<i+1<<" "<<tmp(0)<<" "<<tmp(1)<<" "<<tmp(2)<<endl;
178     for (int d=0;d<3;d++)
179       oldpos(i,d)=tmp(d);
180     //    cout << "pos " << oldpos(i,0) << "   " << oldpos(i,1) << "   " << oldpos(i,2)
181     //     << endl;
182   }
183 
184   //generate .xyz file for gOpenMol to view coordinates
185   pltfile=options.runid + ".xyz";
186   os.open(pltfile.c_str());
187   cout<<"writing to "<<pltfile<<endl;
188   vector <string> atomlabels;
189   sysprop->getAtomicLabels(atomlabels);
190   os<<atomlabels.size()+mywalker->electronSize()<<endl;
191   os<<endl;
192 
193   int spin_up=sysprop->nelectrons(0);
194   //cout << "Up electrons "<<spin_up<<endl;
195 
196 
197   for(unsigned int i=0; i<atomlabels.size(); i++){
198     Array1 <doublevar> pos(3);
199     mywalker->getIonPos(i, pos);
200     os<<atomlabels[i] <<" "<< pos(0)
201     <<" "<<pos(1)
202     <<" "<< pos(2)<<endl;
203   }
204   for(int j=0; j<mywalker->electronSize(); j++){
205     if (j<spin_up) os<<"Eu";
206     else os<<"Ed";
207         // mywalker->getElectronPos(j, pos);
208        os<<" "<< oldpos(j,0)<<" "<<oldpos(j,1) <<" "<< oldpos(j,2)<<endl;
209   }
210   os.close();
211 
212 
213   if (!doublemove) {
214     //calculate value of each molecular orbital at each grid point and store in an Array1
215     // grid values with x=fastest running variable, and z=slowest
216 
217     cout<<"calculating "<<D_array1(0)*D_array1(1)*D_array1(2)
218         <<" grid points"<<endl;
219     cout<<"for "<< plots.GetDim(0) <<" 3D projections of wavefunction"<<endl;
220     count=0;
221     xyz(0)=minmax(0);
222     xyz(1)=minmax(2);
223     xyz(2)=minmax(4); //init elec probe to xmin ymin zmin
224     //Array1 <doublevar> oldpos(3)
225 
226 
227 
228     for(int i=0; i<plots.GetSize(); i++){
229       cout.width(3);
230       cout <<"============================="<<plots(i)
231            <<"=============================="
232            <<endl;
233       count=0;
234       for(int xx=0; xx<D_array1(0);xx++){
235 	xyz(0)=minmax(0)+xx*resolution_array(0);  //move forward on x axis one resolution unit
236 	max_value=min_value=0.0;
237 	cout << "x ";
238         cout.precision(5);
239         cout.width(8);
240         cout<< xyz(0);
241 	for(int yy=0; yy<D_array1(1);yy++){
242           xyz(1)=minmax(2)+yy*resolution_array(1);  //move forward on y axis one resolution unit
243 	  for(int zz=0;zz<D_array1(2);zz++){
244 	    xyz(2)=minmax(4)+zz*resolution_array(2); //move forward on z axis one resolution unit
245 	    // mywalker->getElectronPos(plots(i), oldpos);
246             mywalker->setElectronPos(plots(i)-1,xyz); //move elec#plots(i) to point specified by xyz
247             wf->updateVal(wfdata, mywalker); //update wfdata
248             wf->getVal(wfdata, 0, wfvals); //get wf value
249             const doublevar cutoff=15;
250             if(wfvals.amp(0,0)<cutoff) {
251               grid(i,count)=wfvals.sign(0)*exp(wfvals.amp(0,0));
252             }
253             else { //cut off the maximum value output so that there aren't overflow errors
254               grid(i,count)=wfvals.sign(0)*exp(cutoff);
255             }
256             //grid(i,count)=exp(2.0*wfvals(0,1));//!square of wavefunction
257             if (grid(i,count)>max_value) max_value=grid(i,count);
258             if (grid(i,count)<min_value) min_value=grid(i,count);
259             //  cout << "grid " << grid(i,count)<< " " << xyz(0) << endl;
260 	    count++; //index for cycling through grid points
261           }
262         }
263         cout.setf(ios::scientific| ios:: showpos);
264         cout <<", max. value "<<max_value<<", min. value "<<min_value<< endl;
265         cout.unsetf(ios::scientific| ios:: showpos);
266 
267       }
268       mywalker->setElectronPos(plots(i)-1, oldpos(plots(i)-1));
269     }
270 
271 
272     //Loop through and generate plot files for each orbital requested
273     if(plots.GetSize()<=0)
274       error("Number of requested plots is not a positive number");
275     cout<<"saving data for "<<plots.GetSize()<<" 3D projections of wavefunction"<<endl;
276     for(int i=0; i<plots.GetSize(); i++)
277       {
278         //output to file with orbital number in it
279         char strbuff[40];
280         sprintf(strbuff, "%d", plots(i));
281         confile=pltfile = options.runid;
282         confile += ".orb.";
283         pltfile += ".orb.";
284         pltfile += strbuff;
285         confile += strbuff;
286         pltfile += ".cube"; /*FIGURE OUT HOW TO CONVERT INT TO STRING*/
287         confile += ".xyz";
288 
289         os.open(pltfile.c_str());
290         cout<<"writing to "<<pltfile<<endl;
291 
292         os << "QWalk nodes output\n";
293         os << "Wavefunction single scan with " <<   plots(i) <<" electron"<<endl;
294         int natoms=sysprop->nIons();
295         os << "  " << natoms+ mywalker->electronSize()-1 << "   " << minmax(0) << "   "
296           << minmax(2) << "   " << minmax(4) << endl;
297         os << D_array1(0) << "   " << resolution_array(0) << "  0.0000   0.0000" << endl;
298         os << D_array1(1) << "   0.0000   " << resolution_array(1) << "  0.0000" << endl;
299         os << D_array1(2) << "   0.0000    0.0000    " << resolution_array(2) << endl;
300         Array1 <doublevar> pos(3);
301         for(int at=0; at< natoms; at++) {
302           mywalker->getIonPos(at,pos);
303           os << "   " << mywalker->getIonCharge(at) << "   0.0000    " << pos(0)
304             <<"    " << pos(1) << "   " << pos(2) << endl;
305         }
306         for(int j=0; j<mywalker->electronSize(); j++){
307           if (j!=plots(i)-1){
308             if (j<spin_up) os<<"     3   0.0000    ";
309             else os<<"     3     0.0000    ";
310             os<< oldpos(j,0)<<"   "<<oldpos(j,1)<<"   "<< oldpos(j,2)<<endl;
311           }
312         }
313         os.setf(ios::scientific);
314         for(int j=0; j< D_array1(0)*D_array1(1)*D_array1(2); j++) {
315           os <<setw(16)<<setprecision(8)<<grid(i,j);
316           if(j%6 ==5) os << endl;
317         }
318         os << endl;
319         os.unsetf(ios::scientific);
320         os<<setprecision(6);
321         os.close();
322 
323 
324         /*
325 	  old plt file plots
326         // http://www.csc.fi/gopenmol/developers/plt_format.phtml
327         os<<"3 "; //rank=3 always
328         os<<"2\n"; //dummy variable => "Orbital/density surface"
329         //number of grid points for x, y, & z direction
330         os <<D_array1(2)<<" "<<D_array1(1)<<" "<<D_array1(0)<<endl;
331         os <<minmax(4)<<" "<<minmax(5)<<" "<<minmax(2)<<" "<<minmax(3)
332            <<" "<<minmax(0)<<" "<<minmax(1)<<endl;
333 
334         for(int j=0; j<(D_array1(0)*D_array1(1)*D_array1(2)); j++)
335           os<<grid(i,j)<<endl;
336         os.close();
337 
338         os.open(confile.c_str());
339         cout<<"writing to "<<confile<<endl;
340         Array1 <doublevar> pos(3);
341         sysprop->getAtomicLabels(atomlabels);
342         os<<atomlabels.size()+ mywalker->electronSize()-1 <<endl;
343         os << endl;
344         for(unsigned int j=0; j<atomlabels.size();j++){
345           mywalker->getIonPos(j, pos);
346           os<<atomlabels[j] <<" "<< pos(0)
347             <<" "<<pos(1)
348             <<" "<< pos(2)<<endl;
349         }
350         for(int j=0; j<mywalker->electronSize(); j++){
351           if (j!=plots(i)-1){
352             if (j<spin_up) os<<"Eu";
353             else os<<"Ed";
354             // mywalker->getElectronPos(j, pos);
355             os<<" "<< oldpos(j,0)<<" "<<oldpos(j,1)
356               <<" "<< oldpos(j,2)<<endl;
357           }
358         }
359         os.close();
360 	*/
361 
362       }
363 
364   }
365   else {
366     cout << "Using translation vector(s): "<<endl;
367     for(int i=0;i<dxyz.GetDim(0);i++)
368       cout<<"( "<<dxyz(i,0)<<" , "<<dxyz(i,1)<<" , "<<dxyz(i,2)<<" )"<<endl;
369 
370     for(int i=0; i<plots.GetSize(); i=i+2){
371       count=0;
372       xyz(0)=minmax(0);
373       xyz(1)=minmax(2);
374       xyz(2)=minmax(4); //init elec probe to xmin ymin zmin
375       //Array1 <doublevar> oldpos(3)
376       cout.width(3);
377       cout <<"============================="<<plots(i)<<" and "<<plots(i+1)
378            <<"=============================="
379            <<endl;
380       for(int xx=0; xx<D_array1(0);xx++){
381         max_value=min_value=0.0;
382         xyz(0)=minmax(0)+xx*resolution_array(0);
383         xyz2(0)=xyz(0)+dxyz(i/2,0);
384         cout << "x ";
385         cout.precision(5);
386         cout.width(8);
387         cout<< xyz(0);
388         for(int yy=0; yy<D_array1(1);yy++){
389           xyz(1)=minmax(2)+yy*resolution_array(1);
390           xyz2(1)=xyz(1)+dxyz(i/2,1);
391           for(int zz=0;zz<D_array1(2);zz++){
392             xyz(2)=minmax(4)+zz*resolution_array(2);
393             xyz2(2)=xyz(2)+dxyz(i/2,2);
394             // mywalker->getElectronPos(plots(i), oldpos);
395             mywalker->setElectronPos(plots(i)-1,xyz);//move elec#plots(i)
396             //to point specified by xyz
397             mywalker->setElectronPos(plots(i+1)-1,xyz2);//move elec#plots(i)
398             //to point specified by xyz
399             wf->updateVal(wfdata, mywalker); //update wfdata
400             wf->getVal(wfdata, 0, wfvals); //get wf value
401             grid(i,count)=wfvals.sign(0)*exp(wfvals.amp(0,0));
402             //grid(i,count)=exp(2.0*wfvals(0,1));//!square of wavefunction
403             //  cout << "grid " << grid(i,count)<< " " << xyz(0) << endl;
404             if (grid(i,count)>max_value) max_value=grid(i,count);
405             if (grid(i,count)<min_value) min_value=grid(i,count);
406 
407             count++; //index for cycling through grid points
408           }
409         }
410         cout.setf(ios::scientific| ios:: showpos);
411         cout <<", max. value "<<max_value<<", min. value "<<min_value<< endl;
412         cout.unsetf(ios::scientific| ios:: showpos);
413       }
414 
415       mywalker->setElectronPos(plots(i)-1, oldpos(plots(i)-1));
416       mywalker->setElectronPos(plots(i+1)-1, oldpos(plots(i+1)-1));
417     }
418 
419     //Loop through and generate plot files for each orbital requested
420     if(plots.GetSize()<=0)
421       error("Number of requested plots is not a positive number");
422     cout<<"saving data for "<<plots.GetSize()<<" 3D projections of wavefunction"<<endl;
423     for(int i=0; i<plots.GetSize(); i=i+2)
424       {
425         char strbuff2[40],strbuff[40];
426         //output to file with orbital number in it
427         sprintf(strbuff, "%d", plots(i));
428         sprintf(strbuff2, "%d", plots(i+1));
429         confile=pltfile = options.runid;
430         confile += ".orb.";
431         pltfile += ".orb.";
432         pltfile += strbuff;
433         confile += strbuff;
434         pltfile += "with";
435         confile += "with";
436         pltfile += strbuff2;
437         confile += strbuff2;
438 
439         pltfile += ".cube"; /*FIGURE OUT HOW TO CONVERT INT TO STRING*/
440         confile += ".xyz";
441 
442         os.open(pltfile.c_str());
443         cout<<"writing to "<<pltfile<<endl;
444 	os << "GOS nodes output\n";
445 	os << "Wave function double scan with "<<   plots(i) <<" & "<<plots(i+1)<<" electrons"<< endl;
446         int natoms=sysprop->nIons();
447         os << "  " << natoms + mywalker->electronSize()-2 << "   " << minmax(0) << "   "
448            << minmax(2) << "   " << minmax(4) << endl;
449         os << D_array1(0) << "   " << resolution_array(0) << "  0.0000   0.0000" << endl;
450         os << D_array1(1) << "   0.0000   " << resolution_array(1) << "  0.0000" << endl;
451         os << D_array1(2) << "   0.0000    0.0000    " << resolution_array(2) << endl;
452         Array1 <doublevar> pos(3);
453         for(int at=0; at< natoms; at++) {
454           mywalker->getIonPos(at,pos);
455           os << "   " << mywalker->getIonCharge(at) << "   0.0000    " << pos(0)
456              <<"    " << pos(1) << "   " << pos(2) << endl;
457         }
458         for(int j=0; j<mywalker->electronSize(); j++){
459           if ((j!=plots(i)-1)&&(j!=plots(i+1)-1)){
460             if (j<spin_up) os<<"    3    0.0000    ";
461             else os<<"    3    0.0000   ";
462             os<< oldpos(j,0)<<"    "<<oldpos(j,1)<<"    "<< oldpos(j,2)<<endl;
463           }
464         }
465 	os.setf(ios::scientific);
466         for(int j=0; j< D_array1(0)*D_array1(1)*D_array1(2); j++) {
467           os << setw(16) << setprecision(8) << grid(i,j);
468           if(j%6 ==5) os << endl;
469         }
470         os << endl;
471 	os.unsetf(ios::scientific);
472 	os<<setprecision(6);
473         os.close();
474 
475         /*
476           old plot to plt file version
477         // http://www.csc.fi/gopenmol/developers/plt_format.phtml
478         os<<"3 "; //rank=3 always
479         os<<"2\n"; //dummy variable => "Orbital/density surface"
480         //number of grid points for x, y, & z direction
481         os <<D_array1(2)<<" "<<D_array1(1)<<" "<<D_array1(0)<<endl;
482         os <<minmax(4)<<" "<<minmax(5)<<" "<<minmax(2)<<" "<<minmax(3)
483            <<" "<<minmax(0)<<" "<<minmax(1)<<endl;
484 
485         for(int j=0; j<(D_array1(0)*D_array1(1)*D_array1(2)); j++)
486           os<<grid(i,j)<<endl;
487         os.close();
488 
489         os.open(confile.c_str());
490         cout<<"writing to "<<confile<<endl;
491         Array1 <doublevar> pos(3);
492         sysprop->getAtomicLabels(atomlabels);
493         os<<atomlabels.size()+ mywalker->electronSize()-2 <<endl;
494         os << endl;
495         for(unsigned int j=0; j<atomlabels.size();j++){
496           mywalker->getIonPos(j, pos);
497           os<<atomlabels[j] <<" "<< pos(0)
498             <<" "<<pos(1)
499             <<" "<< pos(2)<<endl;
500         }
501         for(int j=0; j<mywalker->electronSize(); j++){
502           if ((j!=plots(i)-1)&&(j!=plots(i+1)-1)){
503             if (j<spin_up) os<<"Eu";
504             else os<<"Ed";
505             // mywalker->getElectronPos(j, pos);
506             os<<" "<< oldpos(j,0)<<" "<<oldpos(j,1)
507               <<" "<< oldpos(j,2)<<endl;
508           }
509         }
510         os.close();
511         */
512 
513       }
514   }
515   cout <<"End of Nodes Method"<<endl;
516 }
517 
518 
519 /*!
520 Print information about private variables {plots,resolution,minmax}
521 */
showinfo(ostream & os)522 int Nodes_method::showinfo(ostream & os)
523 {
524    sysprop->showinfo(os);
525     os << endl << endl;
526     os << "                               Wavefunction  "
527        << endl << endl;
528     wfdata->showinfo(os);
529   os<<"#############Nodes_method#################\n";
530   if (doublemove)
531     os <<"Doing doublemoves with"<<endl;
532   os<<"Plots= "<<plots(0);
533   for(int i=1;i<plots.GetSize();i++)
534     os<<", "<<plots(i);
535   os<<endl;
536 
537   if (doublemove){
538     os << "Translation vector(s): "<<endl;
539     for(int i=0;i<dxyz.GetDim(0);i++)
540       os<<"( "<<dxyz(i,0)<<" , "<<dxyz(i,1)<<" , "<<dxyz(i,2)<<" )"<<endl;
541     }
542 
543 
544   os<<"resolution "<<resolution<<endl;
545   os<<"xmin="<<minmax(0)<<" xmax="<<minmax(1)<<endl;
546   os<<"ymin="<<minmax(2)<<" ymax="<<minmax(3)<<endl;
547   os<<"zmin="<<minmax(4)<<" zmax="<<minmax(5)<<endl;
548   os<<"done"<<endl;
549   return 1;
550 }
551