LCOV - code coverage report
Current view: top level - eds - EDS.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 363 391 92.8 %
Date: 2021-11-18 15:22:58 Functions: 21 24 87.5 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             : Copyright (c) 2017 of Glen Hocky and Andrew White
       3             : 
       4             : The eds module is free software: you can redistribute it and/or modify
       5             : it under the terms of the GNU Lesser General Public License as published by
       6             : the Free Software Foundation, either version 3 of the License, or
       7             : (at your option) any later version.
       8             : 
       9             : The eds module is distributed in the hope that it will be useful,
      10             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             : GNU Lesser General Public License for more details.
      13             : 
      14             : You should have received a copy of the GNU Lesser General Public License
      15             : along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      16             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      17             : #include "bias/Bias.h"
      18             : #include "core/ActionRegister.h"
      19             : #include "core/Atoms.h"
      20             : #include "core/PlumedMain.h"
      21             : #include "tools/File.h"
      22             : #include "tools/Matrix.h"
      23             : #include "tools/Random.h"
      24             : 
      25             : 
      26             : 
      27             : #include <iostream>
      28             : 
      29             : 
      30             : using namespace PLMD;
      31             : using namespace bias;
      32             : 
      33             : //namespace is lowercase to match
      34             : //module names being all lowercase
      35             : 
      36             : namespace PLMD {
      37             : namespace eds {
      38             : 
      39             : //+PLUMEDOC EDSMOD_BIAS EDS
      40             : /*
      41             : Add a linear bias on a set of observables.
      42             : 
      43             : This force is the same as the linear part of the bias in \ref
      44             : RESTRAINT, but this bias has the ability to compute the prefactors
      45             : adaptively using the scheme of White and Voth \cite white2014efficient
      46             : in order to match target observable values for a set of CVs.
      47             : Further updates to the algorithm are described in \cite hocky2017cgds.
      48             : 
      49             : You can
      50             : see a tutorial on EDS specifically for biasing coordination number at
      51             : <a
      52             : href="http://thewhitelab.org/Blog/tutorial/2017/05/10/lammps-coordination-number-tutorial/">
      53             : Andrew White's webpage</a>.
      54             : 
      55             : The addition to the potential is of the form
      56             : \f[
      57             :   \sum_i \frac{\alpha_i}{s_i} x_i
      58             : \f]
      59             : 
      60             : where for CV \f$x_i\f$, a coupling constant \f${\alpha}_i\f$ is determined
      61             : adaptively or set by the user to match a target value for
      62             : \f$x_i\f$. \f$s_i\f$ is a scale parameter, which by default is set to
      63             : the target value. It may also be set separately.
      64             : 
      65             : \warning
      66             : It is not possible to set the target value of the observable
      67             : to zero with the default value of \f$s_i\f$ as this will cause a
      68             : divide-by-zero error. Instead, set \f$s_i=1\f$ or modify the CV so the
      69             : desired target value is no longer zero.
      70             : 
      71             : Notice that a similar method is available as \ref MAXENT, although with different features and using a different optimization algorithm.
      72             : 
      73             : \par Examples
      74             : 
      75             : The following input for a harmonic oscillator of two beads will
      76             : adaptively find a linear bias to change the mean and variance to the
      77             : target values. The PRINT line shows how to access the value of the
      78             : coupling constants.
      79             : 
      80             : \plumedfile
      81             : dist: DISTANCE ATOMS=1,2
      82             : # this is the squared of the distance
      83             : dist2: COMBINE ARG=dist POWERS=2 PERIODIC=NO
      84             : 
      85             : #bias mean and variance
      86             : eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 PERIOD=50000 TEMP=1.0
      87             : PRINT ARG=dist,dist2,eds.dist_coupling,eds.dist2_coupling,eds.bias,eds.force2 FILE=colvars.dat STRIDE=100
      88             : \endplumedfile
      89             : 
      90             : Rather than trying to find the coupling constants adaptively, one can ramp up to a constant value.
      91             : \plumedfile
      92             : dist: DISTANCE ATOMS=1,2
      93             : dist2: COMBINE ARG=dist POWERS=2 PERIODIC=NO
      94             : 
      95             : #ramp couplings from 0,0 to -1,1 over 50000 steps
      96             : eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 FIXED=-1,1 RAMP PERIOD=50000 TEMP=1.0
      97             : 
      98             : #same as above, except starting at -0.5,0.5 rather than default of 0,0
      99             : eds2: EDS ARG=dist,dist2 CENTER=2.0,1.0 FIXED=-1,1 INIT=-0.5,0.5 RAMP PERIOD=50000 TEMP=1.0
     100             : \endplumedfile
     101             : 
     102             : A restart file can be added to dump information needed to restart/continue simulation using these parameters every PERIOD.
     103             : \plumedfile
     104             : dist: DISTANCE ATOMS=1,2
     105             : dist2: COMBINE ARG=dist POWERS=2 PERIODIC=NO
     106             : 
     107             : #add the option to write to a restart file
     108             : eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 PERIOD=50000 TEMP=1.0 OUT_RESTART=checkpoint.eds
     109             : \endplumedfile
     110             : 
     111             : The first few lines of the restart file that is output if we run a calculation with one CV will look something like this:
     112             : 
     113             : \auxfile{restart.eds}
     114             : #! FIELDS time d1_center d1_set d1_target d1_coupling d1_maxrange d1_maxgrad d1_accum d1_mean d1_std
     115             : #! SET adaptive  1
     116             : #! SET update_period  1
     117             : #! SET seed  0
     118             : #! SET kbt    2.4943
     119             :    0.0000   1.0000   0.0000   0.0000   0.0000   7.4830   0.1497   0.0000   0.0000   0.0000
     120             :    1.0000   1.0000   0.0000   0.0000   0.0000   7.4830   0.1497   0.0000   0.0000   0.0000
     121             :    2.0000   1.0000  -7.4830   0.0000   0.0000   7.4830   0.1497   0.0224   0.0000   0.0000
     122             :    3.0000   1.0000  -7.4830   0.0000  -7.4830   7.4830   0.1497   0.0224   0.0000   0.0000
     123             :    4.0000   1.0000  -7.4830   0.0000  -7.4830   7.4830   0.1497   0.0224   0.0000   0.0000
     124             : \endauxfile
     125             : 
     126             : Read in a previous restart file. Adding RESTART flag makes output append
     127             : \plumedfile
     128             : d1: DISTANCE ATOMS=1,2
     129             : 
     130             : eds: EDS ARG=d1 CENTER=2.0 PERIOD=50000 TEMP=1.0 IN_RESTART=restart.eds RESTART=YES
     131             : \endplumedfile
     132             : 
     133             : Read in a previous restart file and freeze the bias at the final level from the previous simulation
     134             : \plumedfile
     135             : d1: DISTANCE ATOMS=1,2
     136             : 
     137             : eds: EDS ARG=d1 CENTER=2.0 TEMP=1.0 IN_RESTART=restart.eds FREEZE
     138             : \endplumedfile
     139             : 
     140             : Read in a previous restart file and freeze the bias at the mean from the previous simulation
     141             : \plumedfile
     142             : d1: DISTANCE ATOMS=1,2
     143             : 
     144             : eds: EDS ARG=d1 CENTER=2.0 TEMP=1.0 IN_RESTART=restart.eds FREEZE MEAN
     145             : \endplumedfile
     146             : 
     147             : Read in a previous restart file and continue the bias, but use the mean from the previous run as the starting point
     148             : \plumedfile
     149             : d1: DISTANCE ATOMS=1,2
     150             : 
     151             : eds: EDS ARG=d1 CENTER=2.0 PERIOD=50000 TEMP=1.0 IN_RESTART=restart.eds FREEZE MEAN
     152             : \endplumedfile
     153             : 
     154             : 
     155             : */
     156             : //+ENDPLUMEDOC
     157             : 
     158             : class EDS : public Bias {
     159             : 
     160             : 
     161             : private:
     162             :   /*We will get this and store it once, since on-the-fly changing number of CVs will be fatal*/
     163             :   const unsigned int ncvs_;
     164             :   std::vector<double> center_;
     165             :   std::vector<Value*> center_values_;
     166             :   std::vector<double> scale_;
     167             :   std::vector<double> current_coupling_;
     168             :   std::vector<double> set_coupling_;
     169             :   std::vector<double> target_coupling_;
     170             :   std::vector<double> max_coupling_range_;
     171             :   std::vector<double> max_coupling_grad_;
     172             :   std::vector<double> coupling_rate_;
     173             :   std::vector<double> coupling_accum_;
     174             :   std::vector<double> means_;
     175             :   std::vector<double> differences_;
     176             :   std::vector<double> alpha_vector_;
     177             :   std::vector<double> alpha_vector_2_;
     178             :   std::vector<double> ssds_;
     179             :   std::vector<double> step_size_;
     180             :   std::vector<Value*> out_coupling_;
     181             :   Matrix<double> covar_;
     182             :   Matrix<double> covar2_;
     183             :   Matrix<double> lm_inv_;
     184             :   std::string in_restart_name_;
     185             :   std::string out_restart_name_;
     186             :   std::string fmt_;
     187             :   OFile out_restart_;
     188             :   IFile in_restart_;
     189             :   bool b_c_values_;
     190             :   bool b_adaptive_;
     191             :   bool b_freeze_;
     192             :   bool b_equil_;
     193             :   bool b_ramp_;
     194             :   bool b_covar_;
     195             :   bool b_restart_;
     196             :   bool b_write_restart_;
     197             :   bool b_hard_c_range_;
     198             :   bool b_lm_;
     199             :   int seed_;
     200             :   int update_period_;
     201             :   int avg_coupling_count_;
     202             :   int update_calls_;
     203             :   double kbt_;
     204             :   double c_range_increase_f_;
     205             :   double multi_prop_;
     206             :   double lm_mixing_par_;
     207             :   Random rand_;
     208             :   Value* value_force2_;
     209             : 
     210             :   /*read input restart. b_mean sets if we use mean or final value for freeze*/
     211             :   void readInRestart(const bool b_mean);
     212             :   /*setup output restart*/
     213             :   void setupOutRestart();
     214             :   /*write output restart*/
     215             :   void writeOutRestart();
     216             :   void update_statistics();
     217             :   void calc_lm_step_size();
     218             :   void calc_covar_step_size();
     219             :   void calc_ssd_step_size();
     220             :   void reset_statistics();
     221             :   void update_bias();
     222             :   void apply_bias();
     223             : 
     224             : public:
     225             :   explicit EDS(const ActionOptions&);
     226             :   void calculate();
     227             :   void update();
     228             :   void turnOnDerivatives();
     229             :   static void registerKeywords(Keywords& keys);
     230             :   ~EDS();
     231             : };
     232             : 
     233        7370 : PLUMED_REGISTER_ACTION(EDS,"EDS")
     234             : 
     235           8 : void EDS::registerKeywords(Keywords& keys) {
     236           8 :   Bias::registerKeywords(keys);
     237          16 :   keys.use("ARG");
     238          32 :   keys.add("optional","CENTER","The desired centers (equilibrium values) which will be sought during the adaptive linear biasing. This is for fixed values");
     239          32 :   keys.add("optional","CENTER_ARG","The desired centers (equilibrium values) which will be sought during the adaptive linear biasing. "
     240             :            "CENTER_ARG is for calculated centers, e.g. from a CV or analysis. ");
     241             : 
     242          32 :   keys.add("optional","PERIOD","Steps over which to adjust bias for adaptive or ramping");
     243          40 :   keys.add("compulsory","RANGE","25.0","The (starting) maximum increase in coupling constant per PERIOD (in \\f$k_B T\\f$/[BIAS_SCALE unit]) for each CV based");
     244          40 :   keys.add("compulsory","INCREASE_FACTOR","1.0","Factor by which to increase RANGE every time coupling exceeds RANGE. RANGE is the max prefactor for increasing coupling in a given PERIOD.");
     245          40 :   keys.add("compulsory","SEED","0","Seed for random order of changing bias");
     246          40 :   keys.add("compulsory","INIT","0","Starting value for coupling constant");
     247          40 :   keys.add("compulsory","FIXED","0","Fixed target values for coupling constant. Non-adaptive.");
     248          32 :   keys.add("optional","BIAS_SCALE","A divisor to set the units of the bias. "
     249             :            "If not set, this will be the experimental value by default (as is done in White and Voth 2014).");
     250          32 :   keys.add("optional","TEMP","The system temperature. If not provided will be taken from MD code (if available)");
     251          32 :   keys.add("optional","MULTI_PROP","What proportion of dimensions to update at each step. "
     252             :            "Must be in interval [1,0), where 1 indicates all and any other indicates a stochastic update. "
     253             :            "If not set, default is 1 / N, where N is the number of CVs. ");
     254             : 
     255          24 :   keys.addFlag("LM",false,"Use Levenberg-Marquadt algorithm along with simultaneous keyword. Otherwise use gradient descent.");
     256          24 :   keys.addFlag("LM_MIXING","1","Initial mixing parameter when using Levenberg-Marquadt minimization.");
     257             : 
     258          32 :   keys.add("optional","RESTART_FMT","the format that should be used to output real numbers in EDS restarts");
     259          32 :   keys.add("optional","OUT_RESTART","Output file for all information needed to continue EDS simulation. "
     260             :            "If you have the RESTART directive set (global or for EDS), this file will be appended to. "
     261             :            "Note that the header will be printed again if appending.");
     262          32 :   keys.add("optional","IN_RESTART","Read this file to continue an EDS simulation. "
     263             :            "If same as OUT_RESTART and you have not set the RESTART directive, the file will be backed-up and overwritten with new output. "
     264             :            "If you do have the RESTART flag set and it is the same name as OUT_RESTART, this file will be appended.");
     265             : 
     266          24 :   keys.addFlag("RAMP",false,"Slowly increase bias constant to a fixed value");
     267          24 :   keys.addFlag("COVAR",false,"Utilize the covariance matrix when updating the bias. Default Off, but may be enabled due to other options");
     268          24 :   keys.addFlag("FREEZE",false,"Fix bias at current level (only used for restarting).");
     269          24 :   keys.addFlag("MEAN",false,"Instead of using final bias level from restart, use average. Can only be used in conjunction with FREEZE");
     270             : 
     271          16 :   keys.use("RESTART");
     272             : 
     273          32 :   keys.addOutputComponent("force2","default","squared value of force from the bias");
     274          32 :   keys.addOutputComponent("_coupling","default", "For each named CV biased, there will be a corresponding output CV_coupling storing the current linear bias prefactor.");
     275           8 : }
     276             : 
     277           7 : EDS::EDS(const ActionOptions&ao):
     278             :   PLUMED_BIAS_INIT(ao),
     279             :   ncvs_(getNumberOfArguments()),
     280             :   scale_(ncvs_,0.0),
     281           7 :   current_coupling_(ncvs_,0.0),
     282           7 :   set_coupling_(ncvs_,0.0),
     283           7 :   target_coupling_(ncvs_,0.0),
     284           7 :   max_coupling_range_(ncvs_,25.0),
     285           7 :   max_coupling_grad_(ncvs_,0.0),
     286           7 :   coupling_rate_(ncvs_,1.0),
     287           7 :   coupling_accum_(ncvs_,0.0),
     288           7 :   means_(ncvs_,0.0),
     289           7 :   step_size_(ncvs_,0.0),
     290           7 :   out_coupling_(ncvs_,NULL),
     291             :   in_restart_name_(""),
     292             :   out_restart_name_(""),
     293             :   fmt_("%f"),
     294             :   b_adaptive_(true),
     295             :   b_freeze_(false),
     296             :   b_equil_(true),
     297             :   b_ramp_(false),
     298             :   b_covar_(false),
     299             :   b_restart_(false),
     300             :   b_write_restart_(false),
     301             :   b_hard_c_range_(false),
     302             :   b_lm_(false),
     303             :   seed_(0),
     304             :   update_period_(0),
     305             :   avg_coupling_count_(1),
     306             :   update_calls_(0),
     307             :   kbt_(0.0),
     308             :   c_range_increase_f_(1.0),
     309             :   multi_prop_(-1.0),
     310             :   lm_mixing_par_(0.1),
     311         147 :   value_force2_(NULL)
     312             : {
     313           7 :   double temp=-1.0;
     314           7 :   bool b_mean=false;
     315             : 
     316          14 :   addComponent("force2");
     317          14 :   componentIsNotPeriodic("force2");
     318          14 :   value_force2_ = getPntrToComponent("force2");
     319             : 
     320          29 :   for(unsigned int i = 0; i<ncvs_; i++) {
     321          11 :     std::string comp = getPntrToArgument(i)->getName() + "_coupling";
     322          11 :     addComponent(comp);
     323          11 :     componentIsNotPeriodic(comp);
     324          11 :     out_coupling_[i]=getPntrToComponent(comp);
     325             :   }
     326             : 
     327          14 :   parseVector("CENTER",center_);
     328          14 :   parseArgumentList("CENTER_ARG",center_values_);
     329          14 :   parseVector("BIAS_SCALE", scale_);
     330          14 :   parseVector("RANGE",max_coupling_range_);
     331          14 :   parseVector("FIXED",target_coupling_);
     332          14 :   parseVector("INIT",set_coupling_);
     333          14 :   parse("PERIOD",update_period_);
     334          14 :   parse("INCREASE_FACTOR",c_range_increase_f_);
     335          14 :   parse("TEMP",temp);
     336          14 :   parse("SEED",seed_);
     337          14 :   parse("MULTI_PROP",multi_prop_);
     338          14 :   parse("LM_MIXING",lm_mixing_par_);
     339          14 :   parse("RESTART_FMT", fmt_);
     340          14 :   fmt_ = " " + fmt_;//add space since parse strips them
     341          14 :   parse("OUT_RESTART",out_restart_name_);
     342          14 :   parseFlag("LM",b_lm_);
     343          14 :   parseFlag("RAMP",b_ramp_);
     344          14 :   parseFlag("FREEZE",b_freeze_);
     345          14 :   parseFlag("MEAN",b_mean);
     346          14 :   parseFlag("COVAR",b_covar_);
     347          14 :   parse("IN_RESTART",in_restart_name_);
     348           7 :   checkRead();
     349             : 
     350             :   /*
     351             :    * Things that are different when using changing centers:
     352             :    * 1. Scale
     353             :    * 2. The log file
     354             :    * 3. Reading Restarts
     355             :    */
     356             : 
     357           7 :   if(center_.size() == 0) {
     358           1 :     if(center_values_.size() == 0)
     359           0 :       error("Must set either CENTER or CENTER_ARG");
     360           1 :     else if(center_values_.size() != ncvs_)
     361           0 :       error("CENTER_ARG must contain the same number of variables as ARG");
     362           1 :     b_c_values_ = true;
     363           1 :     center_.resize(ncvs_);
     364           1 :     log.printf("  EDS will use possibly varying centers\n");
     365             :   } else {
     366           6 :     if(center_.size() != ncvs_)
     367           0 :       error("Must have same number of CENTER arguments as ARG arguments");
     368           6 :     else if(center_values_.size() != 0)
     369           0 :       error("You can only set CENTER or CENTER_ARG. Not both");
     370           6 :     b_c_values_ = false;
     371           6 :     log.printf("  EDS will use fixed centers\n");
     372             :   }
     373             : 
     374             : 
     375             : 
     376           7 :   log.printf("  setting scaling:");
     377           7 :   if(scale_.size() > 0  && scale_.size() < ncvs_) {
     378           0 :     error("the number of BIAS_SCALE values be the same as number of CVs");
     379           9 :   } else if(scale_.size() == 0 && b_c_values_) {
     380           0 :     log.printf(" Setting SCALE to be 1 for all CVs\n");
     381           0 :     scale_.resize(ncvs_);
     382           0 :     for(unsigned int i = 0; i < ncvs_; ++i)
     383           0 :       scale_[i] = 1;
     384           9 :   } else if(scale_.size() == 0 && !b_c_values_) {
     385           2 :     log.printf(" (default) ");
     386             : 
     387           2 :     scale_.resize(ncvs_);
     388          16 :     for(unsigned int i = 0; i < scale_.size(); i++) {
     389           4 :       if(center_[i]==0)
     390           0 :         error("BIAS_SCALE parameter has been set to CENTER value of 0 (as is default). This will divide by 0, so giving up. See doc for EDS bias");
     391           4 :       scale_[i] = center_[i];
     392             :     }
     393             :   } else {
     394          31 :     for(unsigned int i = 0; i < scale_.size(); i++)
     395          14 :       log.printf(" %f",scale_[i]);
     396             :   }
     397           7 :   log.printf("\n");
     398             : 
     399             : 
     400           7 :   if (b_lm_) {
     401           1 :     log.printf("  EDS will perform Levenberg-Marquardt minimization with mixing parameter = %f\n",lm_mixing_par_);
     402           1 :     differences_.resize(ncvs_);
     403           1 :     alpha_vector_.resize(ncvs_);
     404           1 :     alpha_vector_2_.resize(ncvs_);
     405           1 :     covar_.resize(ncvs_, ncvs_);
     406           1 :     covar2_.resize(ncvs_, ncvs_);
     407           1 :     lm_inv_.resize(ncvs_, ncvs_);
     408           3 :     covar2_*=0; lm_inv_*=0;
     409           1 :     if(multi_prop_ != 1) log.printf("     WARNING - doing LM minimization but MULTI_PROP!=1\n");
     410             :   }
     411           6 :   else if(b_covar_) {
     412           1 :     log.printf("  EDS will utilize covariance matrix for update steps\n");
     413           1 :     covar_.resize(ncvs_, ncvs_);
     414             :   } else {
     415           5 :     log.printf("  EDS will utilize variance for update steps\n");
     416           5 :     ssds_.resize(ncvs_);
     417             :   }
     418             : 
     419             : 
     420           7 :   if (b_mean == true and b_freeze_ == false) {
     421           0 :     error("EDS keyworkd MEAN can only be used along with keyword FREEZE");
     422             :   }
     423             : 
     424           7 :   if(in_restart_name_ != "") {
     425           2 :     b_restart_ = true;
     426           4 :     log.printf("  reading simulation information from file: %s\n",in_restart_name_.c_str());
     427           2 :     readInRestart(b_mean);
     428             :   } else {
     429             : 
     430          10 :     if(temp>=0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp;
     431           0 :     else kbt_ = plumed.getAtoms().getKbT();
     432             : 
     433             :     //in driver, this results in kbt of 0
     434           5 :     if(kbt_ == 0) {
     435           0 :       error("  Unable to determine valid kBT. "
     436             :             "Could be because you are runnning from driver or MD didn't give temperature.\n"
     437             :             "Consider setting temperature manually with the TEMP keyword.");
     438           0 :       kbt_ = 1;
     439             :     }
     440             : 
     441           5 :     log.printf("  kBT = %f\n",kbt_);
     442           5 :     log.printf("  Updating every %i steps\n",update_period_);
     443             : 
     444           5 :     if(!b_c_values_) {
     445           4 :       log.printf("  with centers:");
     446          20 :       for(unsigned int i = 0; i< ncvs_; i++) {
     447          16 :         log.printf(" %f ",center_[i]);
     448             :       }
     449             :     } else {
     450           1 :       log.printf("  with actions centers:");
     451           3 :       for(unsigned int i = 0; i< ncvs_; i++) {
     452           3 :         log.printf(" %s ",center_values_[i]->getName().c_str());
     453             :         //add dependency on these actions
     454           1 :         addDependency(center_values_[i]->getPntrToAction());
     455             :       }
     456             :     }
     457             : 
     458           5 :     log.printf("\n  with initial ranges / rates:\n");
     459          37 :     for(unsigned int i = 0; i<max_coupling_range_.size(); i++) {
     460             :       //this is just an empirical guess. Bigger range, bigger grads. Less frequent updates, bigger changes
     461             :       //
     462             :       //using the current maxing out scheme, max_coupling_range is the biggest step that can be taken in any given interval
     463           9 :       max_coupling_range_[i]*=kbt_;
     464           9 :       max_coupling_grad_[i] = max_coupling_range_[i];
     465          27 :       log.printf("    %f / %f\n",max_coupling_range_[i],max_coupling_grad_[i]);
     466             :     }
     467             : 
     468           5 :     if(seed_>0) {
     469           1 :       log.printf("  setting random seed = %i",seed_);
     470           1 :       rand_.setSeed(seed_);
     471             :     }
     472             : 
     473          23 :     for(unsigned int i = 0; i<ncvs_; ++i) if(target_coupling_[i]!=0.0) b_adaptive_=false;
     474             : 
     475           5 :     if(!b_adaptive_) {
     476           1 :       if(b_ramp_) {
     477           1 :         log.printf("  ramping up coupling constants over %i steps\n",update_period_);
     478             :       }
     479             : 
     480           1 :       log.printf("  with starting coupling constants");
     481           5 :       for(unsigned int i = 0; i<set_coupling_.size(); i++) log.printf(" %f",set_coupling_[i]);
     482           1 :       log.printf("\n");
     483           1 :       log.printf("  and final coupling constants");
     484           5 :       for(unsigned int i = 0; i<target_coupling_.size(); i++) log.printf(" %f",target_coupling_[i]);
     485           1 :       log.printf("\n");
     486             :     }
     487             : 
     488             :     //now do setup
     489           5 :     if(b_ramp_) {
     490           1 :       update_period_*=-1;
     491             :     }
     492             : 
     493          37 :     for(unsigned int i = 0; i<set_coupling_.size(); i++) current_coupling_[i] = set_coupling_[i];
     494             : 
     495             :     // if b_adaptive_, then first half will be used for equilibrating and second half for statistics
     496           5 :     if(update_period_>0) {
     497           4 :       update_period_ /= 2;
     498             :     }
     499             : 
     500             : 
     501             :   }
     502             : 
     503           7 :   if(b_freeze_) {
     504           1 :     b_adaptive_=false;
     505           1 :     update_period_ = 0;
     506           1 :     if (b_mean) {
     507           1 :       log.printf("  freezing bias at the average level from the restart file\n");
     508             :     } else {
     509           0 :       log.printf("  freezing bias at current level\n");
     510             :     }
     511             :   }
     512             : 
     513           7 :   if(multi_prop_ == -1.0) {
     514           5 :     log.printf("  Will update each dimension stochastically with probability 1 / number of CVs\n");
     515           5 :     multi_prop_ = 1.0 / ncvs_;
     516           2 :   } else if(multi_prop_ > 0 && multi_prop_ <= 1.0) {
     517           2 :     log.printf("  Will update each dimension stochastically with probability %f\n", multi_prop_);
     518             :   } else {
     519           0 :     error("  MULTI_PROP must be between 0 and 1\n");
     520             :   }
     521             : 
     522           7 :   if(out_restart_name_.length()>0) {
     523          14 :     log.printf("  writing restart information every %i steps to file %s with format %s\n",abs(update_period_),out_restart_name_.c_str(), fmt_.c_str());
     524           7 :     b_write_restart_ = true;
     525           7 :     setupOutRestart();
     526             :   }
     527             : 
     528          21 :   log<<"  Bibliography "<<plumed.cite("White and Voth, J. Chem. Theory Comput. 10 (8), 3023-3030 (2014)")<<"\n";
     529          21 :   log<<"  Bibliography "<<plumed.cite("G. M. Hocky, T. Dannenhoffer-Lafage, G. A. Voth, J. Chem. Theory Comput. 13 (9), 4593-4603 (2017)")<<"\n";
     530           7 : }
     531             : 
     532           2 : void EDS::readInRestart(const bool b_mean) {
     533           2 :   int adaptive_i=0;
     534             : 
     535           2 :   in_restart_.open(in_restart_name_);
     536             : 
     537           4 :   if(in_restart_.FieldExist("kbt")) {
     538           4 :     in_restart_.scanField("kbt",kbt_);
     539           0 :   } else { error("No field 'kbt' in restart file"); }
     540           2 :   log.printf("  with kBT = %f\n",kbt_);
     541             : 
     542           4 :   if(in_restart_.FieldExist("update_period")) {
     543           4 :     in_restart_.scanField("update_period",update_period_);
     544           0 :   } else { error("No field 'update_period' in restart file"); }
     545           2 :   log.printf("  Updating every %i steps\n",update_period_);
     546             : 
     547           4 :   if(in_restart_.FieldExist("adaptive")) {
     548             :     //note, no version of scanField for boolean
     549           4 :     in_restart_.scanField("adaptive",adaptive_i);
     550           0 :   } else { error("No field 'adaptive' in restart file"); }
     551           2 :   b_adaptive_ = bool(adaptive_i);
     552             : 
     553           4 :   if(in_restart_.FieldExist("seed")) {
     554           4 :     in_restart_.scanField("seed",seed_);
     555           0 :   } else { error("No field 'seed' in restart file"); }
     556           2 :   if(seed_>0) {
     557           0 :     log.printf("  setting random seed = %i",seed_);
     558           0 :     rand_.setSeed(seed_);
     559             :   }
     560             : 
     561             :   double time, tmp;
     562           2 :   std::vector<double> avg_bias = std::vector<double>(center_.size());
     563             :   unsigned int N = 0;
     564             :   std::string cv_name;
     565             : 
     566          24 :   while(in_restart_.scanField("time",time)) {
     567             : 
     568          30 :     for(unsigned int i = 0; i<ncvs_; ++i) {
     569             :       cv_name = getPntrToArgument(i)->getName();
     570          20 :       in_restart_.scanField(cv_name + "_center", set_coupling_[i]);
     571          20 :       in_restart_.scanField(cv_name + "_set", set_coupling_[i]);
     572          20 :       in_restart_.scanField(cv_name + "_target",target_coupling_[i]);
     573          20 :       in_restart_.scanField(cv_name + "_coupling",current_coupling_[i]);
     574          20 :       in_restart_.scanField(cv_name + "_maxrange",max_coupling_range_[i]);
     575          20 :       in_restart_.scanField(cv_name + "_maxgrad",max_coupling_grad_[i]);
     576          20 :       in_restart_.scanField(cv_name + "_accum",coupling_accum_[i]);
     577          20 :       in_restart_.scanField(cv_name + "_mean",means_[i]);
     578             :       //unused due to difference between covar/nocovar
     579          20 :       in_restart_.scanField(cv_name + "_std",tmp);
     580             : 
     581          20 :       avg_bias[i] += current_coupling_[i];
     582             :     }
     583          10 :     N++;
     584             : 
     585          10 :     in_restart_.scanField();
     586             :   }
     587             : 
     588             : 
     589           2 :   log.printf("  with centers:");
     590          10 :   for(unsigned int i = 0; i<center_.size(); i++) {
     591           4 :     log.printf(" %f",center_[i]);
     592             :   }
     593           2 :   log.printf("\n  and scaling:");
     594          10 :   for(unsigned int i = 0; i<scale_.size(); i++) {
     595           4 :     log.printf(" %f",scale_[i]);
     596             :   }
     597             : 
     598           2 :   log.printf("\n  with initial ranges / rates:\n");
     599          10 :   for(unsigned int i = 0; i<max_coupling_range_.size(); i++) {
     600           6 :     log.printf("    %f / %f\n",max_coupling_range_[i],max_coupling_grad_[i]);
     601             :   }
     602             : 
     603           2 :   if(!b_adaptive_ && update_period_<0) {
     604           0 :     log.printf("  ramping up coupling constants over %i steps\n",-update_period_);
     605             :   }
     606             : 
     607           2 :   if(b_mean) {
     608           1 :     log.printf("Loaded in averages for coupling constants...\n");
     609           6 :     for(unsigned int i = 0; i<current_coupling_.size(); i++) current_coupling_[i] = avg_bias[i] / N;
     610           6 :     for(unsigned int i = 0; i<current_coupling_.size(); i++) set_coupling_[i] = avg_bias[i] / N;
     611             :   }
     612             : 
     613           2 :   log.printf("  with current coupling constants:\n    ");
     614          10 :   for(unsigned int i = 0; i<current_coupling_.size(); i++) log.printf(" %f",current_coupling_[i]);
     615           2 :   log.printf("\n");
     616           2 :   log.printf("  with initial coupling constants:\n    ");
     617          10 :   for(unsigned int i = 0; i<set_coupling_.size(); i++) log.printf(" %f",set_coupling_[i]);
     618           2 :   log.printf("\n");
     619           2 :   log.printf("  and final coupling constants:\n    ");
     620          10 :   for(unsigned int i = 0; i<target_coupling_.size(); i++) log.printf(" %f",target_coupling_[i]);
     621           2 :   log.printf("\n");
     622             : 
     623           2 :   in_restart_.close();
     624           2 : }
     625             : 
     626           7 : void EDS::setupOutRestart() {
     627           7 :   out_restart_.link(*this);
     628           7 :   out_restart_.fmtField(fmt_);
     629           7 :   out_restart_.open(out_restart_name_);
     630             :   out_restart_.setHeavyFlush();
     631             : 
     632          21 :   out_restart_.addConstantField("adaptive").printField("adaptive",b_adaptive_);
     633          21 :   out_restart_.addConstantField("update_period").printField("update_period",update_period_);
     634          21 :   out_restart_.addConstantField("seed").printField("seed",seed_);
     635          21 :   out_restart_.addConstantField("kbt").printField("kbt",kbt_);
     636             : 
     637           7 : }
     638             : 
     639          28 : void EDS::writeOutRestart() {
     640             :   std::string cv_name;
     641          56 :   out_restart_.printField("time",getTimeStep()*getStep());
     642             : 
     643         116 :   for(unsigned int i = 0; i<ncvs_; ++i) {
     644             :     cv_name = getPntrToArgument(i)->getName();
     645          88 :     out_restart_.printField(cv_name + "_center",center_[i]);
     646          88 :     out_restart_.printField(cv_name + "_set",set_coupling_[i]);
     647          88 :     out_restart_.printField(cv_name + "_target",target_coupling_[i]);
     648          88 :     out_restart_.printField(cv_name + "_coupling",current_coupling_[i]);
     649          88 :     out_restart_.printField(cv_name + "_maxrange",max_coupling_range_[i]);
     650          88 :     out_restart_.printField(cv_name + "_maxgrad",max_coupling_grad_[i]);
     651          88 :     out_restart_.printField(cv_name + "_accum",coupling_accum_[i]);
     652          88 :     out_restart_.printField(cv_name + "_mean",means_[i]);
     653          44 :     if(!b_covar_ && !b_lm_)
     654          40 :       out_restart_.printField(cv_name + "_std",ssds_[i] / (fmax(1, update_calls_ - 1)));
     655             :     else
     656          48 :       out_restart_.printField(cv_name + "_std",covar_(i,i) / (fmax(1, update_calls_ - 1)));
     657             : 
     658             :   }
     659          28 :   out_restart_.printField();
     660          28 : }
     661             : 
     662             : 
     663             : 
     664          35 : void EDS::calculate() {
     665             : 
     666             :   //get center values from action if necessary
     667          35 :   if(b_c_values_)
     668          15 :     for(unsigned int i = 0; i < ncvs_; ++i)
     669          15 :       center_[i] = center_values_[i]->get();
     670             : 
     671          35 :   apply_bias();
     672             : 
     673             :   //adjust parameters according to EDS recipe
     674          35 :   update_calls_++;
     675             : 
     676             :   //check if we're ramping or doing normal updates and then restart if needed. The ramping check
     677             :   //is complicated because we could be frozen, finished ramping or not ramping.
     678             :   //The + 2 is so we have an extra line showing that the bias isn't changing (for my sanity and yours)
     679          35 :   if( b_write_restart_) {
     680          63 :     if(getStep() == 0 ||
     681          32 :         ( (update_period_ < 0 && !b_freeze_ && update_calls_ <= fabs(update_period_) + 2) ||
     682          20 :           (update_period_ > 0 && update_calls_ % update_period_ == 0 ) ) )
     683          28 :       writeOutRestart();
     684             :   }
     685             : 
     686             :   int b_finished_equil_flag = 1;
     687             : 
     688             :   //assume forces already applied and saved
     689             : 
     690             : 
     691             :   //are we ramping to a constant value and not done equilibrating?
     692          35 :   if(update_period_ < 0) {
     693           5 :     if(update_calls_ <= fabs(update_period_) && !b_freeze_) {
     694           6 :       for(unsigned int i = 0; i < ncvs_; ++i)
     695           8 :         current_coupling_[i] += (target_coupling_[i]-set_coupling_[i])/fabs(update_period_);
     696             :     }
     697             :     //make sure we don't reset update calls
     698             :     b_finished_equil_flag = 0;
     699          30 :   } else if(update_period_ == 0) { //do we have a no-update case?
     700             :     //not updating
     701             :     //pass
     702          25 :   } else if(!b_equil_) {
     703             :     //if we aren't wating for the bias to equilibrate, collect data
     704          10 :     update_statistics();
     705             :   } else {
     706             :     // equilibrating
     707             :     //check if we've reached the setpoint
     708          69 :     for(unsigned int i = 0; i < ncvs_; ++i) {
     709         129 :       if(coupling_rate_[i] == 0 || pow(current_coupling_[i] - set_coupling_[i],2) < pow(coupling_rate_[i],2)) {
     710          16 :         b_finished_equil_flag &= 1;
     711             :       }
     712             :       else {
     713          22 :         current_coupling_[i] += coupling_rate_[i];
     714             :         b_finished_equil_flag = 0;
     715             :       }
     716             :     }
     717             :   }
     718             : 
     719             :   //Update max coupling range if not hard
     720          35 :   if(!b_hard_c_range_) {
     721         145 :     for(unsigned int i = 0; i < ncvs_; ++i) {
     722         165 :       if(fabs(current_coupling_[i])>max_coupling_range_[i]) {
     723           0 :         max_coupling_range_[i]*=c_range_increase_f_;
     724           0 :         max_coupling_grad_[i]*=c_range_increase_f_;
     725             :       }
     726             :     }
     727             :   }
     728             : 
     729             :   //reduce all the flags
     730          35 :   if(b_equil_ && b_finished_equil_flag) {
     731          11 :     b_equil_ = false;
     732          11 :     update_calls_ = 0;
     733             :   }
     734             : 
     735             :   //Now we update coupling constant, if necessary
     736          35 :   if(!b_equil_ && update_period_ > 0 && update_calls_ == update_period_ && !b_freeze_) {
     737           9 :     update_bias();
     738           9 :     update_calls_ = 0;
     739           9 :     avg_coupling_count_++;
     740           9 :     b_equil_ = true; //back to equilibration now
     741             :   } //close update if
     742             : 
     743             :   //pass couplings out so they are accessible
     744         145 :   for(unsigned int i = 0; i<ncvs_; ++i) {
     745         165 :     out_coupling_[i]->set(current_coupling_[i]);
     746             :   }
     747             : 
     748             : 
     749          35 : }
     750             : 
     751          35 : void EDS::apply_bias() {
     752             :   //Compute linear force as in "restraint"
     753             :   double ene = 0, totf2 = 0, cv, m, f;
     754             : 
     755         145 :   for(unsigned int i = 0; i < ncvs_; ++i) {
     756          55 :     cv = difference(i, center_[i], getArgument(i));
     757          55 :     m = current_coupling_[i];
     758          55 :     f = -m;
     759          55 :     ene += m*cv;
     760             :     setOutputForce(i,f);
     761          55 :     totf2 += f*f;
     762             :   };
     763             : 
     764             :   setBias(ene);
     765          35 :   value_force2_->set(totf2);
     766             : 
     767          35 : }
     768             : 
     769          10 : void EDS::update_statistics()  {
     770             :   double s;
     771          10 :   std::vector<double> deltas(ncvs_);
     772             :   //Welford, West, and Hanso online variance method
     773          46 :   for(unsigned int i = 0; i < ncvs_; ++i)  {
     774          36 :     deltas[i] = difference(i,means_[i],getArgument(i));
     775          36 :     means_[i] += deltas[i]/fmax(1,update_calls_);
     776          18 :     if(!b_covar_ && !b_lm_)
     777          24 :       ssds_[i] += deltas[i]*difference(i,means_[i],getArgument(i));
     778             :   }
     779          10 :   if(b_covar_ || b_lm_) {
     780          28 :     for(unsigned int i = 0; i < ncvs_; ++i) {
     781          60 :       for(unsigned int j = i; j < ncvs_; ++j) {
     782          96 :         s = (update_calls_ - 1) * deltas[i] * deltas[j] / update_calls_ / update_calls_ - covar_(i,j) / update_calls_;
     783          24 :         covar_(i,j) += s;
     784             :         //do this so we don't double count
     785          24 :         covar_(j,i) = covar_(i,j);
     786             :       }
     787             :     }
     788             :   }
     789          10 : }
     790             : 
     791          15 : void EDS::reset_statistics() {
     792          81 :   for(unsigned int i = 0; i < ncvs_; ++i)  {
     793          66 :     means_[i] = 0;
     794          33 :     if(!b_covar_ && !b_lm_)
     795           6 :       ssds_[i] = 0;
     796             :   }
     797          15 :   if(b_covar_ || b_lm_)
     798          63 :     for(unsigned int i = 0; i < ncvs_; ++i)
     799         189 :       for(unsigned int j = 0; j < ncvs_; ++j)
     800          81 :         covar_(i,j) = 0;
     801          15 : }
     802             : 
     803           1 : void EDS::calc_lm_step_size() {
     804             :   //calulcate step size
     805             :   //uses scale here, which by default is center
     806             : 
     807           1 :   mult(covar_,covar_,covar2_);
     808           7 :   for(unsigned int i = 0; i< ncvs_; ++i) {
     809          12 :     differences_[i] = difference(i, center_[i], means_[i]);
     810           3 :     covar2_[i][i]+=lm_mixing_par_*covar2_[i][i];
     811             :   }
     812             : 
     813             : // "step_size_vec" = 2*inv(covar*covar+ lambda diag(covar*covar))*covar*(mean-center)
     814           1 :   mult(covar_,differences_,alpha_vector_);
     815           1 :   Invert(covar2_,lm_inv_);
     816           1 :   mult(lm_inv_,alpha_vector_,alpha_vector_2_);
     817             : 
     818           7 :   for(unsigned int i = 0; i< ncvs_; ++i) {
     819          12 :     step_size_[i] = 2 * alpha_vector_2_[i] / kbt_ / scale_[i];
     820             :   }
     821             : 
     822           1 : }
     823             : 
     824           2 : void EDS::calc_covar_step_size() {
     825             :   //calulcate step size
     826             :   //uses scale here, which by default is center
     827             :   double tmp;
     828          14 :   for(unsigned int i = 0; i< ncvs_; ++i) {
     829             :     tmp = 0;
     830          42 :     for(unsigned int j = 0; j < ncvs_; ++j)
     831          72 :       tmp += difference(i, center_[i], means_[i]) * covar_(i,j);
     832          18 :     step_size_[i] = 2 * tmp / kbt_ / scale_[i] * update_calls_ / fmax(1,update_calls_ - 1);
     833             :   }
     834             : 
     835           2 : }
     836             : 
     837           6 : void EDS::calc_ssd_step_size() {
     838             :   double tmp;
     839          18 :   for(unsigned int i = 0; i< ncvs_; ++i) {
     840          30 :     tmp = 2. * difference(i, center_[i], means_[i]) * ssds_[i] / fmax(1,update_calls_ - 1);
     841          18 :     step_size_[i] = tmp / kbt_/scale_[i];
     842             :   }
     843           6 : }
     844             : 
     845           9 : void EDS::update_bias()
     846             : {
     847           9 :   log.flush();
     848           9 :   if (b_lm_)
     849             :   {
     850           1 :     log.flush();
     851           1 :     calc_lm_step_size();
     852             :   }
     853           8 :   else if(b_covar_)
     854           2 :     calc_covar_step_size();
     855             :   else
     856           6 :     calc_ssd_step_size();
     857             : 
     858          39 :   for(unsigned int i = 0; i< ncvs_; ++i) {
     859             : 
     860             :     //multidimesional stochastic step
     861          15 :     if(ncvs_ == 1 || (rand_.RandU01() < (multi_prop_) ) ) {
     862             : 
     863          45 :       double proposed_coupling_accum = coupling_accum_[i] + step_size_[i] * step_size_[i];
     864          15 :       double proposed_coupling_prefactor = max_coupling_range_[i]/sqrt(proposed_coupling_accum);
     865          15 :       double proposed_coupling_change = proposed_coupling_prefactor*step_size_[i];
     866             : 
     867             :       //check if update to coupling exceeds maximum possible gradient
     868          15 :       double coupling_change = copysign(fmin(fabs(proposed_coupling_change), max_coupling_grad_[i]), proposed_coupling_change);
     869             : 
     870          15 :       step_size_[i] = coupling_change/proposed_coupling_prefactor;
     871          30 :       coupling_accum_[i] += step_size_[i] * step_size_[i];
     872             : 
     873             :       //equation 5 in White and Voth, JCTC 2014
     874             :       //no negative sign because it's in step_size
     875          15 :       set_coupling_[i] += coupling_change;
     876          45 :       coupling_rate_[i] = (set_coupling_[i]-current_coupling_[i])/update_period_;
     877             : 
     878             :     } else {
     879             :       //do not change the bias
     880           0 :       coupling_rate_[i] = 0;
     881             :     }
     882             : 
     883             :     //reset means/vars
     884          15 :     reset_statistics();
     885             : 
     886             :   }
     887           9 : }
     888             : 
     889             : 
     890             : 
     891          35 : void EDS::update() {
     892             :   //pass
     893          35 : }
     894             : 
     895          28 : EDS::~EDS() {
     896           7 :   out_restart_.close();
     897          14 : }
     898             : 
     899           0 : void EDS::turnOnDerivatives() {
     900             :   // do nothing
     901             :   // this is to avoid errors triggered when a bias is used as a CV
     902             :   // (This is done in ExtendedLagrangian.cpp)
     903           0 : }
     904             : 
     905             : 
     906             : }
     907        5517 : }//close the 2 namespaces

Generated by: LCOV version 1.14