LCOV - code coverage report
Current view: top level - cltools - SumHills.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 207 242 85.5 %
Date: 2025-12-04 11:19:34 Functions: 8 8 100.0 %

          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 "CLTool.h"
      23             : #include "core/CLToolRegister.h"
      24             : #include "tools/Tools.h"
      25             : #include "core/Action.h"
      26             : #include "core/ActionRegister.h"
      27             : #include "core/PlumedMain.h"
      28             : #include "tools/Communicator.h"
      29             : #include "tools/Random.h"
      30             : #include <cstdio>
      31             : #include <string>
      32             : #include <vector>
      33             : #include "tools/File.h"
      34             : #include "core/Value.h"
      35             : #include "tools/Matrix.h"
      36             : 
      37             : namespace PLMD {
      38             : namespace cltools {
      39             : 
      40             : //+PLUMEDOC TOOLS sum_hills
      41             : /*
      42             : sum_hills is a tool that allows one to to use plumed to post-process an existing hills/colvar file
      43             : 
      44             : This tool is most frequently used as shown below after a [METAD](METAD.md) simulation has been performed to sum all the Gaussians in the hills file
      45             : and output the free energy surface.
      46             : 
      47             : ```plumed
      48             : plumed sum_hills  --hills PATHTOMYHILLSFILE
      49             : ```
      50             : 
      51             : The default name for the output file will be `fes.dat`
      52             : Note that plumed automatically detects the
      53             : number of the variables you have and their periodicity.
      54             : Additionally, if you use flexible hills (multivariate Gaussian kernels), plumed will understand it from the HILLS file.
      55             : 
      56             : The sum_hills tool can also accept multiple files that will be integrated one after the other as shown below
      57             : 
      58             : ```plumed
      59             : plumed sum_hills  --hills PATHTOMYHILLSFILE1,PATHTOMYHILLSFILE2,PATHTOMYHILLSFILE3
      60             : ```
      61             : 
      62             : if you want to integrate out some variable from your output free energy surface you do
      63             : 
      64             : ```plumed
      65             : plumed sum_hills  --hills PATHTOMYHILLSFILE   --idw t1 --kt 0.6
      66             : ```
      67             : 
      68             : where with `--idw` you define the variables that you want in the output free energy surface.
      69             : All other variables in the hills file will be integrated out. `--kt` defines the temperature of the system in energy units.
      70             : (be consistent with the units you have in your hills: plumed will not check this for you)
      71             : If you need more variables then you may use a comma separated syntax shown below:
      72             : 
      73             : ```plumed
      74             : plumed sum_hills  --hills PATHTOMYHILLSFILE   --idw t1,t2 --kt 0.6
      75             : ```
      76             : 
      77             : You can define the output grid with the number of bins you want by using a command like this one
      78             : 
      79             : ```plumed
      80             : plumed sum_hills --bin 99,99 --hills PATHTOMYHILLSFILE
      81             : ```
      82             : 
      83             : In the command above the min/max to use are detected for you.  If you want to specify the min/max yourself you can do so by using
      84             : a command like the one shown below:
      85             : 
      86             : ```plumed
      87             : plumed sum_hills --bin 99,99 --min -pi,-pi --max pi,pi --hills PATHTOMYHILLSFILE
      88             : ```
      89             : 
      90             : You can of course use numbers instead of -pi/pi.
      91             : 
      92             : You can use a `--stride` keyword to have a dump of the free energy estimate after each bunch of hills you read as shown in the following command:
      93             : 
      94             : ```plumed
      95             : plumed sum_hills --stride 300 --hills PATHTOMYHILLSFILE
      96             : ```
      97             : 
      98             : If you have run well tempered metadynamics you can also ask `sum_hills` to output the negative bias instead of the free energy by using the keyword `--negbias`
      99             : as shown below
     100             : 
     101             : ```plumed
     102             : plumed sum_hills --negbias --hills PATHTOMYHILLSFILE
     103             : ```
     104             : 
     105             : Here the default output file name will be negativebias.dat
     106             : 
     107             : From time to time you might need to use HILLS or a COLVAR file
     108             : as it was just a simple set  of points from which you want to build
     109             : a free energy by using -(1/beta)log(P).  If you want to do this operation then
     110             : you use the `--histo` option as shown below:
     111             : 
     112             : ```plumed
     113             : plumed sum_hills --histo PATHTOMYCOLVARORHILLSFILE  --sigma 0.2,0.2 --kt 0.6
     114             : ```
     115             : 
     116             : in this case you need a `--kt` to do the reweighting and you
     117             : need to set bandwidth parameters using the `--sigma` option for the histogram calculation as this histogram is computed using
     118             : Gaussian kernels, so it will be a continuous histogram.
     119             : 
     120             : For the command above the default output is called histo.dat.
     121             : Note that also here you can have multiple input files separated by a comma.
     122             : 
     123             : Additionally, if you want to compute the histogram and sum of the hills from the same file you can do this by using a command like this one:
     124             : 
     125             : ```plumed
     126             : plumed sum_hills --hills --histo PATHTOMYCOLVARORHILLSFILE  --sigma 0.2,0.2 --kt 0.6
     127             : ```
     128             : 
     129             : The two files can be eventually the same
     130             : 
     131             : Another interesting thing one can do is monitor the difference in blocks as a metadynamics goes on.
     132             : When the bias deposited is constant over the whole domain one can consider to be at convergence.
     133             : This can be done with the `--nohistory` keyword
     134             : 
     135             : ```plumed
     136             : plumed sum_hills --stride 300 --hills PATHTOMYHILLSFILE  --nohistory
     137             : ```
     138             : 
     139             : and similarly one can do the same for an histogram file
     140             : 
     141             : ```plumed
     142             : plumed sum_hills --histo PATHTOMYCOLVARORHILLSFILE  --sigma 0.2,0.2 --kt 0.6 --nohistory
     143             : ```
     144             : 
     145             : just to check the hypothetical free energy calculated in single blocks of time during a simulation
     146             : and not in a cumulative way
     147             : 
     148             : The output format can be controlled by using the `--fmt` option as shown below
     149             : 
     150             : ```plumed
     151             : plumed sum_hills --hills PATHTOMYHILLSFILE  --fmt %8.3f
     152             : ```
     153             : 
     154             : where here we chose a float with length of 8 and 3 digits
     155             : 
     156             : The output can be named in a arbitrary way by using the `--output` option as shown below:
     157             : 
     158             : ```plumed
     159             : plumed sum_hills --hills PATHTOMYHILLSFILE  --outfile myfes.dat
     160             : ```
     161             : 
     162             : This command produces a file myfes.dat which contains the free energy surface.
     163             : 
     164             : If you use stride, the name specied with `--output` is the suffix so this command:
     165             : 
     166             : ```plumed
     167             : plumed sum_hills --hills PATHTOMYHILLSFILE  --outfile myfes_ --stride 100
     168             : ```
     169             : 
     170             : produces output files called myfes_0.dat,  myfes_1.dat, myfes_2.dat etc.
     171             : 
     172             : The same is true for the output coming from histogram that is used.  So this example
     173             : 
     174             : ```plumed
     175             : plumed sum_hills --histo HILLS --kt 2.5 --sigma 0.01 --outhisto myhisto.dat
     176             : ```
     177             : 
     178             : produces a file myhisto.dat, while this input
     179             : 
     180             : ```plumed
     181             : plumed sum_hills --histo HILLS --kt 2.5 --sigma 0.01 --outhisto myhisto_ --stride 100
     182             : ```
     183             : 
     184             : produces output files called `myhisto_0.dat`,  `myhisto_1.dat`,  `myhisto_3.dat` etc..
     185             : 
     186             : */
     187             : //+ENDPLUMEDOC
     188             : 
     189             : class CLToolSumHills : public CLTool {
     190             : public:
     191             :   static void registerKeywords( Keywords& keys );
     192             :   explicit CLToolSumHills(const CLToolOptions& co );
     193             :   int main(FILE* in,FILE*out,Communicator& pc) override;
     194             :   std::string description()const override;
     195             : /// find a list of variables present, if they are periodic and which is the period
     196             : /// return false if the file does not exist
     197             :   static bool findCvsAndPeriodic(const std::string & filename, std::vector< std::vector <std::string> > &cvs,std::vector<std::string> &pmin,std::vector<std::string> &pmax, bool &multivariate, std::string &lowI_, std::string &uppI_);
     198             : };
     199             : 
     200        5683 : void CLToolSumHills::registerKeywords( Keywords& keys ) {
     201        5683 :   CLTool::registerKeywords( keys );
     202        5683 :   keys.addFlag("--help-debug",false,"print special options that can be used to create regtests");
     203        5683 :   keys.add("optional","--hills","specify the name of the hills file");
     204        5683 :   keys.add("optional","--histo","specify the name of the file for histogram a colvar/hills file is good");
     205        5683 :   keys.add("optional","--stride","specify the stride for integrating hills file (default 0=never)");
     206        5683 :   keys.add("optional","--min","the lower bounds for the grid");
     207        5683 :   keys.add("optional","--max","the upper bounds for the grid");
     208        5683 :   keys.add("optional","--bin","the number of bins for the grid");
     209        5683 :   keys.add("optional","--spacing","grid spacing, alternative to the number of bins");
     210        5683 :   keys.add("optional","--idw","specify the variables to be used for the free-energy/histogram (default is all). With --hills the other variables will be integrated out, with --histo the other variables won't be considered");
     211        5683 :   keys.add("optional","--outfile","specify the output file for sumhills");
     212        5683 :   keys.add("optional","--outhisto","specify the output file for the histogram");
     213        5683 :   keys.add("optional","--kt","specify temperature in energy units for integrating out variables");
     214        5683 :   keys.add("optional","--sigma"," a vector that specify the sigma for binning (only needed when doing histogram ");
     215        5683 :   keys.addFlag("--negbias",false," print the negative bias instead of the free energy (only needed with well tempered runs and flexible hills) ");
     216        5683 :   keys.addFlag("--nohistory",false," to be used with --stride:  it splits the bias/histogram in pieces without previous history ");
     217        5683 :   keys.addFlag("--mintozero",false," it translate all the minimum value in bias/histogram to zero (useful to compare results) ");
     218        5683 :   keys.add("optional","--fmt","specify the output format");
     219        5683 : }
     220             : 
     221          14 : CLToolSumHills::CLToolSumHills(const CLToolOptions& co ):
     222          14 :   CLTool(co) {
     223          14 :   inputdata=inputType::commandline;
     224          14 : }
     225             : 
     226           5 : std::string CLToolSumHills::description()const {
     227           5 :   return "sum the hills with  plumed";
     228             : }
     229             : 
     230           9 : int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc) {
     231             : 
     232             : // Read the hills input file name
     233             :   std::vector<std::string> hillsFiles;
     234             :   bool dohills;
     235          18 :   dohills=parseVector("--hills",hillsFiles);
     236             : // Read the histogram file
     237             :   std::vector<std::string> histoFiles;
     238             :   bool dohisto;
     239           9 :   dohisto=parseVector("--histo",histoFiles);
     240             : 
     241           9 :   plumed_massert(dohisto || dohills,"you should use --histo or/and --hills command");
     242             : 
     243             :   std::vector< std::vector<std::string> > vcvs;
     244             :   std::vector<std::string> vpmin;
     245             :   std::vector<std::string> vpmax;
     246             :   std::string lowI_, uppI_;
     247           9 :   if(dohills) {
     248             :     // parse it as it was a restart
     249             :     bool vmultivariate;
     250           8 :     findCvsAndPeriodic(hillsFiles[0], vcvs, vpmin, vpmax, vmultivariate, lowI_, uppI_);
     251             :   }
     252             : 
     253             :   std::vector< std::vector<std::string> > hcvs;
     254             :   std::vector<std::string> hpmin;
     255             :   std::vector<std::string> hpmax;
     256             : 
     257             :   std::vector<std::string> sigma;
     258           9 :   if(dohisto) {
     259             :     bool hmultivariate;
     260           1 :     findCvsAndPeriodic(histoFiles[0], hcvs, hpmin, hpmax, hmultivariate, lowI_, uppI_);
     261             :     // here need also the vector of sigmas
     262           2 :     parseVector("--sigma",sigma);
     263           1 :     if(sigma.size()==0) {
     264           0 :       plumed_merror("you should define --sigma vector when using histogram");
     265             :     }
     266             :     lowI_=uppI_="-1.";  // Interval is not use for histograms
     267             :   }
     268             : 
     269           9 :   if(dohisto && dohills) {
     270           0 :     plumed_massert(vcvs==hcvs,"variables for histogram and bias should have the same labels");
     271           0 :     plumed_massert(hpmin==vpmin,"variables for histogram and bias should have the same min for periodicity");
     272           0 :     plumed_massert(hpmax==vpmax,"variables for histogram and bias should have the same max for periodicity");
     273             :   }
     274             : 
     275             :   // now put into a neutral vector
     276             : 
     277             :   std::vector< std::vector<std::string> > cvs;
     278             :   std::vector<std::string> pmin;
     279             :   std::vector<std::string> pmax;
     280             : 
     281           9 :   if(dohills) {
     282           8 :     cvs=vcvs;
     283           8 :     pmin=vpmin;
     284           8 :     pmax=vpmax;
     285             :   }
     286           9 :   if(dohisto) {
     287           1 :     cvs=hcvs;
     288           1 :     pmin=hpmin;
     289           1 :     pmax=hpmax;
     290             :   }
     291             : 
     292             : 
     293             :   // setup grids
     294             :   unsigned grid_check=0;
     295           9 :   std::vector<std::string> gmin(cvs.size());
     296          18 :   if(parseVector("--min",gmin)) {
     297           4 :     if(gmin.size()!=cvs.size() && gmin.size()!=0) {
     298           0 :       plumed_merror("not enough values for --min");
     299             :     }
     300             :     grid_check++;
     301             :   }
     302           9 :   std::vector<std::string> gmax(cvs.size() );
     303          18 :   if(parseVector("--max",gmax)) {
     304           4 :     if(gmax.size()!=cvs.size() && gmax.size()!=0) {
     305           0 :       plumed_merror("not enough values for --max");
     306             :     }
     307           4 :     grid_check++;
     308             :   }
     309           9 :   std::vector<std::string> gbin(cvs.size());
     310             :   bool grid_has_bin;
     311             :   grid_has_bin=false;
     312          18 :   if(parseVector("--bin",gbin)) {
     313           5 :     if(gbin.size()!=cvs.size() && gbin.size()!=0) {
     314           0 :       plumed_merror("not enough values for --bin");
     315             :     }
     316             :     grid_has_bin=true;
     317             :   }
     318           9 :   std::vector<std::string> gspacing(cvs.size());
     319             :   bool grid_has_spacing;
     320             :   grid_has_spacing=false;
     321          18 :   if(parseVector("--spacing",gspacing)) {
     322           1 :     if(gspacing.size()!=cvs.size() && gspacing.size()!=0) {
     323           0 :       plumed_merror("not enough values for --spacing");
     324             :     }
     325             :     grid_has_spacing=true;
     326             :   }
     327             :   // allowed: no grids only bin
     328             :   // not allowed: partial grid definition
     329           9 :   plumed_massert( gmin.size()==gmax.size() && (gmin.size()==0 ||  gmin.size()==cvs.size() ),"you should specify --min and --max together with same number of components");
     330             : 
     331             : 
     332             : 
     333           9 :   PlumedMain plumed;
     334             :   std::string ss;
     335           9 :   unsigned nn=1;
     336             :   ss="setNatoms";
     337           9 :   plumed.cmd(ss,&nn);
     338           9 :   if(Communicator::initialized()) {
     339           0 :     plumed.cmd("setMPIComm",&pc.Get_comm());
     340             :   }
     341           9 :   plumed.cmd("init",&nn);
     342           9 :   std::vector <bool> isdone(cvs.size(),false);
     343          26 :   for(unsigned i=0; i<cvs.size(); i++) {
     344          17 :     if(!isdone[i]) {
     345             :       isdone[i]=true;
     346             :       std::vector<std::string> actioninput;
     347             :       std::vector <unsigned> inds;
     348          17 :       actioninput.push_back("FAKE");
     349          34 :       actioninput.push_back("ATOMS=1");
     350          34 :       actioninput.push_back("LABEL="+cvs[i][0]);
     351             :       std::vector<std::string> comps, periods;
     352          17 :       if(cvs[i].size()>1) {
     353           1 :         comps.push_back(cvs[i][1]);
     354           1 :         inds.push_back(i);
     355             :       }
     356          17 :       periods.push_back(pmin[i]);
     357          17 :       periods.push_back(pmax[i]);
     358          25 :       for(unsigned j=i+1; j<cvs.size(); j++) {
     359           8 :         if(cvs[i][0]==cvs[j][0] && !isdone[j]) {
     360           0 :           if(cvs[i].size()==1 || cvs[j].size()==1  ) {
     361           0 :             plumed_merror("you cannot have twice the same label and no components ");
     362             :           }
     363           0 :           if(cvs[j].size()>1) {
     364           0 :             comps.push_back(cvs[j][1]);
     365           0 :             periods.push_back(pmin[j]);
     366           0 :             periods.push_back(pmax[j]);
     367             :             isdone[j]=true;
     368           0 :             inds.push_back(j);
     369             :           }
     370             :         }
     371             : 
     372             :       }
     373             :       // drain all the components
     374             :       std::string addme;
     375          17 :       if(comps.size()>0) {
     376             :         addme="COMPONENTS=";
     377           1 :         for(unsigned ii=0; ii<comps.size()-1; ii++) {
     378           0 :           addme+=comps[ii]+",";
     379             :         }
     380             :         addme+=comps.back();
     381           1 :         actioninput.push_back(addme);
     382             :       }
     383             :       // periodicity (always explicit here)
     384             :       addme="PERIODIC=";
     385          34 :       for(unsigned j=0; j<periods.size()-1; j++) {
     386          34 :         addme+=periods[j]+",";
     387             :       }
     388             :       addme+=periods.back();
     389          17 :       actioninput.push_back(addme);
     390          18 :       for(unsigned j=0; j<inds.size(); j++) {
     391             :         unsigned jj;
     392           1 :         jj=inds[j];
     393           1 :         if(grid_check==2) {
     394             :           double gm;
     395             :           double pm;
     396           1 :           if(pmin[jj]!="none") {
     397           1 :             Tools::convert(gmin[jj],gm);
     398           1 :             Tools::convert(pmin[jj],pm);
     399           1 :             if(  gm<pm  ) {
     400           0 :               plumed_merror("Periodicity issue : GRID_MIN value ( "+gmin[jj]+" ) is less than periodicity in HILLS file in "+cvs[jj][0]+ " ( "+pmin[jj]+" ) ");
     401             :             }
     402             :           }
     403           1 :           if(pmax[jj]!="none") {
     404           1 :             Tools::convert(gmax[jj],gm);
     405           1 :             Tools::convert(pmax[jj],pm);
     406           1 :             if(  gm>pm ) {
     407           0 :               plumed_merror("Periodicity issue : GRID_MAX value ( "+gmax[jj]+" ) is more than periodicity in HILLS file in "+cvs[jj][0]+ " ( "+pmax[jj]+" ) ");
     408             :             }
     409             :           }
     410             :         }
     411             :       }
     412             : 
     413             : //  for(unsigned i=0;i< actioninput.size();i++){
     414             : //    cerr<<"AA "<<actioninput[i]<<endl;
     415             : //  }
     416          17 :       plumed.readInputWords(actioninput,false);
     417          34 :     }
     418             : 
     419             :   }
     420           9 :   unsigned ncv=cvs.size();
     421             :   std::vector<std::string> actioninput;
     422             :   std::vector<std::string> idw;
     423             :   // check if the variables to be used are correct
     424          18 :   if(parseVector("--idw",idw)) {
     425           4 :     for(unsigned i=0; i<idw.size(); i++) {
     426             :       bool found=false;
     427           6 :       for(unsigned j=0; j<cvs.size(); j++) {
     428           4 :         if(cvs[j].size()>1) {
     429           0 :           if(idw[i]==cvs[j][0]+"."+cvs[j][1]) {
     430             :             found=true;
     431             :           }
     432             :         } else {
     433           4 :           if(idw[i]==cvs[j][0]) {
     434             :             found=true;
     435             :           }
     436             :         }
     437             :       }
     438           2 :       if(!found) {
     439           0 :         plumed_merror("variable "+idw[i]+" is not found in the bunch of cvs: revise your --idw option" );
     440             :       }
     441             :     }
     442           2 :     plumed_massert( idw.size()<=cvs.size(),"the number of variables to be integrated should be at most equal to the total number of cvs  ");
     443             :     // in this case you need a beta factor!
     444             :   }
     445             : 
     446             :   std::string kt;
     447           9 :   kt=std::string("1.");// assign an arbitrary value just in case that idw.size()==cvs.size()
     448           9 :   if ( dohisto || idw.size()!=0  ) {
     449           6 :     plumed_massert(parse("--kt",kt),"if you make a dimensionality reduction (--idw) or a histogram (--histo) then you need to define --kt ");
     450             :   }
     451             : 
     452             :   std::string addme;
     453             : 
     454           9 :   actioninput.push_back("FUNCSUMHILLS");
     455          18 :   actioninput.push_back("ISCLTOOL");
     456             : 
     457             :   // set names
     458             :   std::string outfile;
     459          18 :   if(parse("--outfile",outfile)) {
     460           0 :     actioninput.push_back("OUTHILLS="+outfile);
     461             :   }
     462             :   std::string outhisto;
     463          18 :   if(parse("--outhisto",outhisto)) {
     464           2 :     actioninput.push_back("OUTHISTO="+outhisto);
     465             :   }
     466             : 
     467             : 
     468             :   addme="ARG=";
     469          17 :   for(unsigned i=0; i<(ncv-1); i++) {
     470           8 :     if(cvs[i].size()==1) {
     471          16 :       addme+=std::string(cvs[i][0])+",";
     472             :     } else {
     473           0 :       addme+=std::string(cvs[i][0])+"."+std::string(cvs[i][1])+",";
     474             :     }
     475             :   }
     476           9 :   if(cvs[ncv-1].size()==1) {
     477          16 :     addme+=std::string(cvs[ncv-1][0]);
     478             :   } else {
     479           2 :     addme+=std::string(cvs[ncv-1][0])+"."+std::string(cvs[ncv-1][1]);
     480             :   }
     481           9 :   actioninput.push_back(addme);
     482             :   //for(unsigned i=0;i< actioninput.size();i++){
     483             :   //  cerr<<"AA "<<actioninput[i]<<endl;
     484             :   //}
     485           9 :   if(dohills) {
     486             :     addme="HILLSFILES=";
     487           9 :     for(unsigned i=0; i<hillsFiles.size()-1; i++) {
     488           2 :       addme+=hillsFiles[i]+",";
     489             :     }
     490             :     addme+=hillsFiles[hillsFiles.size()-1];
     491           8 :     actioninput.push_back(addme);
     492             :     // set the grid
     493             :   }
     494           9 :   if(grid_check==2) {
     495             :     addme="GRID_MAX=";
     496           7 :     for(unsigned i=0; i<(ncv-1); i++) {
     497           6 :       addme+=gmax[i]+",";
     498             :     }
     499             :     addme+=gmax[ncv-1];
     500           4 :     actioninput.push_back(addme);
     501             :     addme="GRID_MIN=";
     502           7 :     for(unsigned i=0; i<(ncv-1); i++) {
     503           6 :       addme+=gmin[i]+",";
     504             :     }
     505             :     addme+=gmin[ncv-1];
     506           4 :     actioninput.push_back(addme);
     507             :   }
     508           9 :   if(grid_has_bin) {
     509             :     addme="GRID_BIN=";
     510          10 :     for(unsigned i=0; i<(ncv-1); i++) {
     511          10 :       addme+=gbin[i]+",";
     512             :     }
     513             :     addme+=gbin[ncv-1];
     514           5 :     actioninput.push_back(addme);
     515             :   }
     516           9 :   if(grid_has_spacing) {
     517             :     addme="GRID_SPACING=";
     518           1 :     for(unsigned i=0; i<(ncv-1); i++) {
     519           0 :       addme+=gspacing[i]+",";
     520             :     }
     521             :     addme+=gspacing[ncv-1];
     522           1 :     actioninput.push_back(addme);
     523             :   }
     524             :   std::string  stride;
     525             :   stride="";
     526          18 :   if(parse("--stride",stride)) {
     527           1 :     actioninput.push_back("INITSTRIDE="+stride);
     528             :     bool  nohistory;
     529           1 :     parseFlag("--nohistory",nohistory);
     530           1 :     if(nohistory) {
     531           0 :       actioninput.push_back("NOHISTORY");
     532             :     }
     533             :   }
     534             :   bool  mintozero;
     535           9 :   parseFlag("--mintozero",mintozero);
     536           9 :   if(mintozero) {
     537           0 :     actioninput.push_back("MINTOZERO");
     538             :   }
     539           9 :   if(idw.size()!=0) {
     540             :     addme="PROJ=";
     541           2 :     for(unsigned i=0; i<idw.size()-1; i++) {
     542           0 :       addme+=idw[i]+",";
     543             :     }
     544             :     addme+=idw.back();
     545           2 :     actioninput.push_back(addme);
     546             :   }
     547             : 
     548           9 :   if(dohisto) {
     549           1 :     if(idw.size()==0) {
     550           1 :       if(sigma.size()!=hcvs.size()) {
     551           0 :         plumed_merror("you should define as many --sigma vector as the number of collective variable used for the histogram ");
     552             :       }
     553             :     } else {
     554           0 :       if(idw.size()!=sigma.size()) {
     555           0 :         plumed_merror("you should define as many --sigma vector as the number of collective variable used for the histogram ");
     556             :       }
     557             :     }
     558             :   }
     559             : 
     560           9 :   if(idw.size()!=0 || dohisto) {
     561           6 :     actioninput.push_back("KT="+kt);
     562             :   }
     563           9 :   if(dohisto) {
     564             :     addme="HISTOFILES=";
     565           1 :     for(unsigned i=0; i<histoFiles.size()-1; i++) {
     566           0 :       addme+=histoFiles[i]+",";
     567             :     }
     568             :     addme+=histoFiles[histoFiles.size()-1];
     569           1 :     actioninput.push_back(addme);
     570             : 
     571             :     addme="HISTOSIGMA=";
     572           2 :     for(unsigned i=0; i<sigma.size()-1; i++) {
     573           2 :       addme+=sigma[i]+",";
     574             :     }
     575             :     addme+=sigma.back();
     576           1 :     actioninput.push_back(addme);
     577             :   }
     578             : 
     579             :   bool negbias;
     580           9 :   parseFlag("--negbias",negbias);
     581           9 :   if(negbias) {
     582           2 :     actioninput.push_back("NEGBIAS");
     583             :   }
     584             : 
     585           9 :   if(lowI_!=uppI_) {
     586             :     addme="INTERVAL=";
     587           0 :     addme+=lowI_+",";
     588             :     addme+=uppI_;
     589           0 :     actioninput.push_back(addme);
     590             :   }
     591             : 
     592             :   std::string fmt;
     593             :   fmt="";
     594          18 :   parse("--fmt",fmt);
     595           9 :   if(fmt!="") {
     596          18 :     actioninput.push_back("FMT="+fmt);
     597             :   }
     598             : 
     599             : 
     600             : //  for(unsigned i=0;i< actioninput.size();i++){
     601             : //   cerr<<"AA "<<actioninput[i]<<endl;
     602             : //  }
     603           9 :   plumed.readInputWords(actioninput,false);
     604             :   // if not a grid, then set it up automatically
     605           9 :   return 0;
     606          27 : }
     607             : 
     608           9 : bool CLToolSumHills::findCvsAndPeriodic(const std::string & filename,
     609             :                                         std::vector< std::vector<std::string>  > &cvs,
     610             :                                         std::vector<std::string> &pmin,
     611             :                                         std::vector<std::string> &pmax,
     612             :                                         bool &multivariate,
     613             :                                         std::string &lowI_,
     614             :                                         std::string &uppI_) {
     615           9 :   IFile ifile;
     616           9 :   ifile.allowIgnoredFields();
     617             :   std::vector<std::string> fields;
     618           9 :   if(ifile.FileExist(filename)) {
     619             :     cvs.clear();
     620             :     pmin.clear();
     621             :     pmax.clear();
     622           9 :     ifile.open(filename);
     623           9 :     ifile.scanFieldList(fields);
     624             :     bool before_sigma=true;
     625         121 :     for(unsigned i=0; i<fields.size(); i++) {
     626             :       size_t pos = 0;
     627             :       size_t founds,foundm,foundp;
     628             :       //found=(fields[i].find("sigma_", pos) || fields[i].find("min_", pos) || fields[i].find("max_", pos) ) ;
     629         112 :       founds=fields[i].find("sigma_", pos)  ;
     630         112 :       foundm=fields[i].find("min_", pos)  ;
     631         112 :       foundp=fields[i].find("max_", pos)  ;
     632         112 :       if (founds!=std::string::npos || foundm!=std::string::npos ||  foundp!=std::string::npos ) {
     633             :         before_sigma=false;
     634             :       }
     635             :       // cvs are after time and before sigmas
     636             :       size_t  found;
     637         112 :       found=fields[i].find("time", pos);
     638         112 :       if( found==std::string::npos && before_sigma) {
     639             :         // separate the components
     640             :         size_t dot=fields[i].find_first_of('.');
     641             :         std::vector<std::string> ss;
     642             :         // this loop does not take into account repetitions
     643          17 :         if(dot!=std::string::npos) {
     644           1 :           std::string a=fields[i].substr(0,dot);
     645           1 :           std::string name=fields[i].substr(dot+1);
     646           1 :           ss.push_back(a);
     647           1 :           ss.push_back(name);
     648           1 :           cvs.push_back(ss);
     649             :         } else {
     650          32 :           cvs.emplace_back(std::vector<std::string> {fields[i]});
     651             :         }
     652             :         //std::cerr<<"found variable number  "<<cvs.size()<<" :  "<<cvs.back()[0]<<std::endl;
     653             :         //if((cvs.back()).size()!=1){
     654             :         //      std::cerr<<"component    "<<(cvs.back()).back()<<std::endl;
     655             :         //}
     656             :         // get periodicity
     657          17 :         pmin.push_back("none");
     658          34 :         pmax.push_back("none");
     659             :         std::string mm;
     660          17 :         if((cvs.back()).size()>1) {
     661           2 :           mm=cvs.back()[0]+"."+cvs.back()[1];
     662             :         } else {
     663             :           mm=cvs.back()[0];
     664             :         }
     665          34 :         if(ifile.FieldExist("min_"+mm)) {
     666             :           std::string val;
     667          28 :           ifile.scanField("min_"+mm,val);
     668             :           pmin[pmin.size()-1]=val;
     669             :           // std::cerr<<"found min   :  "<<pmin.back()<<std::endl;
     670             :         }
     671             :         //std::cerr<<"found min   :  "<<pmin.back()<<std::endl;
     672          17 :         if(ifile.FieldExist("max_"+mm)) {
     673             :           std::string val;
     674          28 :           ifile.scanField("max_"+mm,val);
     675             :           pmax[pmax.size()-1]=val;
     676             :           // std::cerr<<"found max   :  "<<pmax.back()<<std::endl;
     677             :         }
     678             :         //std::cerr<<"found max   :  "<<pmax.back()<<std::endl;
     679          17 :       }
     680             :     }
     681             :     // is multivariate ???
     682             :     std::string sss;
     683           9 :     multivariate=false;
     684          18 :     if(ifile.FieldExist("multivariate")) {
     685             :       ;
     686          18 :       ifile.scanField("multivariate",sss);
     687           9 :       if(sss=="true") {
     688           6 :         multivariate=true;
     689           3 :       } else if(sss=="false") {
     690           3 :         multivariate=false;
     691             :       }
     692             :     }
     693             :     // do interval?
     694          18 :     if(ifile.FieldExist("lower_int")) {
     695           0 :       ifile.scanField("lower_int",lowI_);
     696           0 :       ifile.scanField("upper_int",uppI_);
     697             :     } else {
     698             :       lowI_="-1.";
     699             :       uppI_="-1.";
     700             :     }
     701           9 :     ifile.scanField();
     702             :     return true;
     703             :   } else {
     704             :     return false;
     705             :   }
     706           9 : }
     707             : 
     708             : 
     709       17063 : PLUMED_REGISTER_CLTOOL(CLToolSumHills,"sum_hills")
     710             : 
     711             : 
     712             : 
     713             : }
     714             : }

Generated by: LCOV version 1.16