Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2013-2020 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 "core/PlumedMain.h" 26 : #include "core/ActionSet.h" 27 : 28 : //+PLUMEDOC MATRIXF SPRINT 29 : /* 30 : Calculate SPRINT topological variables from an adjacency matrix. 31 : 32 : The SPRINT topological variables are calculated from the largest eigenvalue, \f$\lambda\f$ of 33 : an \f$n\times n\f$ adjacency matrix and its corresponding eigenvector, \f$\mathbf{V}\f$, using: 34 : 35 : \f[ 36 : s_i = \sqrt{n} \lambda v_i 37 : \f] 38 : 39 : You can use different quantities to measure whether or not two given atoms/molecules are 40 : adjacent or not in the adjacency matrix. The simplest measure of adjacency is is whether 41 : two atoms/molecules are within some cutoff of each other. Further complexity can be added by 42 : insisting that two molecules are adjacent if they are within a certain distance of each 43 : other and if they have similar orientations. 44 : 45 : \par Examples 46 : 47 : This example input calculates the 7 SPRINT coordinates for a 7 atom cluster of Lennard-Jones 48 : atoms and prints their values to a file. In this input the SPRINT coordinates are calculated 49 : in the manner described in ?? so two atoms are adjacent if they are within a cutoff: 50 : 51 : \plumedfile 52 : DENSITY SPECIES=1-7 LABEL=d1 53 : CONTACT_MATRIX ATOMS=d1 SWITCH={RATIONAL R_0=0.1} LABEL=mat 54 : SPRINT MATRIX=mat LABEL=ss 55 : PRINT ARG=ss.* FILE=colvar 56 : \endplumedfile 57 : 58 : This example input calculates the 14 SPRINT coordinates for a molecule composed of 7 hydrogen and 59 : 7 carbon atoms. Once again two atoms are adjacent if they are within a cutoff: 60 : 61 : \plumedfile 62 : DENSITY SPECIES=1-7 LABEL=c 63 : DENSITY SPECIES=8-14 LABEL=h 64 : 65 : CONTACT_MATRIX ... 66 : ATOMS=c,h 67 : SWITCH11={RATIONAL R_0=2.6 NN=6 MM=12} 68 : SWITCH12={RATIONAL R_0=2.2 NN=6 MM=12} 69 : SWITCH22={RATIONAL R_0=2.2 NN=6 MM=12} 70 : LABEL=mat 71 : ... CONTACT_MATRIX 72 : 73 : SPRINT MATRIX=mat LABEL=ss 74 : 75 : PRINT ARG=ss.* FILE=colvar 76 : \endplumedfile 77 : 78 : */ 79 : //+ENDPLUMEDOC 80 : 81 : namespace PLMD { 82 : namespace sprint { 83 : 84 : class Sprint : public ActionShortcut { 85 : public: 86 : static void registerKeywords(Keywords& keys); 87 : explicit Sprint(const ActionOptions&); 88 : }; 89 : 90 : PLUMED_REGISTER_ACTION(Sprint,"SPRINT") 91 : 92 3 : void Sprint::registerKeywords(Keywords& keys) { 93 3 : ActionShortcut::registerKeywords( keys ); 94 6 : keys.add("optional","MATRIX","the matrix that you would like to perform SPRINT on"); 95 6 : keys.add("numbered","GROUP","specifies the list of atoms that should be assumed indistinguishable"); 96 6 : keys.add("numbered","SWITCH","specify the switching function to use between two sets of indistinguishable atoms"); 97 3 : keys.needsAction("CONTACT_MATRIX"); 98 3 : keys.needsAction("DIAGONALIZE"); 99 3 : keys.needsAction("CUSTOM"); 100 3 : keys.needsAction("SELECT_COMPONENTS"); 101 3 : keys.needsAction("SORT"); 102 3 : keys.needsAction("COMBINE"); 103 6 : keys.addOutputComponent("coord","default","the sprint coordinates"); 104 3 : } 105 : 106 1 : Sprint::Sprint(const ActionOptions& ao): 107 : Action(ao), 108 1 : ActionShortcut(ao) { 109 : std::string matinp; 110 2 : parse("MATRIX",matinp); 111 1 : if( matinp.length()==0 ) { 112 2 : readInputLine( getShortcutLabel() + "_jmat: CONTACT_MATRIX " + convertInputLineToString() ); 113 2 : matinp = getShortcutLabel() + "_jmat"; 114 : } 115 : std::vector<unsigned> nin_group; 116 1 : unsigned ntot_atoms=0; 117 1 : for(unsigned i=1;; ++i) { 118 : std::string inum; 119 3 : Tools::convert( i, inum ); 120 6 : ActionWithValue* av = plumed.getActionSet().selectWithLabel<ActionWithValue*>( matinp + inum + inum ); 121 3 : if( !av ) { 122 : break ; 123 : } 124 2 : unsigned natoms = (av->copyOutput(0))->getShape()[0]; 125 2 : nin_group.push_back( natoms ); 126 2 : ntot_atoms += natoms; 127 2 : } 128 : 129 : // Diagonalization 130 2 : readInputLine( getShortcutLabel() + "_diag: DIAGONALIZE ARG=" + matinp + " VECTORS=1"); 131 : // Compute sprint coordinates as product of eigenvalue and eigenvector times square root of number of atoms in all groups 132 : std::string str_natoms; 133 1 : Tools::convert( ntot_atoms, str_natoms ); 134 3 : readInputLine( getShortcutLabel() + "_sp: CUSTOM ARG=" + getShortcutLabel() + "_diag.vals-1," + getShortcutLabel() + 135 2 : "_diag.vecs-1 FUNC=sqrt(" + str_natoms + ")*x*y PERIODIC=NO"); 136 : // Sort sprint coordinates for each group of atoms 137 1 : unsigned k=0, kk=0; 138 3 : for(unsigned j=0; j<nin_group.size(); ++j) { 139 : std::string jnum, knum; 140 2 : Tools::convert( j+1, jnum ); 141 2 : Tools::convert(k+1, knum); 142 : k++; 143 4 : std::string sort_act = getShortcutLabel() + "_selection" + jnum + ": SELECT_COMPONENTS ARG=" + getShortcutLabel() + "_sp COMPONENTS=" + knum; 144 14 : for(unsigned n=1; n<nin_group[j]; ++n) { 145 12 : Tools::convert( k+1, knum ); 146 24 : sort_act += ","+ knum; 147 : k++; 148 : } 149 2 : readInputLine( sort_act ); 150 4 : readInputLine( getShortcutLabel() + jnum + ": SORT ARG=" + getShortcutLabel() + "_selection" + jnum ); 151 16 : for(unsigned n=0; n<nin_group[j]; ++n) { 152 : std::string knum, nnum; 153 14 : Tools::convert( kk, knum ); 154 14 : Tools::convert( n+1, nnum ); 155 14 : kk++; 156 28 : readInputLine( getShortcutLabel() + "_coord-" + knum + ": COMBINE ARG=" + getShortcutLabel() + jnum + "." + nnum + " PERIODIC=NO" ); 157 : } 158 : } 159 1 : } 160 : 161 : } 162 : }