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 9 : keys.needsAction("CONTACT_MATRIX"); keys.needsAction("DIAGONALIZE"); keys.needsAction("CUSTOM"); 98 9 : keys.needsAction("SELECT_COMPONENTS"); keys.needsAction("SORT"); keys.needsAction("COMBINE"); 99 6 : keys.addOutputComponent("coord","default","scalar","the sprint coordinates"); 100 3 : } 101 : 102 1 : Sprint::Sprint(const ActionOptions& ao): 103 : Action(ao), 104 1 : ActionShortcut(ao) 105 : { 106 2 : std::string matinp; parse("MATRIX",matinp); 107 1 : if( matinp.length()==0 ) { 108 2 : readInputLine( getShortcutLabel() + "_jmat: CONTACT_MATRIX " + convertInputLineToString() ); 109 2 : matinp = getShortcutLabel() + "_jmat"; 110 : } 111 1 : std::vector<unsigned> nin_group; unsigned ntot_atoms=0; 112 1 : for(unsigned i=1;; ++i) { 113 3 : std::string inum; Tools::convert( i, inum ); 114 6 : ActionWithValue* av = plumed.getActionSet().selectWithLabel<ActionWithValue*>( matinp + inum + inum ); 115 3 : if( !av ) break ; 116 2 : unsigned natoms = (av->copyOutput(0))->getShape()[0]; nin_group.push_back( natoms ); ntot_atoms += natoms; 117 2 : } 118 : 119 : // Diagonalization 120 2 : readInputLine( getShortcutLabel() + "_diag: DIAGONALIZE ARG=" + matinp + " VECTORS=1"); 121 : // Compute sprint coordinates as product of eigenvalue and eigenvector times square root of number of atoms in all groups 122 1 : std::string str_natoms; Tools::convert( ntot_atoms, str_natoms ); 123 3 : readInputLine( getShortcutLabel() + "_sp: CUSTOM ARG=" + getShortcutLabel() + "_diag.vals-1," + getShortcutLabel() + 124 2 : "_diag.vecs-1 FUNC=sqrt(" + str_natoms + ")*x*y PERIODIC=NO"); 125 : // Sort sprint coordinates for each group of atoms 126 1 : unsigned k=0, kk=0; 127 3 : for(unsigned j=0; j<nin_group.size(); ++j) { 128 2 : std::string jnum, knum; Tools::convert( j+1, jnum ); Tools::convert(k+1, knum); k++; 129 4 : std::string sort_act = getShortcutLabel() + "_selection" + jnum + ": SELECT_COMPONENTS ARG=" + getShortcutLabel() + "_sp COMPONENTS=" + knum; 130 14 : for(unsigned n=1; n<nin_group[j]; ++n) { 131 24 : Tools::convert( k+1, knum ); sort_act += ","+ knum; k++; 132 : } 133 2 : readInputLine( sort_act ); 134 4 : readInputLine( getShortcutLabel() + jnum + ": SORT ARG=" + getShortcutLabel() + "_selection" + jnum ); 135 16 : for(unsigned n=0; n<nin_group[j]; ++n) { 136 14 : std::string knum, nnum; Tools::convert( kk, knum ); Tools::convert( n+1, nnum ); kk++; 137 28 : readInputLine( getShortcutLabel() + "_coord-" + knum + ": COMBINE ARG=" + getShortcutLabel() + jnum + "." + nnum + " PERIODIC=NO" ); 138 : } 139 : } 140 1 : } 141 : 142 : } 143 : }