/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 2017 of Haochuan Chen (excluding colvar_UIestimator.h) Copyright (c) 2017 of Haohao Fu (colvar_UIestimator.h) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #ifdef __PLUMED_HAS_BOOST_SERIALIZATION #include "cltools/CLTool.h" #include "cltools/CLToolRegister.h" #include "config/Config.h" #include "core/ActionRegister.h" #include "DRR.h" #include "tools/Tools.h" #include "tools/Units.h" #include #include #include #include #include #include #include using namespace PLMD; using namespace cltools; namespace PLMD { namespace drr { //+PLUMEDOC EABFMOD_TOOLS drr_tool /* - Extract .grad and .count files from the binary output .drrstate - Merge windows \par Examples The following command will extract .grad and .count files. \verbatim plumed drr_tool --extract eabf.drrstate \endverbatim The following command will merge windows of two .drrstate file, and output the .grad and .count files. \verbatim plumed drr_tool --merge win1.drrstate,win2.drrstate \endverbatim After getting the .grad and .count file, you can do numerical integration by using abf_integrate tool from https://github.com/Colvars/colvars/tree/master/colvartools \verbatim abf_integrate eabf.czar.grad \endverbatim \note The abf_integrate in colvartools is in kcal/mol, so it may be better to use --units kcal/mol when running drr_tool */ //+ENDPLUMEDOC using std::vector; using std::string; class drrtool : public CLTool { public: static void registerKeywords(Keywords &keys); explicit drrtool(const CLToolOptions &co); int main(FILE *in, FILE *out, Communicator &pc); void extractdrr(const vector &filename); void mergewindows(const vector &filename, string outputname); void calcDivergence(const vector &filename); string description() const { return "Extract or merge the drrstate files."; } private: bool verbosity; Units units; const string suffix{".drrstate"}; }; PLUMED_REGISTER_CLTOOL(drrtool, "drr_tool") void drrtool::registerKeywords(Keywords &keys) { CLTool::registerKeywords(keys); keys.add("optional", "--extract", "Extract drrstate file(s)"); keys.add("optional", "--merge", "Merge eABF windows"); keys.add("optional", "--merge_output", "The output filename of the merged result"); keys.add("optional", "--divergence", "Calculate divergence of gradient field (experimental)"); 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"); keys.addFlag("-v", false, "Verbose output"); } drrtool::drrtool(const CLToolOptions &co) : CLTool(co) { inputdata = commandline; verbosity = false; } int drrtool::main(FILE *in, FILE *out, Communicator &pc) { parseFlag("-v", verbosity); vector stateFilesToExtract; string unitname; parse("--units",unitname); units.setEnergy( unitname ); bool doextract = parseVector("--extract", stateFilesToExtract); if (doextract) { extractdrr(stateFilesToExtract); } vector stateFilesToMerge; bool domerge = parseVector("--merge", stateFilesToMerge); if (domerge) { string merge_outputname; parse("--merge_output", merge_outputname); mergewindows(stateFilesToMerge, merge_outputname); } vector stateFilesToDivergence; bool dodivergence = parseVector("--divergence", stateFilesToDivergence); if (dodivergence) { calcDivergence(stateFilesToDivergence); } return 0; } void drrtool::extractdrr(const vector &filename) { #pragma omp parallel for for (size_t j = 0; j < filename.size(); ++j) { std::ifstream in; in.open(filename[j]); boost::archive::binary_iarchive ia(in); long long int step; vector fict; vector vfict; vector vfict_laststep; vector ffict; ABF abfgrid; CZAR czarestimator; ia >> step >> fict >> vfict >> vfict_laststep >> ffict >> abfgrid >> czarestimator; in.close(); abfgrid.setOutputUnit(units.getEnergy()); czarestimator.setOutputUnit(units.getEnergy()); if (verbosity) { std::cout << "Output units factor: " << units.getEnergy() << '\n'; std::cout << "Dumping information of extended variables..." << '\n'; std::cout << "Step: " << step << '\n'; for (size_t i = 0; i < fict.size(); ++i) { std::cout << "Dimension[" << i + 1 << "]:\n" << " Coordinate: " << fict[i] << '\n' << " Velocity: " << vfict[i] << '\n' << " Velocity(laststep): " << vfict_laststep[i] << '\n' << " Force: " << ffict[i] << '\n'; } std::cout << "Dumping counts and gradients from grids..." << '\n'; } string outputname(filename[j]); outputname = outputname.substr(0, outputname.length() - suffix.length()); if (verbosity) std::cout << "Writing ABF(naive) estimator files..." << '\n'; abfgrid.writeAll(outputname); if (verbosity) std::cout << "Writing CZAR estimator files..." << '\n'; czarestimator.writeAll(outputname); czarestimator.writeZCount(outputname); } } void drrtool::mergewindows(const vector &filename, string outputname) { if (filename.size() < 2) { std::cerr << "ERROR! You need at least two .drrstate file to merge windows!" << std::endl; std::abort(); } // Read grid into abfs and czars; vector abfs; vector czars; for (auto it_fn = filename.begin(); it_fn != filename.end(); ++it_fn) { std::ifstream in; in.open((*it_fn)); boost::archive::binary_iarchive ia(in); long long int step; vector fict; vector vfict; vector vfict_laststep; vector ffict; ABF abfgrid; CZAR czarestimator; ia >> step >> fict >> vfict >> vfict_laststep >> ffict >> abfgrid >> czarestimator; abfgrid.setOutputUnit(units.getEnergy()); czarestimator.setOutputUnit(units.getEnergy()); abfs.push_back(abfgrid); czars.push_back(czarestimator); in.close(); } CZAR cmerged = CZAR::mergewindow(czars[0], czars[1]); ABF amerged = ABF::mergewindow(abfs[0], abfs[1]); for (size_t i = 2; i < czars.size(); ++i) { cmerged = CZAR::mergewindow(cmerged, czars[i]); amerged = ABF::mergewindow(amerged, abfs[i]); } if (outputname.empty()) { // Generate new file name for merged grad and count vector tmp_name = filename; std::transform(std::begin(tmp_name), std::end(tmp_name), std::begin(tmp_name), [&](string s) {return s.substr(0, s.find(suffix));}); outputname = std::accumulate(std::begin(tmp_name), std::end(tmp_name), string(""), [](const string & a, const string & b) {return a + b + "+";}); outputname = outputname.substr(0, outputname.size() - 1); std::cerr << "You have not specified an output filename for the merged" << " result, so the default name \"" + outputname << "\" is used here, which may yield unexpected behavior.\n"; } cmerged.writeAll(outputname); cmerged.writeZCount(outputname); amerged.writeAll(outputname); } void drrtool::calcDivergence(const vector &filename) { #pragma omp parallel for for (size_t j = 0; j < filename.size(); ++j) { std::ifstream in; in.open(filename[j]); boost::archive::binary_iarchive ia(in); long long int step; vector fict; vector vfict; vector vfict_laststep; vector ffict; ABF abfgrid; CZAR czarestimator; ia >> step >> fict >> vfict >> vfict_laststep >> ffict >> abfgrid >> czarestimator; in.close(); abfgrid.setOutputUnit(units.getEnergy()); czarestimator.setOutputUnit(units.getEnergy()); if (verbosity) { std::cout << "Output units factor: " << units.getEnergy() << '\n'; std::cout << "Dumping information of extended variables..." << '\n'; std::cout << "Step: " << step << '\n'; for (size_t i = 0; i < fict.size(); ++i) { std::cout << "Dimension[" << i + 1 << "]:\n" << " Coordinate: " << fict[i] << '\n' << " Velocity: " << vfict[i] << '\n' << " Velocity(laststep): " << vfict_laststep[i] << '\n' << " Force: " << ffict[i] << '\n'; } std::cout << "Dumping counts and gradients from grids..." << '\n'; } string outputname(filename[j]); outputname = outputname.substr(0, outputname.length() - suffix.length()); abfgrid.writeDivergence(outputname); czarestimator.writeDivergence(outputname); } } } // End of namespace } #endif