1 /*
2 
3 Copyright (C) 2007 Lucas K. Wagner
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 
19 */
20 
21 
22 #ifndef POSTPROCESS_METHOD_H_INCLUDED
23 #define POSTPROCESS_METHOD_H_INCLUDED
24 
25 #include <vector>
26 #include <fstream>
27 #include <math.h>
28 #include <stdlib.h>
29 #include "Qmc_method.h"
30 #include "qmc_io.h"
31 #include "Array.h"
32 #include "MO_matrix.h"
33 #include "Sample_point.h"
34 #include "Properties.h"
35 class System;
36 class Wavefunction;
37 class Program_options;
38 
39 /*!
40 In DMC, use the option SAVE_TRACE filename to save the walker positions and their weights to a binary file (called 'filename') once every block.
41 These walkers should be decorrelated, so they can now be treated independently.
42 
43 Now, you can use
44 method { POSTPROCESS
45   READCONFIG filename
46   AVERAGE { ... }
47   DENSITY { ... }
48   }
49   include sys
50   trialfunc { .. }
51 
52 to take any averages that you'd like.
53 
54 There are some tradeoffs with this method. First, since we only save the walkers occasionally, the error bars will b
55 e larger than if you had put AVERAGE into the DMC section directly. However, if the AVERAGE takes some time to evalu
56 ate, such as the 2-RDM, then you will also not waste time evaluating the object on highly correlated walkers. You sh
57 ould use this scheme when one of the following is true:
58 a) You're not sure what averaging variables you want when the DMC calculation is run.
59 b) The averaging variables you want dominate the cost of the DMC calculation (2-RDM!)
60 
61 Otherwise, evaluation on the fly (AVERAGE in the DMC section) is better.
62 
63  */
64 class Postprocess_method : public Qmc_method
65 {
66 public:
67   void read(vector <string> words,
68             unsigned int & pos,
69             Program_options & options);
70   void run(Program_options & options, ostream & output);
71   int showinfo(ostream & os);
Postprocess_method()72   Postprocess_method():sys(NULL),pseudo(NULL),wfdata(NULL) {}
~Postprocess_method()73   ~Postprocess_method()
74   {
75     if(sys != NULL) delete sys;
76     if(pseudo!=NULL) delete pseudo;
77     if(wfdata!=NULL) delete wfdata;
78     for(int i=0; i< densplt.GetDim(0); i++) delete densplt(i);
79     for(int i=0; i< average_var.GetDim(0); i++) delete average_var(i);
80   }
81 
82 private:
83   int gen_point(Wavefunction * wf, Sample_point * sample,
84     Config_save_point & configpos, doublevar weight, Properties_point & pt);
85   int worker(Wavefunction * wf, Sample_point * sample);
86   int master(Wavefunction * wf, Sample_point * sample,FILE * f,ostream & );
87 
88 
89 
90   int nskip;
91   bool evaluate_energy;
92   bool json_output;
93   string json_file;
94   System * sys;
95   Pseudopotential * pseudo;
96   Wavefunction_data * wfdata;
97   Array1 < Local_density_accumulator *> densplt;
98   Array1 < Average_generator * > average_var;
99   string configfile;
100 };
101 
102 //----------------------------------------------------------------------
103 
104 
weighted_update_average(doublevar weight,doublevar xnew,doublevar & xavg,doublevar & xvar,doublevar & totweight)105 inline void weighted_update_average(doublevar weight, doublevar xnew,doublevar &  xavg, doublevar &  xvar, doublevar & totweight)
106   {
107   doublevar nweight=totweight+weight;
108   doublevar navg=(weight*xnew+totweight*xavg)/nweight;
109   doublevar nvar=(weight*xnew*xnew+totweight*(xavg*xavg+xvar))/nweight-navg*navg;
110   xavg=navg;
111   xvar=nvar;
112 }
113 //----------------------------------------------------------------------
114 
115 class Postprocess_average {
116 public:
Postprocess_average(int navg)117   Postprocess_average(int navg) {
118     avgavg.Resize(navg);
119     varavg.Resize(navg);
120     avgen=varen=avgwt=varwt=0.0;
121     npoints=0;
122   }
123 
124   //---------------------
125 
update_average(Properties_point & pt)126   void update_average(Properties_point & pt) {
127    // cout << "here" << endl;
128     weighted_update_average(pt.weight(0),pt.energy(0),avgen,varen,avgwt);
129     for(int i=0; i< avgavg.GetDim(0); i++) {
130       //cout << "resizing avg " <<i << " avgavg " << avgavg.GetDim(0)
131        // << " varavg " << varavg.GetDim(0) << " pt.avgrets "<< pt.avgrets.GetDim(0) << " "
132        // << pt.avgrets.GetDim(1) << endl;
133       if(avgavg(i).vals.GetDim(0)==0) {
134         avgavg(i)=pt.avgrets(0,i);
135         varavg(i)=pt.avgrets(0,i);
136         avgavg(i).vals=0;
137         varavg(i).vals=0;
138       }
139       //cout << "updaing average " << endl;
140       for(int j=0; j< pt.avgrets(0,i).vals.GetDim(0); j++) {
141         weighted_update_average(pt.weight(0),pt.avgrets(0,i).vals(j),avgavg(i).vals(j),varavg(i).vals(j),avgwt);
142       }
143     }
144     avgwt+=pt.weight(0);
145     npoints++;
146   }
147   //---------------------
print(Array1<Average_generator * > average_var,ostream & output)148   void print(Array1<Average_generator *> average_var,ostream & output) {
149     output.precision(10);
150     output << "Averages" << endl;
151     if(avgen!=0 and varen!=0)
152       output << "total_energy " << avgen << " +/- " << sqrt(varen/npoints) << " (sigma " << sqrt(varen) << ") "<< endl;
153     output << "weight " << avgwt/npoints << endl;
154     for(int i=0; i< avgavg.GetDim(0); i++) {
155       for(int j=0; j< varavg(i).vals.GetDim(0); j++)
156         varavg(i).vals(j)=sqrt(varavg(i).vals(j)/npoints);
157       average_var(i)->write_summary(avgavg(i),varavg(i),output);
158     }
159 
160   }
161 
162   //---------------------
JsonOutput(Array1<Average_generator * > & average_var,ostream & os)163   void JsonOutput(Array1<Average_generator *> & average_var,
164                   ostream & os) {
165     os.precision(14);
166     os << "{ \"label\":\"postprocess\"," << endl;
167     os << "\"npoints\":" << npoints << "," << endl;
168     os << "\"properties\":{"<< endl;
169     if(avgen!=0 and varen!=0) {
170       os << "\"energy\": { " << endl;
171       os << "\"value\": [ " << avgen << " ]," << endl;
172       os << "\"error\": [ " << sqrt(varen/npoints) << " ]," << endl;
173       os << "\"sigma\": [ " << sqrt(varen) << " ]" << endl;
174       os << "}" << endl;
175     }
176     for(int i=0; i< average_var.GetDim(0); i++) {
177       if(i!=0 or (avgen!=0 and varen!=0) )
178         os << "," << endl;
179       average_var(i)->jsonOutput(avgavg(i),varavg(i), os);
180     }
181 
182     os <<"}"<< endl;
183     os << "}" << endl;
184 
185 
186   }
187 private:
188   doublevar avgen,varen,avgwt,varwt;
189   long int npoints;
190   Array1 <Average_return> avgavg, varavg;
191 
192 };
193 
194 #endif //POSTPROCESS_METHOD_H_INCLUDED
195 //------------------------------------------------------------------------
196