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

Generated by: LCOV version 1.16