LCOV - code coverage report
Current view: top level - bias - ABMD.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 59 59 100.0 %
Date: 2020-11-18 11:20:57 Functions: 10 11 90.9 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2019 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 "Bias.h"
      23             : #include "tools/Random.h"
      24             : #include "ActionRegister.h"
      25             : #include <ctime>
      26             : 
      27             : using namespace std;
      28             : 
      29             : namespace PLMD {
      30             : namespace bias {
      31             : 
      32             : //+PLUMEDOC BIAS ABMD
      33             : /*
      34             : Adds a ratchet-and-pawl like restraint on one or more variables.
      35             : 
      36             : This action can be used to evolve a system towards a target value in
      37             : CV space using an harmonic potential moving with the thermal fluctuations of the CV
      38             : \cite ballone \cite provasi10abmd \cite camilloni11abmd. The biasing potential in this
      39             : method is as follows:
      40             : 
      41             : \f$
      42             : V(\rho(t)) = \left \{ \begin{array}{ll} \frac{K}{2}\left(\rho(t)-\rho_m(t)\right)^2, &\rho(t)>\rho_m(t)\\
      43             :               0, & \rho(t)\le\rho_m(t), \end{array} \right .
      44             : \f$
      45             : 
      46             : 
      47             : where
      48             : 
      49             : 
      50             : \f$
      51             : \rho(t)=\left(CV(t)-TO\right)^2
      52             : \f$
      53             : 
      54             : 
      55             : and
      56             : 
      57             : 
      58             : \f$
      59             : \rho_m(t)=\min_{0\le\tau\le t}\rho(\tau)+\eta(t)
      60             : \f$.
      61             : 
      62             : The method is based on the introduction of a biasing potential which is zero when
      63             : the system is moving towards the desired arrival point and which damps the
      64             : fluctuations when the system attempts to move in the opposite direction. As in the
      65             : case of the ratchet and pawl system, propelled by thermal motion of the solvent
      66             : molecules, the biasing potential does not exert work on the system. \f$\eta(t)\f$ is
      67             : an additional white noise acting on the minimum position of the bias.
      68             : 
      69             : \par Examples
      70             : 
      71             : The following input sets up two biases, one on the distance between atoms 3 and 5
      72             : and another on the distance between atoms 2 and 4. The two target values are defined
      73             : using TO and the two strength using KAPPA. The total energy of the bias is printed.
      74             : \plumedfile
      75             : DISTANCE ATOMS=3,5 LABEL=d1
      76             : DISTANCE ATOMS=2,4 LABEL=d2
      77             : ABMD ARG=d1,d2 TO=1.0,1.5 KAPPA=5.0,5.0 LABEL=abmd
      78             : PRINT ARG=abmd.bias,abmd.d1_min,abmd.d2_min
      79             : \endplumedfile
      80             : 
      81             : */
      82             : //+ENDPLUMEDOC
      83             : 
      84           3 : class ABMD : public Bias {
      85             :   std::vector<double> to;
      86             :   std::vector<double> min;
      87             :   std::vector<double> kappa;
      88             :   std::vector<double> temp;
      89             :   std::vector<int> seed;
      90             :   vector<Random> random;
      91             : public:
      92             :   explicit ABMD(const ActionOptions&);
      93             :   void calculate();
      94             :   static void registerKeywords(Keywords& keys);
      95             : };
      96             : 
      97        6453 : PLUMED_REGISTER_ACTION(ABMD,"ABMD")
      98             : 
      99           2 : void ABMD::registerKeywords(Keywords& keys) {
     100           2 :   Bias::registerKeywords(keys);
     101           4 :   keys.use("ARG");
     102           8 :   keys.add("compulsory","TO","The array of target values");
     103           8 :   keys.add("compulsory","KAPPA","The array of force constants.");
     104           8 :   keys.add("optional","MIN","Array of starting values for the bias (set rho_m(t), otherwise it is set using the current value of ARG)");
     105           8 :   keys.add("optional","NOISE","Array of white noise intensities (add a temperature to the ABMD)");
     106           8 :   keys.add("optional","SEED","Array of seeds for the white noise (add a temperature to the ABMD)");
     107           8 :   keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential");
     108           8 :   keys.addOutputComponent("_min","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. "
     109             :                           " These quantities will be named with the arguments of the bias followed by "
     110             :                           "the character string _min. These quantities tell the user the minimum value assumed by rho_m(t).");
     111           2 : }
     112             : 
     113           1 : ABMD::ABMD(const ActionOptions&ao):
     114             :   PLUMED_BIAS_INIT(ao),
     115             :   to(getNumberOfArguments(),0.0),
     116             :   min(getNumberOfArguments(),-1.0),
     117             :   kappa(getNumberOfArguments(),0.0),
     118             :   temp(getNumberOfArguments(),0.0),
     119           1 :   seed(getNumberOfArguments(),time(0)),
     120           8 :   random(getNumberOfArguments())
     121             : {
     122             :   // Note : parseVector will check that number of arguments is correct
     123           2 :   parseVector("KAPPA",kappa);
     124           2 :   parseVector("MIN",min);
     125           3 :   if(min.size()==0) min.assign(getNumberOfArguments(),-1.0);
     126           1 :   if(min.size()!=getNumberOfArguments()) error("MIN array should have the same size as ARG array");
     127           2 :   parseVector("NOISE",temp);
     128           2 :   parseVector("SEED",seed);
     129           2 :   parseVector("TO",to);
     130           1 :   checkRead();
     131             : 
     132           1 :   log.printf("  min");
     133           5 :   for(unsigned i=0; i<min.size(); i++) log.printf(" %f",min[i]);
     134           1 :   log.printf("\n");
     135           1 :   log.printf("  to");
     136           5 :   for(unsigned i=0; i<to.size(); i++) log.printf(" %f",to[i]);
     137           1 :   log.printf("\n");
     138           1 :   log.printf("  with force constant");
     139           5 :   for(unsigned i=0; i<kappa.size(); i++) log.printf(" %f",kappa[i]);
     140           1 :   log.printf("\n");
     141             : 
     142           3 :   for(unsigned i=0; i<getNumberOfArguments(); i++) {
     143           1 :     std::string str_min=getPntrToArgument(i)->getName()+"_min";
     144           1 :     addComponent(str_min); componentIsNotPeriodic(str_min);
     145           1 :     if(min[i]!=-1.0) getPntrToComponent(str_min)->set(min[i]);
     146             :   }
     147           3 :   for(unsigned i=0; i<getNumberOfArguments(); i++) {random[i].setSeed(-seed[i]);}
     148           3 :   addComponent("force2"); componentIsNotPeriodic("force2");
     149           1 : }
     150             : 
     151             : 
     152           5 : void ABMD::calculate() {
     153             :   double ene=0.0;
     154             :   double totf2=0.0;
     155          15 :   for(unsigned i=0; i<getNumberOfArguments(); ++i) {
     156           5 :     const double cv=difference(i,to[i],getArgument(i));
     157           5 :     const double cv2=cv*cv;
     158           5 :     const double k=kappa[i];
     159             :     double noise=0.;
     160           5 :     double diff=temp[i];
     161           5 :     if(diff>0) {
     162           5 :       noise = 2.*random[i].Gaussian()*diff;
     163           5 :       if(cv2<=diff) { diff=0.; temp[i]=0.; }
     164             :     }
     165             : 
     166             :     // min < 0 means that the variable has not been used in the input file, so the current position of the CV is used
     167             :     // cv2 < min means that the collective variable is nearer to the target value than at any other previous time so
     168             :     // min is set to the CV value
     169           5 :     if(min[i]<0.||cv2<min[i]) {
     170           1 :       min[i] = cv2;
     171             :     } else {
     172             :       // otherwise a noise is added to the minimum value
     173           4 :       min[i] += noise;
     174           8 :       const double f = -2.*k*(cv2-min[i])*cv;
     175             :       setOutputForce(i,f);
     176           8 :       ene += 0.5*k*(cv2-min[i])*(cv2-min[i]);
     177           4 :       totf2+=f*f;
     178             :     }
     179          10 :     getPntrToComponent(i+1)->set(min[i]);
     180             :   }
     181             :   setBias(ene);
     182          10 :   getPntrToComponent("force2")->set(totf2);
     183           5 : }
     184             : 
     185             : }
     186        4839 : }
     187             : 
     188             : 

Generated by: LCOV version 1.13