LCOV - code coverage report
Current view: top level - drr - drrtool.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 81 85 95.3 %
Date: 2026-11-05 10:19:04 Functions: 12 12 100.0 %

          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

Generated by: LCOV version 1.16