Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2014-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 "tools/SwitchingFunction.h" 24 : #include "MultiColvarFilter.h" 25 : 26 : //+PLUMEDOC MTRANSFORMS MTRANSFORM_MORE 27 : /* 28 : This action can be used to transform the colvar values calculated by a multicolvar using one minus a switching function 29 : 30 : In this action each colvar, \f$s_i\f$, calculated by \ref mcolv is transformed by a \ref switchingfunction function that 31 : is equal to one if the colvar is greater than a certain target value and which is equal to zero otherwise. 32 : It is important to understand the distinction between what is done here and what is done by \ref MFILTER_MORE. 33 : In \ref MFILTER_MORE a weight, \f$w_i\f$ for the colvar is calculated using the \ref histogrambead. If one calculates the 34 : MEAN for \ref MFILTER_MORE one is thus calculating: 35 : 36 : \f[ 37 : \mu = \frac{ \sum_i [1 - \sigma(s_i) ] s_i }{\sum_i [1 - \sigma(s_i)] } 38 : \f] 39 : 40 : where \f$\sigma\f$ is the \ref switchingfunction. In this action by contrast the colvar is being transformed by the \ref switchingfunction. 41 : If one thus calculates a MEAN for this action one computes: 42 : 43 : \f[ 44 : \mu = \frac{ \sum_{i=1}^N 1 - \sigma(s_i) }{ N } 45 : \f] 46 : 47 : In other words, you are calculating the mean for the transformed colvar. 48 : 49 : \par Examples 50 : 51 : The following input gives an example of how a MTRANSFORM_MORE action can be used to duplicate 52 : functionality that is elsewhere in PLUMED. 53 : 54 : \plumedfile 55 : DISTANCES ... 56 : GROUPA=1-10 GROUPB=11-20 57 : LABEL=d1 58 : ... DISTANCES 59 : MTRANSFORM_MORE DATA=d1 SWITCH={GAUSSIAN D_0=1.5 R_0=0.00001} 60 : \endplumedfile 61 : 62 : In this case you can achieve the same result by using: 63 : 64 : \plumedfile 65 : DISTANCES ... 66 : GROUPA=1-10 GROUPB=11-20 67 : MORE_THAN={GAUSSIAN D_0=1.5 R_0=0.00001} 68 : ... DISTANCES 69 : \endplumedfile 70 : (see \ref DISTANCES) 71 : 72 : The advantage of MTRANSFORM_MORE comes, however, if you want to use transformed colvars as input 73 : for \ref MULTICOLVARDENS 74 : 75 : */ 76 : //+ENDPLUMEDOC 77 : 78 : //+PLUMEDOC MFILTERS MFILTER_MORE 79 : /* 80 : This action can be used to filter the distribution of colvar values in a multicolvar so that one can compute the mean and so on for only those multicolvars more than a tolerance. 81 : 82 : This action can be used to create a dynamic group of atom based on the value of a multicolvar. 83 : In this action a multicolvar is within the dynamic group if its value is greater than a target. 84 : In actuality a weight, \f$w_i\f$ is ascribed to each colvar, \f$s_i\f$ calculated by a multicolvar 85 : and this weight measures the degree to which a colvar is a member of the group. This weight is 86 : calculated using a \ref switchingfunction , \f$\sigma\f$ so it is given by: 87 : 88 : \f[ 89 : w_i = 1 - \sigma(s_i) 90 : \f] 91 : 92 : If one calculates a function of the set of multicolvars 93 : these weights are included in the calculation. As such if one calculates the MEAN, \f$\mu\f$ of a filtered 94 : multicolvar what is computed is the following: 95 : 96 : \f[ 97 : \mu = \frac{ \sum_i w_i s_i }{ \sum_i w_i} 98 : \f] 99 : 100 : One is thus calculating the mean for those colvars that are greater than the target. 101 : 102 : \par Examples 103 : 104 : The example shown below calculates the mean for those distances that greater than 1.5 nm in length 105 : 106 : \plumedfile 107 : DISTANCES GROUPA=1 GROUPB=2-50 MEAN LABEL=d1 108 : MFILTER_MORE DATA=d1 SWITCH={GAUSSIAN D_0=1.5 R_0=0.00001} MEAN LABEL=d4 109 : \endplumedfile 110 : 111 : More complicated things can be done by using the label of a filter as input to a new multicolvar as shown 112 : in the example below. Here the coordination numbers of all atoms are computed. The atoms with a coordination 113 : number greater than 2 are then identified using the filter. This reduced list of atoms is then used as input 114 : to a second coordination number calculation. This second coordination number thus measures the number of 115 : two-coordinated atoms that each of the two-coordinated atoms is bound to. 116 : 117 : \plumedfile 118 : c1: COORDINATIONNUMBER SPECIES=1-150 SWITCH={EXP D_0=4.0 R_0=0.5 D_MAX=6.0} 119 : cf: MFILTER_MORE DATA=c1 SWITCH={RATIONAL D_0=2.0 R_0=0.1} LOWMEM 120 : c2: COORDINATIONNUMBER SPECIES=cf SWITCH={EXP D_0=4.0 R_0=0.5 D_MAX=6.0} MORE_THAN={RATIONAL D_0=2.0 R_0=0.1} 121 : \endplumedfile 122 : 123 : */ 124 : //+ENDPLUMEDOC 125 : 126 : namespace PLMD { 127 : namespace multicolvar { 128 : 129 : class FilterMore : public MultiColvarFilter { 130 : private: 131 : SwitchingFunction sf; 132 : public: 133 : static void registerKeywords( Keywords& keys ); 134 : explicit FilterMore(const ActionOptions& ao); 135 : double applyFilter( const double& val, double& df ) const override; 136 : }; 137 : 138 13797 : PLUMED_REGISTER_ACTION(FilterMore,"MFILTER_MORE") 139 13787 : PLUMED_REGISTER_ACTION(FilterMore,"MTRANSFORM_MORE") 140 : 141 15 : void FilterMore::registerKeywords( Keywords& keys ) { 142 15 : MultiColvarFilter::registerKeywords( keys ); 143 30 : keys.add("compulsory","NN","6","The n parameter of the switching function "); 144 30 : keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); 145 30 : keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); 146 30 : keys.add("compulsory","R_0","The r_0 parameter of the switching function"); 147 30 : keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous switching function defined above. " 148 : "The following provides information on the \\ref switchingfunction that are available. " 149 : "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); 150 15 : } 151 : 152 7 : FilterMore::FilterMore(const ActionOptions& ao): 153 : Action(ao), 154 7 : MultiColvarFilter(ao) { 155 : // Read in the switching function 156 : std::string sw, errors; 157 14 : parse("SWITCH",sw); 158 7 : if(sw.length()>0) { 159 7 : sf.set(sw,errors); 160 7 : if( errors.length()!=0 ) { 161 0 : error("problem reading SWITCH keyword : " + errors ); 162 : } 163 : } else { 164 0 : double r_0=-1.0, d_0; 165 : int nn, mm; 166 0 : parse("NN",nn); 167 0 : parse("MM",mm); 168 0 : parse("R_0",r_0); 169 0 : parse("D_0",d_0); 170 0 : if( r_0<0.0 ) { 171 0 : error("you must set a value for R_0"); 172 : } 173 0 : sf.set(nn,mm,r_0,d_0); 174 : } 175 7 : log.printf(" filtering colvar values and focussing only on those more than %s\n",( sf.description() ).c_str() ); 176 : 177 7 : checkRead(); 178 7 : } 179 : 180 16806 : double FilterMore::applyFilter( const double& val, double& df ) const { 181 16806 : double f = 1.0 - sf.calculate( val, df ); 182 16806 : df*=-val; 183 16806 : return f; 184 : } 185 : 186 : } 187 : }