Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2011-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/ActionPilot.h" 23 : #include "core/ActionWithArguments.h" 24 : #include "core/ActionAtomistic.h" 25 : #include "core/ActionRegister.h" 26 : #include "tools/CheckInRange.h" 27 : 28 : //+PLUMEDOC PRINTANALYSIS PRINT_NDX 29 : /* 30 : Print an ndx file 31 : 32 : The following example shows how you can use this command to print out the indices of all the atoms 33 : that have a coordination number that is greater than or equal to 4. 34 : 35 : ```plumed 36 : # These three lines calculate the coordination numbers of 100 atoms 37 : c1: CONTACT_MATRIX GROUP=1-100 SWITCH={RATIONAL R_0=0.1 NN=6 MM=12} 38 : ones: ONES SIZE=100 39 : cc: MATRIX_VECTOR_PRODUCT ARG=c1,ones 40 : 41 : # This command then prints the indices of the atoms that have a coordination number that is greater than 4 42 : # every step 43 : PRINT_NDX ATOMS=1-100 ARG=cc FILE=index.ndx GREATER_THAN_OR_EQUAL=4 44 : ``` 45 : 46 : Obviously, if you want to print the indices of the atoms that have a coordination number that is equal to 4 47 : you use a command like the one shown below: 48 : 49 : ```plumed 50 : # These three lines calculate the coordination numbers of 100 atoms 51 : c1: CONTACT_MATRIX GROUP=1-100 SWITCH={RATIONAL R_0=0.1 NN=6 MM=12} 52 : ones: ONES SIZE=100 53 : cc: MATRIX_VECTOR_PRODUCT ARG=c1,ones 54 : 55 : # This command then prints the indices of the atoms that have a coordination number that is equal to 4 56 : # on every 10th step of the simulation 57 : PRINT_NDX ... 58 : ATOMS=1-100 ARG=cc FILE=index.ndx 59 : LESS_THAN_OR_EQUAL=4 60 : GREATER_THAN_OR_EQUAL=4 61 : STRIDE=10 62 : ... 63 : ``` 64 : 65 : A command like the one above is used in the [OUTPUT_CLUSTER](OUTPUT_CLUSTER.md) command that you can use to output the indices 66 : of the atoms that are in a particular cluster. 67 : 68 : ## RESTART, UPDATE_FROM and UPDATE_UNTIL 69 : 70 : Notice that the RESTART, UPDATE_FROM and UPDATE_UNTIL keywords keywords 71 : can be used in this action in the same way as they are used for [PRINT](PRINT.md). 72 : Consequently, if you would like to append to an existing file called `index.ndx` instead of backing that 73 : file up at the start of the calculation and outputting the data from the calculation on a new file called `index.ndx` 74 : you would use an input like the one shown below: 75 : 76 : ```plumed 77 : c1: CONTACT_MATRIX GROUP=1-100 SWITCH={RATIONAL R_0=0.1 NN=6 MM=12} 78 : ones: ONES SIZE=100 79 : cc: MATRIX_VECTOR_PRODUCT ARG=c1,ones 80 : 81 : PRINT_NDX ... 82 : ATOMS=1-100 ARG=cc FILE=index.ndx 83 : GREATER_THAN_OR_EQUAL=4 RESTART=YES 84 : ... 85 : ``` 86 : 87 : Similarly, if you want to only output the `index.ndx` file during the 400 ps time interval after the first 88 : 100 ps of the simulation you would use an input like the one shown below: 89 : 90 : ```plumed 91 : c1: CONTACT_MATRIX GROUP=1-100 SWITCH={RATIONAL R_0=0.1 NN=6 MM=12} 92 : ones: ONES SIZE=100 93 : cc: MATRIX_VECTOR_PRODUCT ARG=c1,ones 94 : 95 : PRINT_NDX ... 96 : ATOMS=1-100 ARG=cc FILE=index.ndx 97 : GREATER_THAN_OR_EQUAL=4 98 : UPDATE_FROM=100 UPDATE_UNTIL=500 99 : ... 100 : ``` 101 : 102 : */ 103 : //+ENDPLUMEDOC 104 : 105 : namespace PLMD { 106 : namespace generic { 107 : 108 : class PrintNDX : 109 : public ActionPilot, 110 : public ActionAtomistic, 111 : public ActionWithArguments { 112 : std::string file; 113 : OFile ofile; 114 : CheckInRange bounds; 115 : public: 116 4 : void calculate() override {} 117 : std::string writeInGraph() const override; 118 : explicit PrintNDX(const ActionOptions&); 119 : static void registerKeywords(Keywords& keys); 120 0 : bool actionHasForces() override { 121 0 : return false; 122 : } 123 0 : void calculateNumericalDerivatives( ActionWithValue* a=NULL ) override { 124 0 : plumed_error(); 125 : } 126 : void lockRequests() override; 127 : void unlockRequests() override; 128 4 : void apply() override {} 129 : void update() override; 130 12 : ~PrintNDX() {} 131 : }; 132 : 133 : PLUMED_REGISTER_ACTION(PrintNDX,"PRINT_NDX") 134 : 135 10 : void PrintNDX::registerKeywords(Keywords& keys) { 136 10 : Action::registerKeywords(keys); 137 10 : ActionPilot::registerKeywords(keys); 138 10 : ActionAtomistic::registerKeywords( keys ); 139 10 : ActionWithArguments::registerKeywords(keys); 140 20 : keys.addInputKeyword("optional","ARG","vector","the labels of vectors that should be used when printind the NDX file"); 141 10 : keys.add("atoms","ATOMS","the list of atoms that have the corresponding arguments"); 142 10 : keys.add("compulsory","STRIDE","1","the frequency with which the quantities of interest should be output"); 143 10 : keys.add("optional","FILE","the name of the file on which to output these quantities"); 144 10 : keys.add("optional","LESS_THAN_OR_EQUAL","when printing with arguments that are vectors only print components of vectors have a value less than or equal to this value"); 145 10 : keys.add("optional","GREATER_THAN_OR_EQUAL","when printing with arguments that are vectors only print components of vectors have a value greater than or equal to this value"); 146 10 : keys.use("RESTART"); 147 10 : keys.use("UPDATE_FROM"); 148 10 : keys.use("UPDATE_UNTIL"); 149 10 : } 150 : 151 4 : PrintNDX::PrintNDX(const ActionOptions&ao): 152 : Action(ao), 153 : ActionPilot(ao), 154 : ActionAtomistic(ao), 155 4 : ActionWithArguments(ao) { 156 4 : ofile.link(*this); 157 8 : parse("FILE",file); 158 4 : if(file.length()>0) { 159 4 : ofile.open(file); 160 4 : log.printf(" on file %s\n",file.c_str()); 161 : } else { 162 0 : log.printf(" on plumed log file\n"); 163 0 : ofile.link(log); 164 : } 165 4 : std::vector<AtomNumber> all_atoms; 166 8 : parseAtomList("ATOMS",all_atoms); 167 4 : std::vector<std::string> argnames( getNumberOfArguments() ); 168 4 : requestAtoms( all_atoms, false ); 169 8 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 170 4 : if( getPntrToArgument(i)->getRank()!=1 || getPntrToArgument(i)->hasDerivatives() ) { 171 0 : error("arguments for print ndx should be vector"); 172 : } 173 4 : if( getPntrToArgument(i)->getShape()[0]!=all_atoms.size() ) { 174 0 : error("mismatch between number of arguments and number of input atoms"); 175 : } 176 : argnames[i] = getPntrToArgument(i)->getName(); 177 : } 178 4 : log.printf(" printing ndx file containing indices of atoms that have arguments in ranges prescribed below \n"); 179 4 : log.printf(" full set of atom indices investigated are : "); 180 7988 : for(unsigned int i=0; i<all_atoms.size(); ++i) { 181 7984 : if ( (i+1) % 25 == 0 ) { 182 316 : log.printf(" \n"); 183 : } 184 7984 : log.printf(" %d", all_atoms[i].serial()); 185 : } 186 4 : log.printf("\n"); 187 4 : std::vector<std::string> str_upper, str_lower; 188 : std::string errors; 189 4 : parseVector("LESS_THAN_OR_EQUAL",str_upper); 190 4 : parseVector("GREATER_THAN_OR_EQUAL",str_lower); 191 4 : if( !bounds.setBounds( getNumberOfArguments(), str_lower, str_upper, errors ) ) { 192 0 : error( errors ); 193 : } 194 4 : if( bounds.wereSet() ) { 195 8 : log.printf(" %s \n", bounds.report( argnames ).c_str() ); 196 : } 197 4 : checkRead(); 198 4 : } 199 : 200 0 : std::string PrintNDX::writeInGraph() const { 201 0 : return getName() + "\n" + "FILE=" + file; 202 : } 203 : 204 4 : void PrintNDX::lockRequests() { 205 : ActionWithArguments::lockRequests(); 206 : ActionAtomistic::lockRequests(); 207 4 : } 208 : 209 4 : void PrintNDX::unlockRequests() { 210 : ActionWithArguments::unlockRequests(); 211 : ActionAtomistic::unlockRequests(); 212 4 : } 213 : 214 4 : void PrintNDX::update() { 215 : unsigned n=0; 216 4 : std::vector<double> argvals( getNumberOfArguments() ); 217 4 : ofile.printf("[ %s step %lld ] \n", getLabel().c_str(), getStep() ); 218 7988 : for(unsigned i=0; i<getNumberOfAtoms(); ++i) { 219 15968 : for(unsigned j=0; j<getNumberOfArguments(); ++j) { 220 7984 : argvals[j] = getPntrToArgument(j)->get(i); 221 : } 222 7984 : if( bounds.check( argvals ) ) { 223 156 : ofile.printf("%6d", getAbsoluteIndexes()[i].serial() ); 224 156 : n++; 225 156 : if( n%15==0 ) { 226 8 : ofile.printf("\n"); 227 : } 228 : } 229 : } 230 4 : ofile.printf("\n"); 231 4 : } 232 : 233 : } 234 : 235 : 236 : }