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 "cltools/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 EABFMOD_TOOLS drr_tool 41 : /* 42 : - Extract .grad and .count files from the binary output .drrstate 43 : - Merge windows 44 : 45 : \par Examples 46 : 47 : The following command will extract .grad and .count files. 48 : \verbatim 49 : plumed drr_tool --extract eabf.drrstate 50 : \endverbatim 51 : 52 : The following command will merge windows of two .drrstate file, and output the 53 : .grad and .count files. 54 : \verbatim 55 : plumed drr_tool --merge win1.drrstate,win2.drrstate 56 : \endverbatim 57 : 58 : After getting the .grad and .count file, you can do numerical integration by 59 : using abf_integrate tool from 60 : https://github.com/Colvars/colvars/tree/master/colvartools 61 : \verbatim 62 : abf_integrate eabf.czar.grad 63 : \endverbatim 64 : \note 65 : The abf_integrate in colvartools is in kcal/mol, so it may be better to use --units kcal/mol when running drr_tool 66 : 67 : */ 68 : //+ENDPLUMEDOC 69 : 70 : using std::vector; 71 : using std::string; 72 : 73 12 : class drrtool : public CLTool { 74 : public: 75 : static void registerKeywords(Keywords &keys); 76 : explicit drrtool(const CLToolOptions &co); 77 : int main(FILE *in, FILE *out, Communicator &pc); 78 : void extractdrr(const vector<string> &filename); 79 : void mergewindows(const vector<string> &filename); 80 : void calcDivergence(const vector<string> &filename); 81 0 : string description() const { return "Extract or merge the drrstate files."; } 82 : 83 : private: 84 : bool verbosity; 85 : Units units; 86 : const string suffix{".drrstate"}; 87 : }; 88 : 89 7840 : PLUMED_REGISTER_CLTOOL(drrtool, "drr_tool") 90 : 91 1958 : void drrtool::registerKeywords(Keywords &keys) { 92 1958 : CLTool::registerKeywords(keys); 93 7832 : keys.add("optional", "--extract", "Extract drrstate file(s)"); 94 7832 : keys.add("optional", "--merge", "Merge eABF windows"); 95 7832 : keys.add("optional", "--divergence", "Calculate divergence of gradient field (experimental)"); 96 9790 : 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"); 97 5874 : keys.addFlag("-v", false, "Verbose output"); 98 1958 : } 99 : 100 4 : drrtool::drrtool(const CLToolOptions &co) : CLTool(co) { 101 4 : inputdata = commandline; 102 4 : verbosity = false; 103 4 : } 104 : 105 4 : int drrtool::main(FILE *in, FILE *out, Communicator &pc) { 106 8 : parseFlag("-v", verbosity); 107 : vector<string> stateFilesToExtract; 108 : string unitname; 109 8 : parse("--units",unitname); 110 4 : units.setEnergy( unitname ); 111 8 : bool doextract = parseVector("--extract", stateFilesToExtract); 112 4 : if (doextract) { 113 2 : extractdrr(stateFilesToExtract); 114 : } 115 4 : vector<string> stateFilesToMerge; 116 8 : bool domerge = parseVector("--merge", stateFilesToMerge); 117 4 : if (domerge) { 118 1 : mergewindows(stateFilesToMerge); 119 : } 120 4 : vector<string> stateFilesToDivergence; 121 8 : bool dodivergence = parseVector("--divergence", stateFilesToDivergence); 122 4 : if (dodivergence) { 123 1 : calcDivergence(stateFilesToDivergence); 124 : } 125 4 : return 0; 126 : } 127 : 128 2 : void drrtool::extractdrr(const vector<string> &filename) { 129 6 : #pragma omp parallel for 130 : for (size_t j = 0; j < filename.size(); ++j) { 131 2 : std::ifstream in; 132 2 : in.open(filename[j]); 133 2 : boost::archive::binary_iarchive ia(in); 134 : long long int step; 135 : vector<double> fict; 136 : vector<double> vfict; 137 : vector<double> vfict_laststep; 138 : vector<double> ffict; 139 2 : ABF abfgrid; 140 : CZAR czarestimator; 141 : ia >> step >> fict >> vfict >> vfict_laststep >> ffict >> abfgrid >> 142 : czarestimator; 143 2 : in.close(); 144 2 : abfgrid.setOutputUnit(units.getEnergy()); 145 2 : czarestimator.setOutputUnit(units.getEnergy()); 146 2 : if (verbosity) { 147 1 : std::cout << "Output units factor: " << units.getEnergy() << '\n'; 148 1 : std::cout << "Dumping information of extended variables..." << '\n'; 149 1 : std::cout << "Step: " << step << '\n'; 150 3 : for (size_t i = 0; i < fict.size(); ++i) { 151 2 : std::cout << "Dimension[" << i + 1 << "]:\n" 152 2 : << " Coordinate: " << fict[i] << '\n' 153 2 : << " Velocity: " << vfict[i] << '\n' 154 2 : << " Velocity(laststep): " << vfict_laststep[i] << '\n' 155 2 : << " Force: " << ffict[i] << '\n'; 156 : } 157 1 : std::cout << "Dumping counts and gradients from grids..." << '\n'; 158 : } 159 2 : string outputname(filename[j]); 160 4 : outputname = outputname.substr(0, outputname.length() - suffix.length()); 161 2 : if (verbosity) 162 1 : std::cout << "Writing ABF(naive) estimator files..." << '\n'; 163 2 : abfgrid.writeAll(outputname); 164 2 : if (verbosity) 165 1 : std::cout << "Writing CZAR estimator files..." << '\n'; 166 2 : czarestimator.writeAll(outputname); 167 4 : czarestimator.writeZCount(outputname); 168 : } 169 2 : } 170 : 171 1 : void drrtool::mergewindows(const vector<string> &filename) { 172 1 : if (filename.size() < 2) { 173 0 : std::cerr << "ERROR! You need at least two .drrstate file to merge windows!" << std::endl; 174 0 : std::abort(); 175 : } 176 : // Read grid into abfs and czars; 177 : vector<ABF> abfs; 178 1 : vector<CZAR> czars; 179 4 : for (auto it_fn = filename.begin(); it_fn != filename.end(); ++it_fn) { 180 2 : std::ifstream in; 181 2 : in.open((*it_fn)); 182 2 : boost::archive::binary_iarchive ia(in); 183 : long long int step; 184 : vector<double> fict; 185 : vector<double> vfict; 186 : vector<double> vfict_laststep; 187 : vector<double> ffict; 188 2 : ABF abfgrid; 189 : CZAR czarestimator; 190 : ia >> step >> fict >> vfict >> vfict_laststep >> ffict >> abfgrid >> 191 : czarestimator; 192 2 : abfgrid.setOutputUnit(units.getEnergy()); 193 : czarestimator.setOutputUnit(units.getEnergy()); 194 2 : abfs.push_back(abfgrid); 195 2 : czars.push_back(czarestimator); 196 2 : in.close(); 197 2 : } 198 1 : CZAR cmerged = CZAR::mergewindow(czars[0], czars[1]); 199 2 : ABF amerged = ABF::mergewindow(abfs[0], abfs[1]); 200 1 : for (size_t i = 2; i < czars.size(); ++i) { 201 0 : cmerged = CZAR::mergewindow(cmerged, czars[i]); 202 0 : amerged = ABF::mergewindow(amerged, abfs[i]); 203 : } 204 : // Generate new file name for merged grad and count 205 2 : vector<string> tmp_name = filename; 206 6 : std::transform(std::begin(tmp_name), std::end(tmp_name), std::begin(tmp_name), [&](string s) {return s.substr(0, s.find(suffix));}); 207 7 : string mergename = std::accumulate(std::begin(tmp_name), std::end(tmp_name), string(""), [](string a, string b) {return a + b + "+";}); 208 2 : mergename = mergename.substr(0, mergename.size() - 1); 209 1 : cmerged.writeAll(mergename); 210 1 : cmerged.writeZCount(mergename); 211 2 : amerged.writeAll(mergename); 212 1 : } 213 : 214 1 : void drrtool::calcDivergence(const vector<string> &filename) { 215 3 : #pragma omp parallel for 216 : for (size_t j = 0; j < filename.size(); ++j) { 217 1 : std::ifstream in; 218 1 : in.open(filename[j]); 219 1 : boost::archive::binary_iarchive ia(in); 220 : long long int step; 221 : vector<double> fict; 222 : vector<double> vfict; 223 : vector<double> vfict_laststep; 224 : vector<double> ffict; 225 1 : ABF abfgrid; 226 : CZAR czarestimator; 227 : ia >> step >> fict >> vfict >> vfict_laststep >> ffict >> abfgrid >> 228 : czarestimator; 229 1 : in.close(); 230 1 : abfgrid.setOutputUnit(units.getEnergy()); 231 1 : czarestimator.setOutputUnit(units.getEnergy()); 232 1 : if (verbosity) { 233 0 : std::cout << "Output units factor: " << units.getEnergy() << '\n'; 234 0 : std::cout << "Dumping information of extended variables..." << '\n'; 235 0 : std::cout << "Step: " << step << '\n'; 236 0 : for (size_t i = 0; i < fict.size(); ++i) { 237 0 : std::cout << "Dimension[" << i + 1 << "]:\n" 238 0 : << " Coordinate: " << fict[i] << '\n' 239 0 : << " Velocity: " << vfict[i] << '\n' 240 0 : << " Velocity(laststep): " << vfict_laststep[i] << '\n' 241 0 : << " Force: " << ffict[i] << '\n'; 242 : } 243 0 : std::cout << "Dumping counts and gradients from grids..." << '\n'; 244 : } 245 1 : string outputname(filename[j]); 246 2 : outputname = outputname.substr(0, outputname.length() - suffix.length()); 247 1 : abfgrid.writeDivergence(outputname); 248 2 : czarestimator.writeDivergence(outputname); 249 : } 250 1 : } 251 : 252 : } // End of namespace 253 5874 : } 254 : 255 : #endif