LCOV - code coverage report
Current view: top level - bias - MetaDHills.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 21 21 100.0 %
Date: 2026-11-05 10:19:04 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2026 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             : #ifndef __PLUMED_bias_MetaDHills_h
      23             : #define __PLUMED_bias_MetaDHills_h
      24             : 
      25             : #include "MetaDKernel.h"
      26             : #include "tools/Communicator.h"
      27             : #include <deque>
      28             : #include <functional>
      29             : #include <limits>
      30             : #include <memory>
      31             : #include <string>
      32             : #include <vector>
      33             : 
      34             : namespace PLMD {
      35             : 
      36             : class ActionWithValue;
      37             : class IFile;
      38             : class OFile;
      39             : class Value;
      40             : 
      41             : namespace bias {
      42             : 
      43             : class MetaDBiasGrid;
      44             : class MetaDDiffusionRestart;
      45             : 
      46             : /// shortest representation of x that is converted back to the same double
      47             : std::string exactString(double x);
      48             : 
      49             : /// broadcast a string from process 0: the length is sent first, as on the other processes the string
      50             : /// can have a different length (Communicator::Bcast of a string uses the local length)
      51             : void bcastString(Communicator& c, std::string& s);
      52             : 
      53             : /// remove the last line of a hills file if it is incomplete (left by a run that was interrupted while
      54             : /// writing it); returns the message for the log (empty if nothing was done)
      55             : std::string removeIncompleteLastLine(const std::string& path);
      56             : 
      57             : /// The hills files of METAD and PBMETAD for a set of arguments: writing of the hills, and reading of the files
      58             : /// of a restart or of the other walkers.
      59             : ///
      60             : /// With several MPI processes the files are opened and read by the first process only, which also decides if
      61             : /// they exist, and the hills are broadcast to the others: the file of another walker can grow while it is read,
      62             : /// and if each process read it they could read a different number of hills, and their biases would differ.
      63             : /// The file operations do not synchronize the processes (the files are linked to a communicator of the process
      64             : /// alone). Everything written on the log is written by all the processes.
      65             : class MetaDHillsFiles {
      66             : public:
      67             :   /// called for each hill that is read: time, multivariate, height, center, sigma (the widths, or the upper
      68             :   /// triangle of the inverse covariance matrix for multivariate hills)
      69             :   using Callback=std::function<void(double,bool,double,const std::vector<double>&,const std::vector<double>&)>;
      70             :   /// The bias to which the hills that are read are added (see readHills)
      71        1728 :   struct Bias {
      72             :     /// add a hill to the bias
      73             :     std::function<void(const MetaDGaussian&)> add;
      74             :     /// the grid of the bias, if any (it completes the line of the log when it is extended)
      75             :     MetaDBiasGrid* grid=nullptr;
      76             :     /// ADAPTIVE=DIFF: when it is pending, the hills of the own file are kept here for the statistics of the fluctuations
      77             :     MetaDDiffusionRestart* diffrestart=nullptr;
      78             :     /// the height of a hill is the one in the file times heightscale (well-tempered metadynamics)
      79             :     double heightscale=1.0;
      80             :     /// times closer than this are the same time (times are written with a finite precision): half a PACE
      81             :     double tolerance=0.0;
      82             :   };
      83             : private:
      84             :   ActionWithValue& action_;
      85             :   Communicator& comm_;
      86             :   /// communicator of the process alone, linked to the input files
      87             :   Communicator selfcomm_;
      88             :   std::vector<Value*> args_;
      89             :   std::vector<std::unique_ptr<IFile>> ifiles_;
      90             :   std::vector<std::string> ifilesnames_;
      91             :   /// number of hills read from each file
      92             :   std::vector<unsigned long long> nread_;
      93             :   Bias bias_;
      94             :   bool noStretchWarningDone_=false;
      95             :   /// a hill with a Gaussian (not stretched) kernel was read
      96             :   bool gaussianKernelsFound_=false;
      97             :   void noStretchWarning();
      98             :   /// an error in a hills file
      99             :   [[noreturn]] void inputError(const std::string& msg) const;
     100             :   /// the numbers of hills of the other walkers in a grid file (on one process)
     101             :   static std::vector<long long> readGridComment(const std::string& path, unsigned nwalkers);
     102             :   bool scanOneHill(IFile* ifile, std::vector<Value>& v, std::vector<double>& center, std::vector<double>& sigma, double& height,
     103             :                    bool& multivariate, double& time);
     104             : public:
     105             :   MetaDHillsFiles(ActionWithValue& action, Communicator& comm, const std::vector<Value*>& args);
     106             :   /// the name of the hills file of a walker: name.walker with WALKERS_N, in the directory dir if given
     107             :   /// (with WALKERS_N or WALKERS_MPI)
     108             :   static std::string getWalkerFileName(const std::string& name, const std::string& dir, int nwalkers, int walker, bool mpi);
     109             :   ~MetaDHillsFiles();
     110             :   /// add an input file, which is opened if it exists; returns its index. With nosuffix, the name is used without
     111             :   /// the suffix of the replica (with multiple walkers, as for the files that are written)
     112             :   unsigned addInput(const std::string& name, bool nosuffix=false);
     113             :   const std::string& getInputName(unsigned i) const {
     114        6715 :     return ifilesnames_[i];
     115             :   }
     116             :   /// true if the file is open (the same on all the processes)
     117             :   bool isOpen(unsigned i);
     118             :   /// path of an open file (on the first process only, empty on the others)
     119             :   std::string getPath(unsigned i) const;
     120             :   /// open the file if it exists now; returns true if it has been opened
     121             :   bool openIfExists(unsigned i);
     122             :   /// read the hills that are in the file (an open file) up to now and call f for each one; returns their number.
     123             :   /// An error while reading (e.g. a wrong field) is thrown by all the processes.
     124             :   unsigned read(unsigned i, const Callback& f);
     125             :   /// With WALKERS_N, the grid written by a walker contains the hills it has read from the files of the other walkers:
     126             :   /// their numbers are written in a comment line after the grid, so that when restarting from the grid only the
     127             :   /// hills that are not in it are added. The comment line (own is the index of this walker)
     128             :   std::string getGridComment(unsigned own) const;
     129             :   /// the numbers of hills of the other walkers in the grid file path (written by getGridComment), -1 for this walker;
     130             :   /// empty if the file does not contain them
     131             :   /// (read by the first process of comm and broadcast)
     132             :   static std::vector<long long> readGridComment(Communicator& comm, const std::string& path, unsigned nwalkers);
     133             :   void setBias(const Bias& bias) {
     134         432 :     bias_=bias;
     135         432 :   }
     136             :   const Bias& getBias() const {
     137             :     return bias_;
     138             :   }
     139             :   /// Read the hills of file i that are in the file up to now (an open file) and add them to the bias, writing their
     140             :   /// number on the log (the caller has started the line). Returns their number.
     141             :   /// lasttime: if given, the time of the last hill is returned, and the hills are kept for ADAPTIVE=DIFF (own file);
     142             :   /// addtobias: false to only scan the file; the hills up to time skipupto, and the first skipcount, are not added
     143             :   /// (they are already in the grid read from file)
     144             :   unsigned readHills(unsigned i, double* lasttime=nullptr, bool addtobias=true,
     145             :                      double skipupto=-std::numeric_limits<double>::infinity(), unsigned long long skipcount=0);
     146             :   /// prepare an open file for the next read (the hills read up to now are not read again)
     147             :   void reset(unsigned i);
     148             :   void close(unsigned i);
     149             :   /// write a hill; height is the one written in the file
     150             :   void write(OFile& file, double time, const MetaDGaussian& hill, double height, double biasf, bool clock) const;
     151             : };
     152             : 
     153             : /// ADAPTIVE=DIFF: when restarting, the statistics of the fluctuations of the variables (running average and
     154             : /// covariance) are initialized from the last hills of this walker in its hills file. The hills are kept here while the
     155             : /// file is read, until the first update, when the current time is known.
     156             : class MetaDDiffusionRestart {
     157             :   std::deque<double> time_;
     158             :   std::deque<std::vector<double>> center_;
     159             :   /// as stored in the hills: upper triangle of the inverse covariance matrix
     160             :   std::deque<std::vector<double>> sigma_;
     161             :   std::string file_;
     162             : public:
     163             :   /// the statistics are still to be initialized
     164             :   bool pending=false;
     165             :   /// maximum number of hills to keep (the older ones have a negligible weight)
     166             :   unsigned maxhills=0;
     167          18 :   void clear() {
     168          18 :     time_.clear();
     169          18 :     center_.clear();
     170          18 :     sigma_.clear();
     171          18 :   }
     172             :   /// a hill read from file (hills that are not multivariate cannot be used: the previous ones are discarded)
     173             :   void add(const std::string& file, double time, bool multivariate, const std::vector<double>& center, const std::vector<double>& sigma);
     174             :   const std::string& getFile() const {
     175             :     return file_;
     176             :   }
     177             :   /// The statistics from the hills of this walker. The hills with times within tol form blocks (one deposition):
     178             :   /// with blocksize 0 all the hills are used, otherwise the hill at position offset of the blocks with blocksize hills.
     179             :   /// Only the hills up to now, and the last sequence with increasing times, are used. The covariance is that of the
     180             :   /// last hill; the average is the average of the centers with the exponential weights of the running average
     181             :   /// (decay per update, updatetime is the time between updates). difference(i,a,b) and bringBackInPbc(i,x) are those
     182             :   /// of variable i. Returns the number of hills used (0: no statistics), and the time of the last one.
     183             :   unsigned compute(double tol, double now, unsigned blocksize, unsigned offset, double decay, double updatetime,
     184             :                    const std::function<double(unsigned,double,double)>& difference,
     185             :                    const std::function<double(unsigned,double)>& bringBackInPbc,
     186             :                    std::vector<double>& average, std::vector<double>& variance, double& lasttime) const;
     187             : };
     188             : 
     189             : /// The steps when a hill is added: every stride steps, except the first step of a run. At step 0 no hill is
     190             : /// added (also when the bias of a previous simulation is read with RESTART). When continuing a simulation, the
     191             : /// hill is not added only if the hills file already contains it, i.e. if the previous run already performed this
     192             : /// step (some MD codes compute again the last step of the previous run when restarting, others do not).
     193         350 : class MetaDHillSchedule {
     194             :   bool runStarted_=false;
     195             :   long long int runStartStep_=0;
     196             :   /// the time of the last hill in the hills file read when restarting
     197             :   bool lastHillTimeKnown_=false;
     198             :   double lastHillTime_=0.0;
     199             : public:
     200             :   void setLastHillTime(double time) {
     201          62 :     lastHillTimeKnown_=true;
     202          62 :     lastHillTime_=time;
     203          62 :   }
     204             :   /// to be called at every calculate (the first call starts the run)
     205             :   void start(long long int step) {
     206       52496 :     if(!runStarted_) {
     207         330 :       runStarted_=true;
     208         330 :       runStartStep_=step;
     209             :     }
     210             :   }
     211             :   /// true before the first calculate and at the first step of the run
     212             :   bool isRunFirstStep(long long int step) const {
     213       14689 :     return !runStarted_ || step==runStartStep_;
     214             :   }
     215             :   /// tolerance: times are written with a finite precision (FMT), so that a hill within tolerance (half a PACE)
     216             :   /// is considered to be the hill of this step; a later hill means that the previous run went beyond this step
     217       53156 :   bool isHillStep(long long int step, long long int stride, double time, double tolerance) const {
     218       53156 :     if(step%stride!=0) {
     219             :       return false;
     220             :     }
     221             :     if(isRunFirstStep(step)) {
     222         348 :       if(step==0 || !lastHillTimeKnown_) {
     223             :         return false;
     224             :       }
     225          39 :       return lastHillTime_<time-tolerance;
     226             :     }
     227             :     return true;
     228             :   }
     229             : };
     230             : 
     231             : }
     232             : }
     233             : 
     234             : #endif

Generated by: LCOV version 1.16