LCOV - code coverage report
Current view: top level - bias - ABMD.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 61 61 100.0 %
Date: 2024-10-18 13:59:31 Functions: 3 4 75.0 %

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

Generated by: LCOV version 1.16