LCOV - code coverage report
Current view: top level - function - FuncSumHills.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 324 384 84.4 %
Date: 2026-03-30 11:13:23 Functions: 10 12 83.3 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "core/ActionRegister.h"
      23             : #include "Function.h"
      24             : #include "tools/Exception.h"
      25             : #include "tools/Communicator.h"
      26             : #include "tools/BiasRepresentation.h"
      27             : #include "tools/KernelFunctions.h"
      28             : #include "tools/File.h"
      29             : #include "tools/Tools.h"
      30             : #include "tools/Stopwatch.h"
      31             : #include "tools/Grid.h"
      32             : 
      33             : namespace PLMD {
      34             : namespace function {
      35             : 
      36             : 
      37             : //+PLUMEDOC FUNCTION FUNCSUMHILLS
      38             : /*
      39             : This function is intended to be called by the command line tool sum_hills.  It is meant to integrate a HILLS file or an HILLS file interpreted as a histogram in a variety of ways. It is, therefore, not expected that you use this during your dynamics (it will crash!)
      40             : 
      41             : In the future one could implement periodic integration during the metadynamics
      42             : or straightforward MD as a tool to check convergence
      43             : 
      44             : \par Examples
      45             : 
      46             : There are currently no examples for this keyword.
      47             : 
      48             : */
      49             : //+ENDPLUMEDOC
      50             : 
      51          14 : class FilesHandler {
      52             :   std::vector <std::string> filenames;
      53             :   std::vector <std::unique_ptr<IFile>>  ifiles;
      54             :   Action *action;
      55             :   Log *log;
      56             :   bool parallelread;
      57             :   unsigned beingread;
      58             :   bool isopen;
      59             : public:
      60             :   FilesHandler(const std::vector<std::string> &filenames, const bool &parallelread,  Action &myaction, Log &mylog);
      61             :   bool readBunch(BiasRepresentation *br, int stride);
      62             :   bool scanOneHill(BiasRepresentation *br, IFile *ifile );
      63             :   void getMinMaxBin(const std::vector<Value*> & vals, Communicator &cc, std::vector<double> &vmin, std::vector<double> &vmax, std::vector<unsigned> &vbin);
      64             :   void getMinMaxBin(const std::vector<Value*> & vals, Communicator &cc, std::vector<double> &vmin, std::vector<double> &vmax, std::vector<unsigned> &vbin, const std::vector<double> &histosigma);
      65             : };
      66          14 : FilesHandler::FilesHandler(const std::vector<std::string> &filenames, const bool &parallelread, Action &action, Log &mylog ):filenames(filenames),log(&mylog),parallelread(parallelread),beingread(0),isopen(false) {
      67          14 :   this->action=&action;
      68          29 :   for(unsigned i=0; i<filenames.size(); i++) {
      69             :     auto ifile=Tools::make_unique<IFile>();
      70          15 :     ifile->link(action);
      71          15 :     plumed_massert((ifile->FileExist(filenames[i])), "the file "+filenames[i]+" does not exist " );
      72          15 :     ifiles.emplace_back(std::move(ifile));
      73          15 :   }
      74             : 
      75          14 : }
      76             : 
      77             : // note that the FileHandler is completely transparent respect to the biasrepresentation
      78             : // no check are made at this level
      79          15 : bool FilesHandler::readBunch(BiasRepresentation *br, int stride = -1) {
      80             :   bool morefiles;
      81             :   morefiles=true;
      82          15 :   if(parallelread) {
      83           0 :     (*log)<<"  doing parallelread \n";
      84           0 :     plumed_merror("parallelread is not yet implemented !!!");
      85             :   } else {
      86          15 :     (*log)<<"  doing serialread \n";
      87             :     // read one by one hills
      88             :     // is the type defined? if not, assume it is a gaussian
      89             :     IFile *ff;
      90          15 :     ff=ifiles[beingread].get();
      91          15 :     if(!isopen) {
      92          14 :       (*log)<<"  opening file "<<filenames[beingread]<<"\n";
      93          14 :       ff->open(filenames[beingread]);
      94          14 :       isopen=true;
      95             :     }
      96          15 :     int n=0;
      97             :     while(true) {
      98             :       bool fileisover=true;
      99        5578 :       while(scanOneHill(br,ff)) {
     100             :         // here do the dump if needed
     101        5563 :         n=br->getNumberOfKernels();
     102        5563 :         if(stride>0 && n%stride==0 && n!=0  ) {
     103           1 :           (*log)<<"  done with this chunk: now with "<<n<<" kernels  \n";
     104             :           fileisover=false;
     105             :           break;
     106             :         }
     107             :       }
     108             :       if(fileisover) {
     109          15 :         (*log)<<"  closing file "<<filenames[beingread]<<"\n";
     110          15 :         ff->close();
     111          15 :         isopen=false;
     112          15 :         (*log)<<"  now total "<<br->getNumberOfKernels()<<" kernels \n";
     113          15 :         beingread++;
     114          15 :         if(beingread<ifiles.size()) {
     115             :           ff=ifiles[beingread].get();
     116           1 :           ff->open(filenames[beingread]);
     117           1 :           (*log)<<"  opening file "<<filenames[beingread]<<"\n";
     118           1 :           isopen=true;
     119             :         } else {
     120             :           morefiles=false;
     121          14 :           (*log)<<"  final chunk: now with "<<n<<" kernels  \n";
     122             :           break;
     123             :         }
     124             :       }
     125             :       // if there are no more files to read and this file is over then quit
     126             :       if(fileisover && !morefiles) {
     127             :         break;
     128             :       }
     129             :       // if you are in the middle of a file and you are here
     130             :       // then means that you read what you need to read
     131           2 :       if(!fileisover ) {
     132             :         break;
     133             :       }
     134             :     }
     135             :   }
     136          15 :   return morefiles;
     137             : }
     138           4 : void FilesHandler::getMinMaxBin(const std::vector<Value*> & vals, Communicator &cc, std::vector<double> &vmin, std::vector<double> &vmax, std::vector<unsigned> &vbin) {
     139             :   // create the representation (no grid)
     140           4 :   BiasRepresentation br(vals,cc);
     141             :   // read all the kernels
     142           4 :   readBunch(&br);
     143             :   // loop over the kernels and get the support
     144           4 :   br.getMinMaxBin(vmin,vmax,vbin);
     145           4 : }
     146           1 : void FilesHandler::getMinMaxBin(const std::vector<Value*> & vals, Communicator &cc, std::vector<double> &vmin, std::vector<double> &vmax, std::vector<unsigned> &vbin, const std::vector<double> &histosigma) {
     147           1 :   BiasRepresentation br(vals,cc,histosigma);
     148             :   // read all the kernels
     149           1 :   readBunch(&br);
     150             :   // loop over the kernels and get the support
     151           1 :   br.getMinMaxBin(vmin,vmax,vbin);
     152             :   //for(unsigned i=0;i<vals.size();i++){cerr<<"XXX "<<vmin[i]<<" "<<vmax[i]<<" "<<vbin[i]<<"\n";}
     153           1 : }
     154        5578 : bool FilesHandler::scanOneHill(BiasRepresentation *br, IFile *ifile ) {
     155             :   double dummy;
     156       11156 :   if(ifile->scanField("time",dummy)) {
     157             :     //(*log)<<"   scanning one hill: "<<dummy<<" \n";
     158       11126 :     if(ifile->FieldExist("biasf")) {
     159       11126 :       ifile->scanField("biasf",dummy);
     160             :     }
     161       11126 :     if(ifile->FieldExist("clock")) {
     162           0 :       ifile->scanField("clock",dummy);
     163             :     }
     164             :     // keep this intermediate function in case you need to parse more data in the future
     165        5563 :     br->pushKernel(ifile);
     166             :     //(*log)<<"  read hill\n";
     167        5563 :     if(br->hasSigmaInInput()) {
     168        1092 :       ifile->allowIgnoredFields();
     169             :     }
     170        5563 :     ifile->scanField();
     171        5563 :     return true;
     172             :   } else {
     173             :     return false;
     174             :   }
     175             : }
     176             : 
     177             : 
     178         900 : double  mylog( double v1 ) {
     179         900 :   return std::log(v1);
     180             : }
     181             : 
     182        1800 : double  mylogder( double v1 ) {
     183        1800 :   return 1./v1;
     184             : }
     185             : 
     186             : 
     187             : 
     188             : class FuncSumHills :
     189             :   public Function {
     190             :   std::vector<std::string> hillsFiles,histoFiles;
     191             :   std::vector<std::string> proj;
     192             :   int initstride;
     193             :   bool iscltool,integratehills,integratehisto,parallelread;
     194             :   bool negativebias;
     195             :   bool nohistory;
     196             :   bool minTOzero;
     197             :   bool doInt;
     198             :   double lowI_;
     199             :   double uppI_;
     200             :   double beta;
     201             :   std::string outhills,outhisto,fmt;
     202             :   std::unique_ptr<BiasRepresentation> biasrep;
     203             :   std::unique_ptr<BiasRepresentation> historep;
     204             : public:
     205             :   explicit FuncSumHills(const ActionOptions&);
     206             :   void calculate() override; // this probably is not needed
     207             :   bool checkFilesAreExisting(const std::vector<std::string> & hills );
     208             :   static void registerKeywords(Keywords& keys);
     209             : };
     210             : 
     211             : PLUMED_REGISTER_ACTION(FuncSumHills,"FUNCSUMHILLS")
     212             : 
     213          13 : void FuncSumHills::registerKeywords(Keywords& keys) {
     214          13 :   Function::registerKeywords(keys);
     215          13 :   keys.use("ARG");
     216          26 :   keys.add("optional","HILLSFILES"," source file for hills creation(may be the same as HILLS)"); // this can be a vector!
     217          26 :   keys.add("optional","HISTOFILES"," source file for histogram creation(may be the same as HILLS)"); // also this can be a vector!
     218          26 :   keys.add("optional","HISTOSIGMA"," sigmas for binning when the histogram correction is needed    ");
     219          26 :   keys.add("optional","PROJ"," only with sumhills: the projection on the CVs");
     220          26 :   keys.add("optional","KT"," only with sumhills: the kt factor when projection on CVs");
     221          26 :   keys.add("optional","GRID_MIN","the lower bounds for the grid");
     222          26 :   keys.add("optional","GRID_MAX","the upper bounds for the grid");
     223          26 :   keys.add("optional","GRID_BIN","the number of bins for the grid");
     224          26 :   keys.add("optional","GRID_SPACING","the approximate grid spacing (to be used as an alternative or together with GRID_BIN)");
     225          26 :   keys.add("optional","INTERVAL","set one dimensional INTERVAL");
     226          26 :   keys.add("optional","OUTHILLS"," output file for hills ");
     227          26 :   keys.add("optional","OUTHISTO"," output file for histogram ");
     228          26 :   keys.add("optional","INITSTRIDE"," stride if you want an initial dump ");
     229          26 :   keys.add("optional","STRIDE"," stride when you do it on the fly ");
     230          26 :   keys.addFlag("ISCLTOOL",false,"use via plumed command line: calculate at read phase and then go");
     231          26 :   keys.addFlag("PARALLELREAD",false,"read parallel HILLS file");
     232          26 :   keys.addFlag("NEGBIAS",false,"dump  negative bias ( -bias )   instead of the free energy: needed in well tempered with flexible hills ");
     233          26 :   keys.addFlag("NOHISTORY",false,"to be used with INITSTRIDE:  it splits the bias/histogram in pieces without previous history  ");
     234          26 :   keys.addFlag("MINTOZERO",false,"translate the resulting bias/histogram to have the minimum to zero  ");
     235          26 :   keys.add("optional","FMT","the format that should be used to output real numbers");
     236          13 :   keys.setValueDescription("a scalar");
     237          13 : }
     238             : 
     239           9 : FuncSumHills::FuncSumHills(const ActionOptions&ao):
     240             :   Action(ao),
     241             :   Function(ao),
     242           9 :   initstride(-1),
     243           9 :   iscltool(false),
     244           9 :   integratehills(false),
     245           9 :   integratehisto(false),
     246           9 :   parallelread(false),
     247           9 :   negativebias(false),
     248           9 :   nohistory(false),
     249           9 :   minTOzero(false),
     250           9 :   doInt(false),
     251           9 :   lowI_(-1.),
     252           9 :   uppI_(-1.),
     253           9 :   beta(-1.),
     254           9 :   fmt("%14.9f") {
     255             : 
     256             :   // format
     257           9 :   parse("FMT",fmt);
     258           9 :   log<<"  Output format is "<<fmt<<"\n";
     259             :   // here read
     260             :   // Grid Stuff
     261             :   std::vector<std::string> gmin;
     262          18 :   parseVector("GRID_MIN",gmin);
     263           9 :   if(gmin.size()!=getNumberOfArguments() && gmin.size()!=0) {
     264           0 :     error("not enough values for GRID_MIN");
     265             :   }
     266           9 :   plumed_massert(gmin.size()==getNumberOfArguments() || gmin.size()==0,"need GRID_MIN argument for this") ;
     267             :   std::vector<std::string> gmax;
     268          18 :   parseVector("GRID_MAX",gmax);
     269           9 :   if(gmax.size()!=getNumberOfArguments() && gmax.size()!=0) {
     270           0 :     error("not enough values for GRID_MAX");
     271             :   }
     272           9 :   plumed_massert(gmax.size()==getNumberOfArguments() || gmax.size()==0,"need GRID_MAX argument for this") ;
     273             :   std::vector<unsigned> gbin;
     274             :   std::vector<double>   gspacing;
     275          18 :   parseVector("GRID_BIN",gbin);
     276           9 :   plumed_massert(gbin.size()==getNumberOfArguments() || gbin.size()==0,"need GRID_BIN argument for this") ;
     277           9 :   if(gbin.size()!=getNumberOfArguments() && gbin.size()!=0) {
     278           0 :     error("not enough values for GRID_BIN");
     279             :   }
     280          18 :   parseVector("GRID_SPACING",gspacing);
     281           9 :   plumed_massert(gspacing.size()==getNumberOfArguments() || gspacing.size()==0,"need GRID_SPACING argument for this") ;
     282           9 :   if(gspacing.size()!=getNumberOfArguments() && gspacing.size()!=0) {
     283           0 :     error("not enough values for GRID_SPACING");
     284             :   }
     285           9 :   if(gspacing.size()!=0 && gbin.size()==0) {
     286           1 :     log<<"  The number of bins will be estimated from GRID_SPACING\n";
     287           8 :   } else if(gspacing.size()!=0 && gbin.size()!=0) {
     288           0 :     log<<"  You specified both GRID_BIN and GRID_SPACING\n";
     289           0 :     log<<"  The more conservative (highest) number of bins will be used for each variable\n";
     290             :   }
     291           9 :   if(gspacing.size()!=0)
     292           2 :     for(unsigned i=0; i<getNumberOfArguments(); i++) {
     293           1 :       if(gbin.size()==0) {
     294           1 :         gbin.assign(getNumberOfArguments(),1);
     295             :       }
     296             :       double a,b;
     297           1 :       Tools::convert(gmin[i],a);
     298           1 :       Tools::convert(gmax[i],b);
     299           1 :       unsigned n=std::ceil((b-a)/gspacing[i]);
     300           1 :       if(gbin[i]<n) {
     301           1 :         gbin[i]=n;
     302             :       }
     303             :     }
     304             : 
     305             :   // Inteval keyword
     306           9 :   std::vector<double> tmpI(2);
     307          18 :   parseVector("INTERVAL",tmpI);
     308           9 :   if(tmpI.size()!=2&&tmpI.size()!=0) {
     309           0 :     error("both a lower and an upper limits must be provided with INTERVAL");
     310           9 :   } else if(tmpI.size()==2) {
     311           0 :     lowI_=tmpI.at(0);
     312           0 :     uppI_=tmpI.at(1);
     313           0 :     if(getNumberOfArguments()!=1) {
     314           0 :       error("INTERVAL limits correction works only for monodimensional metadynamics!");
     315             :     }
     316           0 :     if(uppI_<lowI_) {
     317           0 :       error("The Upper limit must be greater than the Lower limit!");
     318             :     }
     319           0 :     doInt=true;
     320             :   }
     321           9 :   if(doInt) {
     322           0 :     log << "  Upper and Lower limits boundaries for the bias are activated at " << lowI_ << " - " << uppI_<<"\n";
     323           0 :     log << "  Using the same values as boundaries for the grid if not other value was defined (default: 200 bins)\n";
     324           0 :     std::ostringstream strsmin, strsmax;
     325           0 :     strsmin << lowI_;
     326           0 :     strsmax << uppI_;
     327           0 :     if(gmin.size()==0) {
     328           0 :       gmin.push_back(strsmin.str());
     329             :     }
     330           0 :     if(gmax.size()==0) {
     331           0 :       gmax.push_back(strsmax.str());
     332             :     }
     333           0 :     if(gbin.size()==0) {
     334           0 :       gbin.push_back(200);
     335             :     }
     336           0 :   }
     337             : 
     338             : 
     339             :   // hills file:
     340          18 :   parseVector("HILLSFILES",hillsFiles);
     341           9 :   if(hillsFiles.size()==0) {
     342           1 :     integratehills=false; // default behaviour
     343             :   } else {
     344           8 :     integratehills=true;
     345          17 :     for(unsigned i=0; i<hillsFiles.size(); i++) {
     346           9 :       log<<"  hillsfile  : "<<hillsFiles[i]<<"\n";
     347             :     }
     348             :   }
     349             :   // histo file:
     350          18 :   parseVector("HISTOFILES",histoFiles);
     351           9 :   if(histoFiles.size()==0) {
     352           8 :     integratehisto=false;
     353             :   } else {
     354           1 :     integratehisto=true;
     355           2 :     for(unsigned i=0; i<histoFiles.size(); i++) {
     356           1 :       log<<"  histofile  : "<<histoFiles[i]<<"\n";
     357             :     }
     358             :   }
     359             :   std::vector<double> histoSigma;
     360           9 :   if(integratehisto) {
     361           1 :     parseVector("HISTOSIGMA",histoSigma);
     362           3 :     for(unsigned i=0; i<histoSigma.size(); i++) {
     363           2 :       log<<"  histosigma  : "<<histoSigma[i]<<"\n";
     364             :     }
     365             :   }
     366             : 
     367             :   // needs a projection?
     368             :   proj.clear();
     369           9 :   parseVector("PROJ",proj);
     370           9 :   if(integratehills) {
     371           8 :     plumed_massert(proj.size()<getNumberOfArguments()," The number of projection must be less than the full list of arguments ");
     372             :   }
     373           9 :   if(integratehisto) {
     374           1 :     plumed_massert(proj.size()<=getNumberOfArguments()," The number of projection must be less or equal to the full list of arguments ");
     375             :   }
     376           9 :   if(integratehisto&&proj.size()==0) {
     377           3 :     for(unsigned i=0; i<getNumberOfArguments(); i++) {
     378           2 :       proj.push_back(getPntrToArgument(i)->getName());
     379             :     }
     380             :   }
     381             : 
     382             :   // add some automatic hills width: not in case stride is defined
     383             :   // since when you start from zero the automatic size will be zero!
     384           9 :   if(gmin.size()==0 || gmax.size()==0) {
     385           5 :     log<<"   \n";
     386           5 :     log<<"  No boundaries defined: need to do a prescreening of hills \n";
     387             :     std::vector<Value*> tmphillsvalues, tmphistovalues;
     388           5 :     if(integratehills) {
     389          12 :       for(unsigned i=0; i<getNumberOfArguments(); i++) {
     390           8 :         tmphillsvalues.push_back( getPntrToArgument(i) );
     391             :       }
     392             :     }
     393           5 :     if(integratehisto) {
     394           3 :       for(unsigned i=0; i<getNumberOfArguments(); i++) {
     395           2 :         std::string ss = getPntrToArgument(i)->getName();
     396           6 :         for(unsigned j=0; j<proj.size(); j++) {
     397           4 :           if(proj[j]==ss) {
     398           2 :             tmphistovalues.push_back( getPntrToArgument(i) );
     399             :           }
     400             :         }
     401             :       }
     402             :     }
     403             : 
     404           5 :     if(integratehills) {
     405           4 :       FilesHandler hillsHandler(hillsFiles,parallelread,*this, log);
     406             :       std::vector<double> vmin,vmax;
     407             :       std::vector<unsigned> vbin;
     408           4 :       hillsHandler.getMinMaxBin(tmphillsvalues,comm,vmin,vmax,vbin);
     409           4 :       log<<"  found boundaries from hillsfile: \n";
     410           4 :       gmin.resize(vmin.size());
     411           4 :       gmax.resize(vmax.size());
     412           4 :       if(gbin.size()==0) {
     413           3 :         gbin=vbin;
     414             :       } else {
     415           1 :         log<<"  found nbins in input, this overrides the automatic choice \n";
     416             :       }
     417          12 :       for(unsigned i=0; i<getNumberOfArguments(); i++) {
     418           8 :         Tools::convert(vmin[i],gmin[i]);
     419           8 :         Tools::convert(vmax[i],gmax[i]);
     420           8 :         log<<"  variable "<< getPntrToArgument(i)->getName()<<" min: "<<gmin[i]<<" max: "<<gmax[i]<<" nbin: "<<gbin[i]<<"\n";
     421             :       }
     422             :     }
     423             :     // if at this stage bins are not there then do it with histo
     424           5 :     if(gmin.size()==0) {
     425           1 :       FilesHandler histoHandler(histoFiles,parallelread,*this, log);
     426             :       std::vector<double> vmin,vmax;
     427             :       std::vector<unsigned> vbin;
     428           1 :       histoHandler.getMinMaxBin(tmphistovalues,comm,vmin,vmax,vbin,histoSigma);
     429           1 :       log<<"  found boundaries from histofile: \n";
     430           1 :       gmin.resize(vmin.size());
     431           1 :       gmax.resize(vmax.size());
     432           1 :       if(gbin.size()==0) {
     433           0 :         gbin=vbin;
     434             :       } else {
     435           1 :         log<<"  found nbins in input, this overrides the automatic choice \n";
     436             :       }
     437           3 :       for(unsigned i=0; i<proj.size(); i++) {
     438           2 :         Tools::convert(vmin[i],gmin[i]);
     439           2 :         Tools::convert(vmax[i],gmax[i]);
     440           2 :         log<<"  variable "<< proj[i] <<" min: "<<gmin[i]<<" max: "<<gmax[i]<<" nbin: "<<gbin[i]<<"\n";
     441             :       }
     442             :     }
     443           5 :     log<<"  done!\n";
     444           5 :     log<<"   \n";
     445             :   }
     446             : 
     447             : 
     448           9 :   if( proj.size() != 0 || integratehisto==true  ) {
     449           3 :     parse("KT",beta);
     450           7 :     for(unsigned i=0; i<proj.size(); i++) {
     451           4 :       log<<"  projection "<<i<<" : "<<proj[i]<<"\n";
     452             :     }
     453             :     // this should be only for projection or free energy from histograms
     454           3 :     plumed_massert(beta>0.,"if you make a projection or a histogram correction then you need KT flag!");
     455           3 :     beta=1./beta;
     456           3 :     log<<"  beta is "<<beta<<"\n";
     457             :   }
     458             :   // is a cltool: then you start and then die
     459           9 :   parseFlag("ISCLTOOL",iscltool);
     460             :   //
     461           9 :   parseFlag("NEGBIAS",negativebias);
     462             :   //
     463           9 :   parseFlag("PARALLELREAD",parallelread);
     464             :   // stride
     465           9 :   parse("INITSTRIDE",initstride);
     466             :   // output suffix or names
     467           9 :   if(initstride<0) {
     468           8 :     log<<"  Doing only one integration: no stride \n";
     469             :     outhills="fes.dat";
     470             :     outhisto="histo.dat";
     471             :   } else {
     472             :     outhills="fes_";
     473             :     outhisto="histo_";
     474           1 :     log<<"  Doing integration slices every "<<initstride<<" kernels\n";
     475           1 :     parseFlag("NOHISTORY",nohistory);
     476           1 :     if(nohistory) {
     477           0 :       log<<"  nohistory: each stride block has no memory of the previous block\n";
     478             :     }
     479             :   }
     480           9 :   parseFlag("MINTOZERO",minTOzero);
     481           9 :   if(minTOzero) {
     482           0 :     log<<"  mintozero: bias/histogram will be translated to have the minimum value equal to zero\n";
     483             :   }
     484             :   //what might it be this?
     485             :   // here start
     486             :   // want something right now?? do it and return
     487             :   // your argument is a set of cvs
     488             :   // then you need: a hills / a colvar-like file (to do a histogram)
     489             :   // create a bias representation for this
     490           9 :   if(iscltool) {
     491             : 
     492             :     std::vector<Value*> tmphillsvalues, tmphistovalues;
     493           9 :     if(integratehills) {
     494          23 :       for(unsigned i=0; i<getNumberOfArguments(); i++) {
     495             :         // allocate a new value from the old one: no deriv here
     496             :         // if we are summing hills then all the arguments are needed
     497          15 :         tmphillsvalues.push_back( getPntrToArgument(i) );
     498             :       }
     499             :     }
     500           9 :     if(integratehisto) {
     501           3 :       for(unsigned i=0; i<getNumberOfArguments(); i++) {
     502           2 :         std::string ss = getPntrToArgument(i)->getName();
     503           6 :         for(unsigned j=0; j<proj.size(); j++) {
     504           4 :           if(proj[j]==ss) {
     505           2 :             tmphistovalues.push_back( getPntrToArgument(i) );
     506             :           }
     507             :         }
     508             :       }
     509             :     }
     510             : 
     511             :     // check if the files exists
     512           9 :     if(integratehills) {
     513           8 :       checkFilesAreExisting(hillsFiles);
     514          16 :       biasrep=Tools::make_unique<BiasRepresentation>(tmphillsvalues,comm, gmin, gmax, gbin, doInt, lowI_, uppI_);
     515           8 :       if(negativebias) {
     516           1 :         biasrep->setRescaledToBias(true);
     517           1 :         log<<"  required the -bias instead of the free energy \n";
     518           1 :         if(initstride<0) {
     519             :           outhills="negativebias.dat";
     520             :         } else {
     521             :           outhills="negativebias_";
     522             :         }
     523             :       }
     524             :     }
     525             : 
     526           9 :     parse("OUTHILLS",outhills);
     527           9 :     parse("OUTHISTO",outhisto);
     528           9 :     if(integratehills) {
     529           8 :       log<<"  output file for fes/bias  is :  "<<outhills<<"\n";
     530             :     }
     531           9 :     if(integratehisto) {
     532           1 :       log<<"  output file for histogram is :  "<<outhisto<<"\n";
     533             :     }
     534           9 :     checkRead();
     535             : 
     536           9 :     log<<"\n";
     537           9 :     log<<"  Now calculating...\n";
     538           9 :     log<<"\n";
     539             : 
     540             :     // here it defines the column to be histogrammed, tmpvalues should be only
     541             :     // the list of the collective variable one want to consider
     542           9 :     if(integratehisto) {
     543           1 :       checkFilesAreExisting(histoFiles);
     544           2 :       historep=Tools::make_unique<BiasRepresentation>(tmphistovalues,comm,gmin,gmax,gbin,histoSigma);
     545             :     }
     546             : 
     547             :     // decide how to source hills ( serial/parallel )
     548             :     // here below the input control
     549             :     // say how many hills and it will read them from the
     550             :     // bunch of files provided, will update the representation
     551             :     // of hills (i.e. a list of hills and the associated grid)
     552             : 
     553             :     // decide how to source colvars ( serial parallel )
     554           9 :     std::unique_ptr<FilesHandler> hillsHandler;
     555           9 :     std::unique_ptr<FilesHandler> histoHandler;
     556             : 
     557           9 :     if(integratehills)  {
     558          16 :       hillsHandler=Tools::make_unique<FilesHandler>(hillsFiles,parallelread,*this, log);
     559             :     }
     560           9 :     if(integratehisto)  {
     561           2 :       histoHandler=Tools::make_unique<FilesHandler>(histoFiles,parallelread,*this, log);
     562             :     }
     563             : 
     564             : // Stopwatch is logged when it goes out of scope
     565           9 :     Stopwatch sw(log);
     566             : 
     567             : // Stopwatch is stopped when swh goes out of scope
     568           9 :     auto swh=sw.startStop("0 Summing hills");
     569             : 
     570             :     // read a number of hills and put in the bias representation
     571             :     int nfiles=0;
     572           9 :     bool ibias=integratehills;
     573           9 :     bool ihisto=integratehisto;
     574             :     while(true) {
     575          10 :       if(  integratehills  && ibias  ) {
     576           9 :         if(nohistory) {
     577           0 :           biasrep->clear();
     578           0 :           log<<"  clearing history before reading a new block\n";
     579             :         };
     580           9 :         log<<"  reading hills: \n";
     581           9 :         ibias=hillsHandler->readBunch(biasrep.get(),initstride) ;
     582           9 :         log<<"\n";
     583             :       }
     584             : 
     585          10 :       if(  integratehisto  && ihisto ) {
     586           1 :         if(nohistory) {
     587           0 :           historep->clear();
     588           0 :           log<<"  clearing history before reading a new block\n";
     589             :         };
     590           1 :         log<<"  reading histogram: \n";
     591           1 :         ihisto=histoHandler->readBunch(historep.get(),initstride) ;
     592           1 :         log<<"\n";
     593             :       }
     594             : 
     595             :       // dump: need to project?
     596          10 :       if(proj.size()!=0) {
     597             : 
     598           4 :         if(integratehills) {
     599             : 
     600           3 :           log<<"  Bias: Projecting on subgrid... \n";
     601           3 :           BiasWeight Bw(beta);
     602           3 :           Grid biasGrid=*(biasrep->getGridPtr());
     603           3 :           Grid smallGrid=biasGrid.project(proj,&Bw);
     604           3 :           OFile gridfile;
     605           3 :           gridfile.link(*this);
     606           3 :           std::ostringstream ostr;
     607           3 :           ostr<<nfiles;
     608             :           std::string myout;
     609           3 :           if(initstride>0) {
     610           4 :             myout=outhills+ostr.str()+".dat" ;
     611             :           } else {
     612             :             myout=outhills;
     613             :           }
     614           3 :           log<<"  Bias: Writing subgrid on file "<<myout<<" \n";
     615           3 :           gridfile.open(myout);
     616           3 :           if(minTOzero) {
     617           0 :             smallGrid.setMinToZero();
     618             :           }
     619             :           smallGrid.setOutputFmt(fmt);
     620           3 :           smallGrid.writeToFile(gridfile);
     621           3 :           gridfile.close();
     622           3 :           if(!ibias) {
     623           2 :             integratehills=false;  // once you get to the final bunch just give up
     624             :           }
     625           3 :         }
     626             :         // this should be removed
     627           4 :         if(integratehisto) {
     628             : 
     629           1 :           log<<"  Histo: Projecting on subgrid... \n";
     630           1 :           Grid histoGrid=*(historep->getGridPtr());
     631             : 
     632           1 :           OFile gridfile;
     633           1 :           gridfile.link(*this);
     634           1 :           std::ostringstream ostr;
     635           1 :           ostr<<nfiles;
     636             :           std::string myout;
     637           1 :           if(initstride>0) {
     638           0 :             myout=outhisto+ostr.str()+".dat" ;
     639             :           } else {
     640             :             myout=outhisto;
     641             :           }
     642           1 :           log<<"  Histo: Writing subgrid on file "<<myout<<" \n";
     643           1 :           gridfile.open(myout);
     644             : 
     645           1 :           histoGrid.applyFunctionAllValuesAndDerivatives(&mylog,&mylogder);
     646           1 :           histoGrid.scaleAllValuesAndDerivatives(-1./beta);
     647           1 :           if(minTOzero) {
     648           0 :             histoGrid.setMinToZero();
     649             :           }
     650             :           histoGrid.setOutputFmt(fmt);
     651           1 :           histoGrid.writeToFile(gridfile);
     652             : 
     653           1 :           if(!ihisto) {
     654           1 :             integratehisto=false;  // once you get to the final bunch just give up
     655             :           }
     656           1 :         }
     657             : 
     658             :       } else {
     659             : 
     660           6 :         if(integratehills) {
     661             : 
     662           6 :           Grid biasGrid=*(biasrep->getGridPtr());
     663           6 :           biasGrid.scaleAllValuesAndDerivatives(-1.);
     664             : 
     665           6 :           OFile gridfile;
     666           6 :           gridfile.link(*this);
     667           6 :           std::ostringstream ostr;
     668           6 :           ostr<<nfiles;
     669             :           std::string myout;
     670           6 :           if(initstride>0) {
     671           0 :             myout=outhills+ostr.str()+".dat" ;
     672             :           } else {
     673             :             myout=outhills;
     674             :           }
     675           6 :           log<<"  Writing full grid on file "<<myout<<" \n";
     676           6 :           gridfile.open(myout);
     677             : 
     678           6 :           if(minTOzero) {
     679           0 :             biasGrid.setMinToZero();
     680             :           }
     681             :           biasGrid.setOutputFmt(fmt);
     682           6 :           biasGrid.writeToFile(gridfile);
     683             :           // rescale back prior to accumulate
     684           6 :           if(!ibias) {
     685           6 :             integratehills=false;  // once you get to the final bunch just give up
     686             :           }
     687           6 :         }
     688           6 :         if(integratehisto) {
     689             : 
     690           0 :           Grid histoGrid=*(historep->getGridPtr());
     691             :           // do this if you want a free energy from a grid, otherwise do not
     692           0 :           histoGrid.applyFunctionAllValuesAndDerivatives(&mylog,&mylogder);
     693           0 :           histoGrid.scaleAllValuesAndDerivatives(-1./beta);
     694             : 
     695           0 :           OFile gridfile;
     696           0 :           gridfile.link(*this);
     697           0 :           std::ostringstream ostr;
     698           0 :           ostr<<nfiles;
     699             :           std::string myout;
     700           0 :           if(initstride>0) {
     701           0 :             myout=outhisto+ostr.str()+".dat" ;
     702             :           } else {
     703             :             myout=outhisto;
     704             :           }
     705           0 :           log<<"  Writing full grid on file "<<myout<<" \n";
     706           0 :           gridfile.open(myout);
     707             : 
     708             :           // also this is useful only for free energy
     709           0 :           if(minTOzero) {
     710           0 :             histoGrid.setMinToZero();
     711             :           }
     712             :           histoGrid.setOutputFmt(fmt);
     713           0 :           histoGrid.writeToFile(gridfile);
     714             : 
     715           0 :           if(!ihisto) {
     716           0 :             integratehisto=false;  // once you get to the final bunch just give up
     717             :           }
     718           0 :         }
     719             :       }
     720          10 :       if ( !ibias && !ihisto) {
     721             :         break;  //when both are over then just quit
     722             :       }
     723             : 
     724           1 :       nfiles++;
     725           1 :     }
     726             : 
     727             :     return;
     728           9 :   }
     729             :   // just an initialization but you need to do something on the fly?: need to connect with a metad run and its grid representation
     730             :   // your argument is a metad run
     731             :   // if the grid does not exist crash and say that you need some data
     732             :   // otherwise just link with it
     733             : 
     734           9 : }
     735             : 
     736           0 : void FuncSumHills::calculate() {
     737             :   // this should be connected only with a grid representation to metadynamics
     738             :   // at regular time just dump it
     739           0 :   plumed_merror("You should have never got here: this stuff is not yet implemented!");
     740             : }
     741             : 
     742           9 : bool FuncSumHills::checkFilesAreExisting(const std::vector<std::string> & hills ) {
     743           9 :   plumed_massert(hills.size()!=0,"the number of  files provided should be at least one" );
     744             :   auto ifile=Tools::make_unique<IFile>();
     745           9 :   ifile->link(*this);
     746          19 :   for(unsigned i=0; i< hills.size(); i++) {
     747          10 :     plumed_massert(ifile->FileExist(hills[i]),"missing file "+hills[i]);
     748             :   }
     749           9 :   return true;
     750             : 
     751           9 : }
     752             : 
     753             : }
     754             : 
     755             : }
     756             : 
     757             : 

Generated by: LCOV version 1.16