LCOV - code coverage report
Current view: top level - gridtools - MultiColvarDensity.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 44 52 84.6 %
Date: 2024-10-18 14:00:25 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-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/ActionRegister.h"
      23             : #include "core/ActionShortcut.h"
      24             : 
      25             : namespace PLMD {
      26             : namespace gridtools {
      27             : 
      28             : //+PLUMEDOC GRIDCALC MULTICOLVARDENS
      29             : /*
      30             : Evaluate the average value of a multicolvar on a grid.
      31             : 
      32             : This keyword allows one to construct a phase field representation for a symmetry function from
      33             : an atomistic description.  If each atom has an associated order parameter, \f$\phi_i\f$ then a
      34             : smooth phase field function \f$\phi(r)\f$ can be computed using:
      35             : 
      36             : \f[
      37             : \phi(\mathbf{r}) = \frac{\sum_i K(\mathbf{r}-\mathbf{r}_i) \phi_i }{ \sum_i K(\mathbf{r} - \mathbf{r}_i )}
      38             : \f]
      39             : 
      40             : where \f$\mathbf{r}_i\f$ is the position of atom \f$i\f$, the sums run over all the atoms input
      41             : and \f$K(\mathbf{r} - \mathbf{r}_i)\f$ is one of the \ref kernelfunctions implemented in plumed.
      42             : This action calculates the above function on a grid, which can then be used in the input to further
      43             : actions.
      44             : 
      45             : \par Examples
      46             : 
      47             : The following example shows perhaps the simplest way in which this action can be used.  The following
      48             : input computes the density of atoms at each point on the grid and outputs this quantity to a file.  In
      49             : other words this input instructs plumed to calculate \f$\rho(\mathbf{r}) = \sum_i K(\mathbf{r} - \mathbf{r}_i )\f$
      50             : 
      51             : \plumedfile
      52             : dens: DENSITY SPECIES=1-100
      53             : grid: MULTICOLVARDENS DATA=dens ORIGIN=1 DIR=xyz NBINS=100,100,100 BANDWIDTH=0.05,0.05,0.05 STRIDE=1
      54             : DUMPGRID GRID=grid STRIDE=500 FILE=density
      55             : \endplumedfile
      56             : 
      57             : In the above example density is added to the grid on every step.  The PRINT_GRID instruction thus tells PLUMED to
      58             : output the average density at each point on the grid every 500 steps of simulation.  Notice that the that grid output
      59             : on step 1000 is an average over all 1000 frames of the trajectory.  If you would like to analyze these two blocks
      60             : of data separately you must use the CLEAR flag.
      61             : 
      62             : This second example computes an order parameter (in this case \ref FCCUBIC) and constructs a phase field model
      63             : for this order parameter using the equation above.
      64             : 
      65             : \plumedfile
      66             : fcc: FCCUBIC SPECIES=1-5184 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} ALPHA=27
      67             : dens: MULTICOLVARDENS DATA=fcc ORIGIN=1 DIR=xyz NBINS=14,14,28 BANDWIDTH=1.0,1.0,1.0 STRIDE=1 CLEAR=1
      68             : DUMPCUBE GRID=dens STRIDE=1 FILE=dens.cube
      69             : \endplumedfile
      70             : 
      71             : In this example the phase field model is computed and output to a file on every step of the simulation.  Furthermore,
      72             : because the CLEAR=1 keyword is set on the MULTICOLVARDENS line each Gaussian cube file output is a phase field
      73             : model for a particular trajectory frame. The average value accumulated thus far is cleared at the start of every single
      74             : timestep and there is no averaging over trajectory frames in this case.
      75             : 
      76             : */
      77             : //+ENDPLUMEDOC
      78             : 
      79             : class MultiColvarDensity : public ActionShortcut {
      80             : public:
      81             :   explicit MultiColvarDensity(const ActionOptions&);
      82             :   static void registerKeywords( Keywords& keys );
      83             : };
      84             : 
      85             : PLUMED_REGISTER_ACTION(MultiColvarDensity,"MULTICOLVARDENS")
      86             : 
      87          10 : void MultiColvarDensity::registerKeywords( Keywords& keys ) {
      88          10 :   ActionShortcut::registerKeywords( keys );
      89          20 :   keys.add("compulsory","STRIDE","1","the frequency with which to accumulate the densities");
      90          20 :   keys.add("compulsory","CLEAR","0","the frequency with which to clear the density");
      91          20 :   keys.add("compulsory","ORIGIN","we will use the position of this atom as the origin");
      92          20 :   keys.add("compulsory","DIR","the direction in which to calculate the density profile");
      93          20 :   keys.add("optional","BANDWIDTH","the bandwidths for kernel density esimtation");
      94          20 :   keys.add("compulsory","KERNEL","GAUSSIAN","the kernel function you are using.  More details on  the kernels available "
      95             :            "in plumed plumed can be found in \\ref kernelfunctions.");
      96          20 :   keys.add("optional","NBINS","the number of bins to use in each direction (alternative to GRID_NBIN)");
      97          20 :   keys.add("optional","DATA","the multicolvar which you would like to calculate the density profile for");
      98          20 :   keys.add("optional","ATOMS","if you are calculating a atomic density you use this keyword to specify the atoms that are involved");
      99          20 :   keys.addFlag("UNORMALIZED",false,"do not divide by the density");
     100          20 :   keys.add("optional","NORMALIZATION","set true/false to determine how to the data is normalised");
     101          10 :   keys.setValueDescription("the average value of the order parameters at each point on the grid");
     102          30 :   keys.needsAction("DISTANCES"); keys.needsAction("KDE"); keys.needsAction("ACCUMULATE");
     103          30 :   keys.needsAction("CUSTOM"); keys.needsAction("ONES"); keys.needsAction("CUSTOM");
     104          10 : }
     105             : 
     106           8 : MultiColvarDensity::MultiColvarDensity(const ActionOptions&ao):
     107             :   Action(ao),
     108           8 :   ActionShortcut(ao)
     109             : {
     110             :   // Read in the position of the origin
     111          16 :   std::string origin_str; parse("ORIGIN",origin_str);
     112             :   // Read in the quantity we are calculating the density for
     113          24 :   std::string atoms_str, data_str; parse("ATOMS",atoms_str); parse("DATA",data_str);
     114           8 :   if( atoms_str.length()==0 && data_str.length()==0 ) error("quantity to calculate the density for was not specified used DATA/ATOMS");
     115             :   // Get the information on the direction for the density
     116          24 :   std::string dir, direction_string; parse("DIR",dir); std::string nbins=""; parse("NBINS",nbins); if(nbins.length()>0) nbins=" GRID_BIN=" + nbins;
     117          16 :   if( dir=="x" ) direction_string = "ARG=" + getShortcutLabel() + "_dist.x " + nbins;
     118           0 :   else if( dir=="y" ) direction_string = "ARG=" + getShortcutLabel() + "_dist.y " + nbins;
     119           0 :   else if( dir=="z" ) direction_string = "ARG=" + getShortcutLabel() + "_dist.z " + nbins;
     120           0 :   else if( dir=="xy" ) direction_string = "ARG=" + getShortcutLabel() + "_dist.x," + getShortcutLabel() + "_dist.y " + nbins;
     121           0 :   else if( dir=="xz" ) direction_string = "ARG=" + getShortcutLabel() + "_dist.x," + getShortcutLabel() + "_dist.z " + nbins;
     122           0 :   else if( dir=="yz" ) direction_string = "ARG=" + getShortcutLabel() + "_dist.y," + getShortcutLabel() + "_dist.z " + nbins;
     123           0 :   else if( dir=="xyz" ) direction_string = "ARG=" + getShortcutLabel() + "_dist.x," + getShortcutLabel() + "_dist.y," + getShortcutLabel() + "_dist.z " + nbins;
     124           0 :   else error( dir + " is invalid dir specification use x/y/z/xy/xz/yz/xyz");
     125             : 
     126             :   // Parse the keymap for this averaging stuff
     127          24 :   std::string stride, clear; parse("STRIDE",stride); parse("CLEAR",clear); bool unorm; parseFlag("UNORMALIZED",unorm);
     128          14 :   if( !unorm ) { std::string normstr; parse("NORMALIZATION",normstr); if( normstr=="false" ) unorm=true; }
     129             :   // Create distance action
     130          16 :   bool hasheights; std::string dist_words = getShortcutLabel() + "_dist: DISTANCES COMPONENTS ORIGIN=" + origin_str;
     131          11 :   if( atoms_str.length()>0 ) { hasheights=false; dist_words += " ATOMS=" + atoms_str; }
     132          10 :   else { hasheights=true; dist_words += " ATOMS=" + data_str; }
     133             :   // plumed_massert( keys.count("ORIGIN"), "you must specify the position of the origin" );
     134           8 :   readInputLine( dist_words );
     135             : 
     136           8 :   std::string inputLine = convertInputLineToString();
     137             :   // Make the kde object for the numerator if needed
     138           8 :   if( hasheights ) {
     139          10 :     readInputLine( getShortcutLabel() + "_inumer: KDE VOLUMES=" + data_str + " " + direction_string + " " + inputLine );
     140           7 :     if( unorm ) { readInputLine( getShortcutLabel() + ": ACCUMULATE ARG=" + getShortcutLabel() + "_inumer STRIDE=" + stride + " CLEAR=" + clear ); return; }
     141           6 :     else readInputLine( getShortcutLabel() + "_numer: ACCUMULATE ARG=" + getShortcutLabel() + "_inumer STRIDE=" + stride + " CLEAR=" + clear );
     142             :   }
     143             :   // Make the kde object
     144          12 :   readInputLine( getShortcutLabel() + "_kde: KDE " + inputLine  + " " + direction_string );
     145             :   // Make the division object if it is required
     146           6 :   if( hasheights && !unorm ) {
     147           6 :     readInputLine( getShortcutLabel() + "_denom: ACCUMULATE ARG=" + getShortcutLabel() + "_kde STRIDE=" + stride + " CLEAR=" + clear );
     148           6 :     readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_numer," + getShortcutLabel() + "_denom FUNC=x/y PERIODIC=NO");
     149           3 :   } else if( !hasheights ) {
     150           3 :     readInputLine( getShortcutLabel() + "_weight: ONES SIZE=1" );
     151           6 :     readInputLine( getShortcutLabel() + "_numer: ACCUMULATE ARG=" + getShortcutLabel() + "_kde STRIDE=" + stride + " CLEAR=" + clear );
     152           6 :     readInputLine( getShortcutLabel() + "_denom: ACCUMULATE ARG=" + getShortcutLabel() + "_weight STRIDE=" + stride + " CLEAR=" + clear );
     153           6 :     readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_numer," + getShortcutLabel() + "_denom FUNC=x/y PERIODIC=NO");
     154             :   }
     155           0 : }
     156             : 
     157             : }
     158             : }

Generated by: LCOV version 1.16