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 "Function.h" 23 : #include "ActionRegister.h" 24 : #include "tools/PDB.h" 25 : #include "reference/MetricRegister.h" 26 : #include "reference/ArgumentOnlyDistance.h" 27 : #include "core/Atoms.h" 28 : #include "core/PlumedMain.h" 29 : 30 : namespace PLMD { 31 : namespace function { 32 : 33 : //+PLUMEDOC DCOLVAR TARGET 34 : /* 35 : This function measures the Pythagorean distance from a particular structure measured in the space defined by some set of collective variables. 36 : 37 : This collective variable can be used to calculate something akin to: 38 : 39 : \f[ 40 : d(X,X') = \vert X - X' \vert 41 : \f] 42 : 43 : where \f$ X \f$ is the instantaneous values for a set of collective variables for the system and 44 : \f$ X' \f$ is the values that these self-same set of collective variables take in some reference structure provided as input. 45 : If we call our set of collective variables \f$\{s_i\}\f$ then this CV computes: 46 : 47 : \f[ 48 : d = \sqrt{ \sum_{i=1}^N (s_i - s_i^{(ref)})^2 } 49 : \f] 50 : 51 : where \f$s_i^{(ref)}\f$ are the values of the CVs in the reference structure and \f$N\f$ is the number of input CVs. 52 : 53 : We can also calculate normalized euclidean differences using this action and the METRIC=NORM-EUCLIDEAN flag. In other words, 54 : we can compute: 55 : 56 : \f[ 57 : d = \sqrt{ \sum_{i=1}^N \sigma_i (s_i - s_i^{(ref)})^2 } 58 : \f] 59 : 60 : where \f$\sigma_i\f$ is a vector of weights. Lastly, by using the METRIC=MAHALONOBIS we can compute Mahalonobis distances using: 61 : 62 : \f[ 63 : d = \left( \mathbf{s} - \mathbf{s}^{(ref)} \right)^T \mathbf{\Sigma} \left( \mathbf{s} - \mathbf{s}^{(ref)} \right) 64 : \f] 65 : 66 : where \f$\mathbf{s}\f$ is a column vector containing the values of all the CVs and \f$\mathbf{s}^{(ref)}\f$ is a column vector 67 : containing the values of the CVs in the reference configuration. \f$\mathbf{\Sigma}\f$ is then an \f$N \times N\f$ matrix that is 68 : specified in the input. 69 : 70 : \par Examples 71 : 72 : The following input calculates the distance between a reference configuration and the instantaneous position of the system in the trajectory. 73 : The position of the reference configuration is specified by providing the values of the distance between atoms 1 and 2 and atoms 3 and 4. 74 : 75 : \plumedfile 76 : d1: DISTANCE ATOMS=1,2 77 : d2: DISTANCE ATOMS=3,4 78 : t1: TARGET REFERENCE=reference.pdb TYPE=EUCLIDEAN 79 : PRINT ARG=t1 FILE=colvar 80 : \endplumedfile 81 : 82 : The contents of the file containing the reference structure (reference.pdb) is shown below. As you can see you must provide information on the 83 : labels of the CVs that are being used to define the position of the reference configuration in this file together with the values that these 84 : quantities take in the reference configuration. 85 : 86 : \auxfile{reference.pdb} 87 : DESCRIPTION: a reference point. 88 : REMARK WEIGHT=1.0 89 : REMARK ARG=d1,d2 90 : REMARK d1=1.0 d2=1.0 91 : END 92 : \endauxfile 93 : 94 : */ 95 : //+ENDPLUMEDOC 96 : 97 : class Target : public Function { 98 : private: 99 : MultiValue myvals; 100 : ReferenceValuePack mypack; 101 : std::unique_ptr<PLMD::ArgumentOnlyDistance> target; 102 : public: 103 : explicit Target(const ActionOptions&); 104 : void calculate() override; 105 : static void registerKeywords(Keywords& keys ); 106 : }; 107 : 108 10419 : PLUMED_REGISTER_ACTION(Target,"TARGET") 109 : 110 1 : void Target::registerKeywords(Keywords& keys) { 111 1 : Function::registerKeywords(keys); 112 2 : keys.add("compulsory","TYPE","EUCLIDEAN","the manner in which the distance should be calculated"); 113 2 : keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure. In the PDB file the atomic " 114 : "coordinates and box lengths should be in Angstroms unless you are working with natural units. " 115 : "If you are working with natural units then the coordinates should be in your natural length unit. " 116 : "The charges and masses of the atoms (if required) should be inserted in the beta and occupancy " 117 : "columns respectively. For more details on the PDB file format visit http://www.wwpdb.org/docs.html"); 118 1 : } 119 : 120 0 : Target::Target(const ActionOptions&ao): 121 : Action(ao), 122 : Function(ao), 123 0 : myvals(1,0), 124 0 : mypack(0,0,myvals) 125 : { 126 0 : std::string type; parse("TYPE",type); 127 0 : std::string reference; parse("REFERENCE",reference); 128 0 : checkRead(); PDB pdb; 129 0 : if( !pdb.read(reference,plumed.getAtoms().usingNaturalUnits(),0.1/plumed.getAtoms().getUnits().getLength()) ) 130 0 : error("missing input file " + reference); 131 : 132 : // Use the base ActionWithArguments to expand things like a1.* 133 0 : expandArgKeywordInPDB( pdb ); 134 : 135 : // Generate the reference structure 136 0 : target=metricRegister().create<ArgumentOnlyDistance>( type, pdb ); 137 : 138 : // Get the argument names 139 : std::vector<std::string> args_to_retrieve; 140 0 : target->getArgumentRequests( args_to_retrieve, false ); 141 : 142 : // Get the arguments 143 : std::vector<Value*> myargs; 144 0 : interpretArgumentList( args_to_retrieve, myargs ); 145 0 : requestArguments( myargs ); 146 : 147 : // Now create packs 148 0 : myvals.resize( 1, myargs.size() ); 149 0 : mypack.resize( myargs.size(), 0 ); 150 : 151 : // Create the value 152 0 : addValueWithDerivatives(); setNotPeriodic(); 153 0 : } 154 : 155 0 : void Target::calculate() { 156 0 : mypack.clear(); double r=target->calculate( getArguments(), mypack, false ); setValue(r); 157 0 : for(unsigned i=0; i<getNumberOfArguments(); i++) setDerivative( i, mypack.getArgumentDerivative(i) ); 158 0 : } 159 : 160 : } 161 : }