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