LCOV - code coverage report
Current view: top level - symfunc - LocalAverage.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 66 66 100.0 %
Date: 2025-04-08 21:11:17 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 PLUMED actions
      40             : calculate one scalar quantity or one vector for each of the atoms in the system.  For example
      41             : [COORDINATIONNUMBER](COORDINATIONNUMBER.md) measures the coordination number of each of the atoms in the system and [Q4](Q4.md) 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.  In the paper in the bibliography Lechner and Dellago
      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             : $$
      52             : s_i = \frac{ c_i + \sum_j \sigma(r_{ij})c_j }{ 1 + \sum_j \sigma(r_{ij}) }
      53             : $$
      54             : 
      55             : where the $c_i$ and $c_j$ values can be any vector of [symmetry functions](https://www.plumed-tutorials.org/lessons/23/001/data/SymmetryFunction.html)
      56             :  that can be calculated using plumed multicolvars.  The function $\sigma( r_{ij} )$ is a switching function that acts on the distance between
      57             : atoms $i$ and $j$.  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 $j$ is in the first coordination sphere of atom $i$ and is zero otherwise.
      59             : 
      60             : To see how this works in practice consider the following example input.
      61             : 
      62             : ```plumed
      63             : d1: COORDINATIONNUMBER SPECIES=1-64 D_0=1.3 R_0=0.2
      64             : la: LOCAL_AVERAGE SPECIES=d1 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MORE_THAN={RATIONAL R_0=4}
      65             : PRINT ARG=la.* FILE=colvar
      66             : ```
      67             : 
      68             : This input calculates the coordination numbers for all the atoms in the system.  These coordination numbers are then averaged over
      69             : spherical regions.  The number of averaged coordination numbers that are greater than 4 is then output to a file.  Furthermore, if you
      70             : expand the input above you can see how the LOCAL_AVERAGE command is a shortcut action that expands to a longer input that you should be able to
      71             : interpret.
      72             : 
      73             : What Lechner and Dellago did in their paper was a little more complicated than this first example. To reproduce what they did you would use
      74             : an input something like this:
      75             : 
      76             : ```plumed
      77             : Q4 SPECIES=1-64 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=q4
      78             : LOCAL_AVERAGE SPECIES=q4 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MEAN LABEL=la
      79             : PRINT ARG=la.* FILE=colvar
      80             : ```
      81             : 
      82             : This example input calculates the [Q4](Q4.md) vectors for each of the atoms in the system.  These vectors are then averaged
      83             : component by component over a spherical region.  The average value for this quantity is then outputeed to a file.  If you want
      84             : to understand more about the shortcut that is used here you can read [this page](https://www.plumed-tutorials.org/lessons/23/001/data/Steinhardt.html).
      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          12 :   keys.needsAction("ONES");
     102          12 :   keys.needsAction("MATRIX_VECTOR_PRODUCT");
     103          12 :   keys.needsAction("VSTACK");
     104          12 :   keys.needsAction("CUSTOM");
     105          12 :   keys.needsAction("OUTER_PRODUCT");
     106          24 :   keys.setValueDescription("vector","the values of the local averages");
     107          12 :   keys.addDOI("10.1063/1.2977970");
     108          12 : }
     109             : 
     110          10 : LocalAverage::LocalAverage(const ActionOptions&ao):
     111             :   Action(ao),
     112          10 :   ActionShortcut(ao) {
     113             :   std::string sp_str, specA, specB;
     114          10 :   parse("SPECIES",sp_str);
     115          10 :   parse("SPECIESA",specA);
     116          10 :   parse("SPECIESB",specB);
     117          10 :   CoordinationNumbers::expandMatrix( false, getShortcutLabel(), sp_str, specA, specB, this );
     118             :   std::map<std::string,std::string> keymap;
     119          10 :   multicolvar::MultiColvarShortcuts::readShortcutKeywords( keymap, this );
     120          10 :   if( sp_str.length()>0 ) {
     121             :     specA=specB=sp_str;
     122             :   }
     123             :   // Calculate the coordination numbers
     124          10 :   ActionWithValue* av = plumed.getActionSet().selectWithLabel<ActionWithValue*>( getShortcutLabel() + "_mat");
     125          10 :   plumed_assert( av && av->getNumberOfComponents()>0 && (av->copyOutput(0))->getRank()==2 );
     126             :   std::string size;
     127          10 :   Tools::convert( (av->copyOutput(0))->getShape()[1], size );
     128          20 :   readInputLine( getShortcutLabel() + "_ones: ONES SIZE=" + size );
     129          20 :   readInputLine( getShortcutLabel() + "_coord: MATRIX_VECTOR_PRODUCT ARG=" + getShortcutLabel() + "_mat," + getShortcutLabel() + "_ones" );
     130             : 
     131          10 :   int l=-1;
     132          10 :   std::vector<ActionShortcut*> shortcuts=plumed.getActionSet().select<ActionShortcut*>();
     133          73 :   for(unsigned i=0; i<shortcuts.size(); ++i) {
     134          72 :     if( specA==shortcuts[i]->getShortcutLabel() ) {
     135          19 :       std::string sname = shortcuts[i]->getName();
     136          70 :       if( sname=="Q1" || sname=="Q3" || sname=="Q4" || sname=="Q6" ) {
     137          18 :         Tools::convert( sname.substr(1), l );
     138             :         break;
     139             :       }
     140             :     }
     141             :   }
     142             : 
     143          10 :   if( l>0 ) {
     144           9 :     std::string vargs, svargs, sargs = "ARG=" + getShortcutLabel() + "_mat";
     145         106 :     for(int i=-l; i<=l; ++i) {
     146          97 :       std::string num = getMomentumSymbol(i);
     147         194 :       if( !plumed.getActionSet().selectWithLabel<ActionWithValue*>(specB + "_rmn-" + num) ) {
     148         194 :         readInputLine( specB + "_rmn-" + num + ": CUSTOM ARG=" + specB + "_sp.rm-" + num + "," + specB + "_denom FUNC=x/y PERIODIC=NO");
     149             :       }
     150         194 :       if( !plumed.getActionSet().selectWithLabel<ActionWithValue*>(specB + "_imn-" + num) ) {
     151         194 :         readInputLine( specB  + "_imn-" + num + ": CUSTOM ARG=" + specB + "_sp.im-" + num + "," + specB  + "_denom FUNC=x/y PERIODIC=NO");
     152             :       }
     153          97 :       if( i==-l ) {
     154          18 :         vargs = "ARG=" + specB + "_rmn-" + num + "," + specB + "_imn-" + num;
     155          18 :         svargs = "ARG=" + getShortcutLabel() + "_prod." + specB + "_rmn-" + num + "," + getShortcutLabel() + "_prod." + specB + "_imn-" + num;
     156             :       } else {
     157         176 :         vargs += "," +  specB + "_rmn-" + num + "," + specB + "_imn-" + num;
     158         176 :         svargs += "," + getShortcutLabel() + "_prod." + specB + "_rmn-" + num + "," + getShortcutLabel() + "_prod." + specB + "_imn-" + num;
     159             :       }
     160         194 :       sargs += "," + specB + "_rmn-" + num + "," + specB  + "_imn-" + num;
     161             :     }
     162          18 :     readInputLine( getShortcutLabel() + "_vstack: VSTACK " + vargs );
     163          18 :     readInputLine( getShortcutLabel() + "_prod: MATRIX_VECTOR_PRODUCT " + sargs );
     164          18 :     readInputLine( getShortcutLabel() + "_vpstack: VSTACK " + svargs );
     165             :     std::string twolplusone;
     166           9 :     Tools::convert( 2*(2*l+1), twolplusone );
     167          18 :     readInputLine( getShortcutLabel() + "_lones: ONES SIZE=" + twolplusone );
     168          18 :     readInputLine( getShortcutLabel() + "_unorm: OUTER_PRODUCT ARG=" + getShortcutLabel() + "_coord," + getShortcutLabel() + "_lones" );
     169          18 :     readInputLine( getShortcutLabel() + "_av: CUSTOM ARG=" + getShortcutLabel() + "_vpstack," + getShortcutLabel() + "_vstack," + getShortcutLabel() + "_unorm FUNC=(x+y)/(1+z) PERIODIC=NO");
     170          18 :     readInputLine( getShortcutLabel() + "_av2: CUSTOM ARG=" + getShortcutLabel() + "_av FUNC=x*x PERIODIC=NO");
     171          18 :     readInputLine( getShortcutLabel() + "_2: MATRIX_VECTOR_PRODUCT ARG=" + getShortcutLabel() + "_av2," + getShortcutLabel() + "_lones");
     172          18 :     readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_2 FUNC=sqrt(x) PERIODIC=NO");
     173             :   } else {
     174           2 :     readInputLine( getShortcutLabel() + "_prod: MATRIX_VECTOR_PRODUCT ARG=" + getShortcutLabel() + "_mat," + sp_str + " " + convertInputLineToString() );
     175           2 :     readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_prod," + sp_str + "," + getShortcutLabel() + "_coord  FUNC=(x+y)/(1+z) PERIODIC=NO");
     176             :   }
     177          20 :   multicolvar::MultiColvarShortcuts::expandFunctions( getShortcutLabel(), getShortcutLabel(), "", keymap, this );
     178          10 : }
     179             : 
     180          97 : std::string LocalAverage::getMomentumSymbol( const int& m ) const {
     181          97 :   if( m<0 ) {
     182             :     std::string num;
     183          44 :     Tools::convert( -1*m, num );
     184          44 :     return "n" + num;
     185          53 :   } else if( m>0 ) {
     186             :     std::string num;
     187          44 :     Tools::convert( m, num );
     188          44 :     return "p" + num;
     189             :   }
     190           9 :   return "0";
     191             : }
     192             : 
     193             : }
     194             : }

Generated by: LCOV version 1.16