Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2017 of Haochuan Chen (excluding colvar_UIestimator.h)
3 : Copyright (c) 2017 of Haohao Fu (colvar_UIestimator.h)
4 :
5 : This program is free software: you can redistribute it and/or modify
6 : it under the terms of the GNU Lesser General Public License as published
7 : by the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
14 :
15 : You should have received a copy of the GNU Lesser General Public License
16 : along with this program. If not, see <http://www.gnu.org/licenses/>.
17 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
18 : #ifdef __PLUMED_HAS_BOOST_SERIALIZATION
19 : #include "cltools/CLTool.h"
20 : #include "core/CLToolRegister.h"
21 : #include "config/Config.h"
22 : #include "core/ActionRegister.h"
23 : #include "DRR.h"
24 : #include "tools/Tools.h"
25 : #include "tools/Units.h"
26 : #include <boost/archive/binary_iarchive.hpp>
27 : #include <boost/archive/binary_oarchive.hpp>
28 : #include <boost/serialization/vector.hpp>
29 : #include <cstdlib>
30 : #include <fstream>
31 : #include <iostream>
32 : #include <string>
33 :
34 : using namespace PLMD;
35 : using namespace cltools;
36 :
37 : namespace PLMD {
38 : namespace drr {
39 :
40 : //+PLUMEDOC TOOLS drr_tool
41 : /*
42 : - Extract .grad and .count files from the binary output .drrstate
43 : - Merge windows
44 :
45 : ## Examples
46 :
47 : The following command will extract .grad and .count files.
48 :
49 : ```plumed
50 : plumed drr_tool --extract eabf.drrstate
51 : ```
52 :
53 : The following command will merge windows of two .drrstate file, and output the
54 : .grad and .count files.
55 :
56 : ```plumed
57 : plumed drr_tool --merge win1.drrstate,win2.drrstate
58 : ```
59 :
60 : After getting the .grad and .count file, you can do numerical integration by
61 : using abf_integrate tool from
62 : https://github.com/Colvars/colvars/tree/master/colvartools
63 :
64 : ````
65 : abf_integrate eabf.czar.grad
66 : ````
67 :
68 : !!! note "units"
69 :
70 : The abf_integrate in colvartools is in kcal/mol, so it may be better to use --units kcal/mol when running drr_tool
71 :
72 : */
73 : //+ENDPLUMEDOC
74 :
75 : using std::vector;
76 : using std::string;
77 :
78 : class drrtool : public CLTool {
79 : public:
80 : static void registerKeywords(Keywords &keys);
81 : explicit drrtool(const CLToolOptions &co);
82 : int main(FILE *in, FILE *out, Communicator &pc);
83 : void extractdrr(const vector<string> &filename);
84 : void mergewindows(const vector<string> &filename, string outputname);
85 : void calcDivergence(const vector<string> &filename, const string &fmt);
86 7 : string description() const {
87 7 : return "Extract or merge the drrstate files.";
88 : }
89 :
90 : private:
91 : bool verbosity;
92 : Units units;
93 : const string suffix{".drrstate"};
94 : };
95 :
96 21975 : PLUMED_REGISTER_CLTOOL(drrtool, "drr_tool")
97 :
98 7321 : void drrtool::registerKeywords(Keywords &keys) {
99 7321 : CLTool::registerKeywords(keys);
100 7321 : keys.add("optional", "--extract", "Extract drrstate file(s)");
101 7321 : keys.add("optional", "--merge", "Merge eABF windows");
102 7321 : keys.add("optional", "--merge_output", "The output filename of the merged result");
103 7321 : keys.add("optional", "--divergence", "Calculate divergence of gradient field (experimental)");
104 7321 : keys.add("optional","--dump-fmt","( default=%%f ) the format to use to dump the output");
105 7321 : keys.add("compulsory","--units","kj/mol","the units of energy can be kj/mol, kcal/mol, j/mol, eV or the conversion factor from kj/mol");
106 7321 : keys.addFlag("-v", false, "Verbose output");
107 7321 : }
108 :
109 12 : drrtool::drrtool(const CLToolOptions &co) : CLTool(co) {
110 12 : inputdata = inputType::commandline;
111 12 : verbosity = false;
112 12 : }
113 :
114 5 : int drrtool::main(FILE *in, FILE *out, Communicator &pc) {
115 5 : parseFlag("-v", verbosity);
116 5 : vector<string> stateFilesToExtract;
117 : string unitname;
118 5 : parse("--units",unitname);
119 5 : units.setEnergy( unitname );
120 5 : std::string dumpFmt("%.9f");;
121 5 : parse("--dump-fmt", dumpFmt);
122 5 : bool doextract = parseVector("--extract", stateFilesToExtract);
123 5 : if (doextract) {
124 2 : extractdrr(stateFilesToExtract);
125 : }
126 5 : vector<string> stateFilesToMerge;
127 5 : bool domerge = parseVector("--merge", stateFilesToMerge);
128 5 : if (domerge) {
129 : string merge_outputname;
130 2 : parse("--merge_output", merge_outputname);
131 4 : mergewindows(stateFilesToMerge, merge_outputname);
132 : }
133 5 : vector<string> stateFilesToDivergence;
134 5 : bool dodivergence = parseVector("--divergence", stateFilesToDivergence);
135 5 : if (dodivergence) {
136 1 : calcDivergence(stateFilesToDivergence, dumpFmt);
137 : }
138 5 : return 0;
139 10 : }
140 :
141 2 : void drrtool::extractdrr(const vector<string> &filename) {
142 2 : #pragma omp parallel for
143 : for (size_t j = 0; j < filename.size(); ++j) {
144 : std::ifstream in;
145 : in.open(filename[j]);
146 : boost::archive::binary_iarchive ia(in);
147 : long long int step;
148 : vector<double> fict;
149 : vector<double> vfict;
150 : vector<double> vfict_laststep;
151 : vector<double> ffict;
152 : ABF abfgrid;
153 : CZAR czarestimator;
154 : ia >> step >> fict >> vfict >> vfict_laststep >> ffict >> abfgrid >>
155 : czarestimator;
156 : in.close();
157 : abfgrid.setOutputUnit(units.getEnergy());
158 : czarestimator.setOutputUnit(units.getEnergy());
159 : if (verbosity) {
160 : std::cout << "Output units factor: " << units.getEnergy() << '\n';
161 : std::cout << "Dumping information of extended variables..." << '\n';
162 : std::cout << "Step: " << step << '\n';
163 : for (size_t i = 0; i < fict.size(); ++i) {
164 : std::cout << "Dimension[" << i + 1 << "]:\n"
165 : << " Coordinate: " << fict[i] << '\n'
166 : << " Velocity: " << vfict[i] << '\n'
167 : << " Velocity(laststep): " << vfict_laststep[i] << '\n'
168 : << " Force: " << ffict[i] << '\n';
169 : }
170 : std::cout << "Dumping counts and gradients from grids..." << '\n';
171 : }
172 : string outputname(filename[j]);
173 : outputname.resize(outputname.length() - suffix.length());
174 : if (verbosity) {
175 : std::cout << "Writing ABF(naive) estimator files..." << '\n';
176 : }
177 : abfgrid.writeAll(outputname);
178 : if (verbosity) {
179 : std::cout << "Writing CZAR estimator files..." << '\n';
180 : }
181 : czarestimator.writeAll(outputname);
182 : czarestimator.writeZCountZGrad(outputname);
183 : }
184 2 : }
185 :
186 2 : void drrtool::mergewindows(const vector<string> &filename, string outputname) {
187 2 : if (filename.size() < 2) {
188 0 : std::cerr << "ERROR! You need at least two .drrstate file to merge windows!" << std::endl;
189 0 : std::abort();
190 : }
191 : // Read grid into abfs and czars;
192 2 : vector<ABF> abfs;
193 2 : vector<CZAR> czars;
194 6 : for (auto it_fn = filename.begin(); it_fn != filename.end(); ++it_fn) {
195 4 : std::ifstream in;
196 4 : in.open((*it_fn));
197 4 : boost::archive::binary_iarchive ia(in);
198 : long long int step;
199 4 : vector<double> fict;
200 4 : vector<double> vfict;
201 4 : vector<double> vfict_laststep;
202 4 : vector<double> ffict;
203 : ABF abfgrid;
204 : CZAR czarestimator;
205 : ia >> step >> fict >> vfict >> vfict_laststep >> ffict >> abfgrid >>
206 : czarestimator;
207 4 : abfgrid.setOutputUnit(units.getEnergy());
208 : czarestimator.setOutputUnit(units.getEnergy());
209 4 : abfs.push_back(abfgrid);
210 4 : czars.push_back(czarestimator);
211 4 : in.close();
212 8 : }
213 2 : CZAR cmerged = CZAR::mergewindow(czars[0], czars[1]);
214 2 : ABF amerged = ABF::mergewindow(abfs[0], abfs[1]);
215 2 : for (size_t i = 2; i < czars.size(); ++i) {
216 0 : cmerged = CZAR::mergewindow(cmerged, czars[i]);
217 0 : amerged = ABF::mergewindow(amerged, abfs[i]);
218 : }
219 2 : if (outputname.empty()) {
220 : // Generate new file name for merged grad and count
221 1 : vector<string> tmp_name = filename;
222 1 : std::transform(std::begin(tmp_name), std::end(tmp_name), std::begin(tmp_name),
223 2 : [&](const string & s) {
224 2 : return s.substr(0, s.find(suffix));
225 : });
226 2 : outputname = std::accumulate(std::begin(tmp_name), std::end(tmp_name), string(""),
227 2 : [](const string & a, const string & b) {
228 4 : return a + b + "+";
229 1 : });
230 1 : outputname.resize(outputname.size() - 1);
231 : std::cerr << "You have not specified an output filename for the merged"
232 1 : << " result, so the default name \"" + outputname
233 2 : << "\" is used here, which may yield unexpected behavior.\n";
234 1 : }
235 2 : cmerged.writeAll(outputname);
236 2 : cmerged.writeZCountZGrad(outputname);
237 2 : amerged.writeAll(outputname);
238 4 : }
239 :
240 1 : void drrtool::calcDivergence(const vector<string> &filename, const string &dumpFmt) {
241 1 : #pragma omp parallel for
242 : for (size_t j = 0; j < filename.size(); ++j) {
243 : std::ifstream in;
244 : in.open(filename[j]);
245 : boost::archive::binary_iarchive ia(in);
246 : long long int step;
247 : vector<double> fict;
248 : vector<double> vfict;
249 : vector<double> vfict_laststep;
250 : vector<double> ffict;
251 : ABF abfgrid;
252 : CZAR czarestimator;
253 : ia >> step >> fict >> vfict >> vfict_laststep >> ffict >> abfgrid >>
254 : czarestimator;
255 : in.close();
256 : abfgrid.setOutputUnit(units.getEnergy());
257 : czarestimator.setOutputUnit(units.getEnergy());
258 : if (verbosity) {
259 : std::cout << "Output units factor: " << units.getEnergy() << '\n';
260 : std::cout << "Dumping information of extended variables..." << '\n';
261 : std::cout << "Step: " << step << '\n';
262 : for (size_t i = 0; i < fict.size(); ++i) {
263 : std::cout << "Dimension[" << i + 1 << "]:\n"
264 : << " Coordinate: " << fict[i] << '\n'
265 : << " Velocity: " << vfict[i] << '\n'
266 : << " Velocity(laststep): " << vfict_laststep[i] << '\n'
267 : << " Force: " << ffict[i] << '\n';
268 : }
269 : std::cout << "Dumping counts and gradients from grids..." << '\n';
270 : }
271 : string outputname(filename[j]);
272 : outputname.resize(outputname.length() - suffix.length());
273 : abfgrid.writeDivergence(outputname, dumpFmt);
274 : czarestimator.writeDivergence(outputname, dumpFmt);
275 : }
276 1 : }
277 :
278 : } // End of namespace
279 : }
280 :
281 : #endif
|