LCOV - code coverage report
Current view: top level - generic - Average.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 36 38 94.7 %
Date: 2024-10-18 13:59:31 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2016-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 "core/ActionShortcut.h"
      23             : #include "core/ActionWithArguments.h"
      24             : #include "core/PlumedMain.h"
      25             : #include "core/ActionRegister.h"
      26             : 
      27             : //+PLUMEDOC GRIDCALC AVERAGE
      28             : /*
      29             : Calculate the ensemble average of a collective variable
      30             : 
      31             : The ensemble average for a non-periodic, collective variable, \f$s\f$ is given by the following expression:
      32             : 
      33             : \f[
      34             : \langle s \rangle = \frac{ \sum_{t'=0}^t w(t') s(t') }{ \sum_{t'=0}^t w(t') }
      35             : \f]
      36             : 
      37             : Here the sum runs over a the trajectory and \f$s(t')\f$ is used to denote the value of the collective variable
      38             : at time \f$t'\f$.  The final quantity evaluated is a weighted
      39             : average as the weights, \f$w(t')\f$, allow us to negate the effect any bias might have on the region of phase space
      40             : sampled by the system.  This is discussed in the section of the manual on \ref Analysis.
      41             : 
      42             : When the variable is periodic (e.g. \ref TORSION) and has a value, \f$s\f$, in \f$a \le s \le b\f$ the ensemble average is evaluated using:
      43             : 
      44             : \f[
      45             : \langle s \rangle = a + \frac{b - a}{2\pi} \arctan \left[ \frac{ \sum_{t'=0}^t w(t') \sin\left( \frac{2\pi [s(t')-a]}{b - a} \right) }{ \sum_{t'=0}^t w(t') \cos\left( \frac{2\pi [s(t')-a]}{b - a} \right) } \right]
      46             : \f]
      47             : 
      48             : \par Examples
      49             : 
      50             : The following example calculates the ensemble average for the distance between atoms 1 and 2
      51             : and output this to a file called COLVAR.  In this example it is assumed that no bias is acting
      52             : on the system and that the weights, \f$w(t')\f$ in the formulas above can thus all be set equal
      53             : to one.
      54             : 
      55             : \plumedfile
      56             : d1: DISTANCE ATOMS=1,2
      57             : d1a: AVERAGE ARG=d1
      58             : PRINT ARG=d1a FILE=colvar STRIDE=100
      59             : \endplumedfile
      60             : 
      61             : The following example calculates the ensemble average for the torsional angle involving atoms 1, 2, 3 and 4.
      62             : At variance with the previous example this quantity is periodic so the second formula in the above introduction
      63             : is used to calculate the average.  Furthermore, by using the CLEAR keyword we have specified that block averages
      64             : are to be calculated.  Consequently, after 100 steps all the information acquired thus far in the simulation is
      65             : forgotten and the process of averaging is begun again.  The quantities output in the colvar file are thus the
      66             : block averages taken over the first 100 frames of the trajectory, the block average over the second 100 frames
      67             : of trajectory and so on.
      68             : 
      69             : \plumedfile
      70             : t1: TORSION ATOMS=1,2,3,4
      71             : t1a: AVERAGE ARG=t1 CLEAR=100
      72             : PRINT ARG=t1a FILE=colvar STRIDE=100
      73             : \endplumedfile
      74             : 
      75             : This third example incorporates a bias.  Notice that the effect the bias has on the ensemble average is removed by taking
      76             : advantage of the \ref REWEIGHT_BIAS method.  The final ensemble averages output to the file are thus block ensemble averages for the
      77             : unbiased canonical ensemble at a temperature of 300 K.
      78             : 
      79             : \plumedfile
      80             : t1: TORSION ATOMS=1,2,3,4
      81             : RESTRAINT ARG=t1 AT=pi KAPPA=100.
      82             : ww: REWEIGHT_BIAS TEMP=300
      83             : t1a: AVERAGE ARG=t1 LOGWEIGHTS=ww CLEAR=100
      84             : PRINT ARG=t1a FILE=colvar STRIDE=100
      85             : \endplumedfile
      86             : 
      87             : */
      88             : //+ENDPLUMEDOC
      89             : 
      90             : namespace PLMD {
      91             : namespace generic {
      92             : 
      93             : class Average : public ActionShortcut {
      94             : public:
      95             :   static void registerKeywords( Keywords& keys );
      96             :   explicit Average( const ActionOptions& );
      97             : };
      98             : 
      99             : PLUMED_REGISTER_ACTION(Average,"AVERAGE")
     100             : 
     101           6 : void Average::registerKeywords( Keywords& keys ) {
     102           6 :   ActionShortcut::registerKeywords( keys );
     103          12 :   keys.addInputKeyword("compulsory","ARG","scalar/grid","the quantity that is being averaged");
     104          12 :   keys.add("optional","LOGWEIGHTS","the logarithm of the quantity to use as the weights when calculating averages");
     105          12 :   keys.add("compulsory","STRIDE","1","the frequency with which to store data for averaging");
     106          12 :   keys.add("compulsory","CLEAR","0","the frequency with whihc to clear the data that is being averaged");
     107          12 :   keys.add("optional","NORMALIZATION","keyword for old version of the code that is there to maintain back compatibility only. Adding this keyword does nothing");
     108          12 :   keys.setValueDescription("scalar/grid","the value of the average");
     109          24 :   keys.needsAction("COMBINE"); keys.needsAction("CUSTOM"); keys.needsAction("ONES"); keys.needsAction("ACCUMULATE");
     110           6 : }
     111             : 
     112           4 : Average::Average( const ActionOptions& ao ):
     113             :   Action(ao),
     114           4 :   ActionShortcut(ao)
     115             : {
     116             : 
     117          16 :   std::string lw; parse("LOGWEIGHTS",lw); std::string stride, clearstride; parse("STRIDE",stride); parse("CLEAR",clearstride);
     118           4 :   if( lw.length()>0 ) {
     119           2 :     readInputLine( getShortcutLabel() + "_wsum: COMBINE ARG=" + lw + " PERIODIC=NO");
     120           2 :     readInputLine( getShortcutLabel() + "_weight: CUSTOM ARG=" + getShortcutLabel() + "_wsum FUNC=exp(x) PERIODIC=NO");
     121           6 :   } else readInputLine( getShortcutLabel() + "_weight: ONES SIZE=1" );
     122             : 
     123           8 :   std::vector<std::string> arg; parseVector("ARG",arg);
     124           4 :   if( arg.size()!=1 ) error("should only be one argument to this action");
     125           4 :   std::vector<Value*> vals; ActionWithArguments::interpretArgumentList( arg, plumed.getActionSet(), this, vals );
     126             : 
     127           8 :   readInputLine( getShortcutLabel() + "_denom: ACCUMULATE ARG=" + getShortcutLabel() + "_weight STRIDE=" + stride + " CLEAR=" + clearstride );
     128           4 :   if( vals[0]->isPeriodic() ) {
     129           2 :     std::string lbound, ubound, pfactor; vals[0]->getDomain( lbound, ubound ); pfactor = "((" + ubound + "-" + lbound + ")/(pi+pi))";
     130           2 :     readInputLine( getShortcutLabel() + "_sin: CUSTOM ARG=" + arg[0] + "," + getShortcutLabel() + "_weight FUNC=y*sin((x-" + lbound + ")/" + pfactor + ") PERIODIC=NO");
     131           2 :     readInputLine( getShortcutLabel() + "_cos: CUSTOM ARG=" + arg[0] + "," + getShortcutLabel() + "_weight FUNC=y*cos((x-" + lbound + ")/" + pfactor + ") PERIODIC=NO");
     132           2 :     readInputLine( getShortcutLabel() + "_sinsum: ACCUMULATE ARG=" + getShortcutLabel() + "_sin STRIDE=" + stride + " CLEAR=" + clearstride );
     133           2 :     readInputLine( getShortcutLabel() + "_cossum: ACCUMULATE ARG=" + getShortcutLabel() + "_cos STRIDE=" + stride + " CLEAR=" + clearstride );
     134           2 :     readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_sinsum," + getShortcutLabel() + "_cossum," + getShortcutLabel() + "_denom FUNC=" + lbound + "+" + pfactor + "*atan2(x/z,y/z) PERIODIC=" + lbound +"," + ubound);
     135             :   } else {
     136           6 :     std::string normstr; parse("NORMALIZATION",normstr);
     137           6 :     if( normstr=="true" || normstr=="false" ) warning("NORMALIZATION is deprecated. You are advised to take this out of input files in future and use the new syntax with ACCUMULATE for unormalized data rather than the shortcut AVERAGE");
     138           3 :     else if( normstr.length()>0 ) error("NORMALIZATION=" + normstr + " is not valid PLUMED input.  If you want an unormalised 'average' use ACCUMULATE");
     139           6 :     readInputLine( getShortcutLabel() + "_prod: CUSTOM ARG=" + arg[0] + "," + getShortcutLabel() + "_weight FUNC=x*y PERIODIC=NO");
     140           3 :     if( normstr.length()==0 || normstr=="true" ) {
     141           6 :       readInputLine( getShortcutLabel() + "_numer: ACCUMULATE ARG=" + getShortcutLabel() + "_prod STRIDE=" + stride + " CLEAR=" + clearstride  );
     142           6 :       readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_numer," + getShortcutLabel() + "_denom FUNC=x/y PERIODIC=NO");
     143           0 :     } else if( normstr=="false" ) readInputLine( getShortcutLabel() + ": ACCUMULATE ARG=" + getShortcutLabel() + "_prod STRIDE=" + stride + " CLEAR=" + clearstride  );
     144           0 :     else plumed_error();
     145             :   }
     146           8 : }
     147             : 
     148             : }
     149             : }

Generated by: LCOV version 1.16