LCOV - code coverage report
Current view: top level - symfunc - LocalAverage.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 53 53 100.0 %
Date: 2024-10-18 14:00:25 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-2017 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/ActionRegister.h"
      24             : #include "core/ActionWithValue.h"
      25             : #include "multicolvar/MultiColvarShortcuts.h"
      26             : #include "core/PlumedMain.h"
      27             : #include "core/ActionSet.h"
      28             : #include "CoordinationNumbers.h"
      29             : #include <string>
      30             : #include <cmath>
      31             : 
      32             : namespace PLMD {
      33             : namespace symfunc {
      34             : 
      35             : //+PLUMEDOC MCOLVARF LOCAL_AVERAGE
      36             : /*
      37             : Calculate averages over spherical regions centered on atoms
      38             : 
      39             : As is explained in <a href="http://www.youtube.com/watch?v=iDvZmbWE5ps"> this video </a> certain multicolvars
      40             : calculate one scalar quantity or one vector for each of the atoms in the system.  For example
      41             : \ref COORDINATIONNUMBER measures the coordination number of each of the atoms in the system and \ref Q4 measures
      42             : the 4th order Steinhardt parameter for each of the atoms in the system.  These quantities provide tell us something about
      43             : the disposition of the atoms in the first coordination sphere of each of the atoms of interest.  Lechner and Dellago \cite dellago-q6
      44             : have suggested that one can probe local order in a system by taking the average value of such symmetry functions over
      45             : the atoms within a spherical cutoff of each of these atoms in the systems.  When this is done with Steinhardt parameters
      46             : they claim this gives a coordinate that is better able to distinguish solid and liquid configurations of Lennard-Jones atoms.
      47             : 
      48             : You can calculate such locally averaged quantities within plumed by using the LOCAL_AVERAGE command.  This command calculates
      49             : the following atom-centered quantities:
      50             : 
      51             : \f[
      52             : s_i = \frac{ c_i + \sum_j \sigma(r_{ij})c_j }{ 1 + \sum_j \sigma(r_{ij}) }
      53             : \f]
      54             : 
      55             : where the \f$c_i\f$ and \f$c_j\f$ values can be for any one of the symmetry functions that can be calculated using plumed
      56             : multicolvars.  The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between
      57             : atoms \f$i\f$ and \f$j\f$.  Lechner and Dellago suggest that the parameters of this function should be set so that it the function is equal to one
      58             : when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise.
      59             : 
      60             : The \f$s_i\f$ quantities calculated using the above command can be again thought of as atom-centred symmetry functions.  They
      61             : thus operate much like multicolvars.  You can thus calculate properties of the distribution of \f$s_i\f$ values using MEAN, LESS_THAN, HISTOGRAM
      62             : and so on.  You can also probe the value of these averaged variables in regions of the box by using the command in tandem with the
      63             : \ref AROUND command.
      64             : 
      65             : \par Examples
      66             : 
      67             : This example input calculates the coordination numbers for all the atoms in the system.  These coordination numbers are then averaged over
      68             : spherical regions.  The number of averaged coordination numbers that are greater than 4 is then output to a file.
      69             : 
      70             : \plumedfile
      71             : COORDINATIONNUMBER SPECIES=1-64 D_0=1.3 R_0=0.2 LABEL=d1
      72             : LOCAL_AVERAGE ARG=d1 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MORE_THAN={RATIONAL R_0=4} LABEL=la
      73             : PRINT ARG=la.* FILE=colvar
      74             : \endplumedfile
      75             : 
      76             : This example input calculates the \f$q_4\f$ (see \ref Q4) vectors for each of the atoms in the system.  These vectors are then averaged
      77             : component by component over a spherical region.  The average value for this quantity is then outputeed to a file.  This calculates the
      78             : quantities that were used in the paper by Lechner and Dellago \cite dellago-q6
      79             : 
      80             : \plumedfile
      81             : Q4 SPECIES=1-64 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=q4
      82             : LOCAL_AVERAGE ARG=q4 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MEAN LABEL=la
      83             : PRINT ARG=la.* FILE=colvar
      84             : \endplumedfile
      85             : 
      86             : */
      87             : //+ENDPLUMEDOC
      88             : 
      89             : class LocalAverage : public ActionShortcut {
      90             : private:
      91             :   std::string getMomentumSymbol( const int& m ) const ;
      92             : public:
      93             :   static void registerKeywords( Keywords& keys );
      94             :   explicit LocalAverage(const ActionOptions&);
      95             : };
      96             : 
      97             : PLUMED_REGISTER_ACTION(LocalAverage,"LOCAL_AVERAGE")
      98             : 
      99          12 : void LocalAverage::registerKeywords( Keywords& keys ) {
     100          12 :   CoordinationNumbers::shortcutKeywords( keys );
     101          24 :   keys.needsAction("ONES"); keys.needsAction("MATRIX_VECTOR_PRODUCT");
     102          36 :   keys.needsAction("VSTACK"); keys.needsAction("CUSTOM"); keys.needsAction("OUTER_PRODUCT");
     103          12 : }
     104             : 
     105          10 : LocalAverage::LocalAverage(const ActionOptions&ao):
     106             :   Action(ao),
     107          10 :   ActionShortcut(ao)
     108             : {
     109          30 :   std::string sp_str, specA, specB; parse("SPECIES",sp_str); parse("SPECIESA",specA); parse("SPECIESB",specB);
     110          10 :   CoordinationNumbers::expandMatrix( false, getShortcutLabel(), sp_str, specA, specB, this );
     111          10 :   std::map<std::string,std::string> keymap; multicolvar::MultiColvarShortcuts::readShortcutKeywords( keymap, this );
     112          10 :   if( sp_str.length()>0 ) specA=specB=sp_str;
     113             :   // Calculate the coordination numbers
     114          10 :   ActionWithValue* av = plumed.getActionSet().selectWithLabel<ActionWithValue*>( getShortcutLabel() + "_mat");
     115          10 :   plumed_assert( av && av->getNumberOfComponents()>0 && (av->copyOutput(0))->getRank()==2 );
     116          10 :   std::string size; Tools::convert( (av->copyOutput(0))->getShape()[1], size );
     117          20 :   readInputLine( getShortcutLabel() + "_ones: ONES SIZE=" + size );
     118          20 :   readInputLine( getShortcutLabel() + "_coord: MATRIX_VECTOR_PRODUCT ARG=" + getShortcutLabel() + "_mat," + getShortcutLabel() + "_ones" );
     119             : 
     120          10 :   int l=-1; std::vector<ActionShortcut*> shortcuts=plumed.getActionSet().select<ActionShortcut*>();
     121          73 :   for(unsigned i=0; i<shortcuts.size(); ++i) {
     122          72 :     if( specA==shortcuts[i]->getShortcutLabel() ) {
     123          19 :       std::string sname = shortcuts[i]->getName();
     124          79 :       if( sname=="Q1" || sname=="Q3" || sname=="Q4" || sname=="Q6" ) { Tools::convert( sname.substr(1), l ); break; }
     125             :     }
     126             :   }
     127             : 
     128          10 :   if( l>0 ) {
     129           9 :     std::string vargs, svargs, sargs = "ARG=" + getShortcutLabel() + "_mat";
     130         106 :     for(int i=-l; i<=l; ++i) {
     131          97 :       std::string num = getMomentumSymbol(i);
     132         194 :       if( !plumed.getActionSet().selectWithLabel<ActionWithValue*>(specB + "_rmn-" + num) ) {
     133         194 :         readInputLine( specB + "_rmn-" + num + ": CUSTOM ARG=" + specB + "_sp.rm-" + num + "," + specB + "_denom FUNC=x/y PERIODIC=NO");
     134             :       }
     135         194 :       if( !plumed.getActionSet().selectWithLabel<ActionWithValue*>(specB + "_imn-" + num) ) {
     136         194 :         readInputLine( specB  + "_imn-" + num + ": CUSTOM ARG=" + specB + "_sp.im-" + num + "," + specB  + "_denom FUNC=x/y PERIODIC=NO");
     137             :       }
     138         115 :       if( i==-l ) { vargs = "ARG=" + specB + "_rmn-" + num + "," + specB + "_imn-" + num; svargs = "ARG=" + getShortcutLabel() + "_prod." + specB + "_rmn-" + num + "," + getShortcutLabel() + "_prod." + specB + "_imn-" + num; }
     139         264 :       else { vargs += "," +  specB + "_rmn-" + num + "," + specB + "_imn-" + num; svargs += "," + getShortcutLabel() + "_prod." + specB + "_rmn-" + num + "," + getShortcutLabel() + "_prod." + specB + "_imn-" + num; }
     140         194 :       sargs += "," + specB + "_rmn-" + num + "," + specB  + "_imn-" + num;
     141             :     }
     142          18 :     readInputLine( getShortcutLabel() + "_vstack: VSTACK " + vargs );
     143          18 :     readInputLine( getShortcutLabel() + "_prod: MATRIX_VECTOR_PRODUCT " + sargs );
     144          18 :     readInputLine( getShortcutLabel() + "_vpstack: VSTACK " + svargs );
     145          18 :     std::string twolplusone; Tools::convert( 2*(2*l+1), twolplusone ); readInputLine( getShortcutLabel() + "_lones: ONES SIZE=" + twolplusone );
     146          18 :     readInputLine( getShortcutLabel() + "_unorm: OUTER_PRODUCT ARG=" + getShortcutLabel() + "_coord," + getShortcutLabel() + "_lones" );
     147          18 :     readInputLine( getShortcutLabel() + "_av: CUSTOM ARG=" + getShortcutLabel() + "_vpstack," + getShortcutLabel() + "_vstack," + getShortcutLabel() + "_unorm FUNC=(x+y)/(1+z) PERIODIC=NO");
     148          18 :     readInputLine( getShortcutLabel() + "_av2: CUSTOM ARG=" + getShortcutLabel() + "_av FUNC=x*x PERIODIC=NO");
     149          18 :     readInputLine( getShortcutLabel() + "_2: MATRIX_VECTOR_PRODUCT ARG=" + getShortcutLabel() + "_av2," + getShortcutLabel() + "_lones");
     150          18 :     readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_2 FUNC=sqrt(x) PERIODIC=NO");
     151             :   } else {
     152           2 :     readInputLine( getShortcutLabel() + "_prod: MATRIX_VECTOR_PRODUCT ARG=" + getShortcutLabel() + "_mat," + sp_str + " " + convertInputLineToString() );
     153           2 :     readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_prod," + sp_str + "," + getShortcutLabel() + "_coord  FUNC=(x+y)/(1+z) PERIODIC=NO");
     154             :   }
     155          20 :   multicolvar::MultiColvarShortcuts::expandFunctions( getShortcutLabel(), getShortcutLabel(), "", keymap, this );
     156          10 : }
     157             : 
     158          97 : std::string LocalAverage::getMomentumSymbol( const int& m ) const {
     159          97 :   if( m<0 ) {
     160          44 :     std::string num; Tools::convert( -1*m, num );
     161          44 :     return "n" + num;
     162          53 :   } else if( m>0 ) {
     163          44 :     std::string num; Tools::convert( m, num );
     164          44 :     return "p" + num;
     165             :   }
     166           9 :   return "0";
     167             : }
     168             : 
     169             : }
     170             : }

Generated by: LCOV version 1.16