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 GREATER_THAN_OR_EQUAL=4 44 : ``` 45 : 46 : This command is used in the [OUTPUT_CLUSTER](OUTPUT_CLUSTER.md) command that you can use to output the indices 47 : of the atoms that are in a particular cluster. 48 : 49 : */ 50 : //+ENDPLUMEDOC 51 : 52 : namespace PLMD { 53 : namespace generic { 54 : 55 : class PrintNDX : 56 : public ActionPilot, 57 : public ActionAtomistic, 58 : public ActionWithArguments { 59 : std::string file; 60 : OFile ofile; 61 : CheckInRange bounds; 62 : public: 63 4 : void calculate() override {} 64 : std::string writeInGraph() const override; 65 : explicit PrintNDX(const ActionOptions&); 66 : static void registerKeywords(Keywords& keys); 67 0 : bool actionHasForces() override { 68 0 : return false; 69 : } 70 0 : void calculateNumericalDerivatives( ActionWithValue* a=NULL ) override { 71 0 : plumed_error(); 72 : } 73 : void lockRequests() override; 74 : void unlockRequests() override; 75 4 : void apply() override {} 76 : void update() override; 77 12 : ~PrintNDX() {} 78 : }; 79 : 80 : PLUMED_REGISTER_ACTION(PrintNDX,"PRINT_NDX") 81 : 82 8 : void PrintNDX::registerKeywords(Keywords& keys) { 83 8 : Action::registerKeywords(keys); 84 8 : ActionPilot::registerKeywords(keys); 85 8 : ActionAtomistic::registerKeywords( keys ); 86 8 : ActionWithArguments::registerKeywords(keys); 87 16 : keys.addInputKeyword("optional","ARG","vector","the labels of vectors that should be used when printind the NDX file"); 88 8 : keys.add("atoms","ATOMS","the list of atoms that have the corresponding arguments"); 89 8 : keys.add("compulsory","STRIDE","1","the frequency with which the quantities of interest should be output"); 90 8 : keys.add("optional","FILE","the name of the file on which to output these quantities"); 91 8 : 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"); 92 8 : 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"); 93 8 : keys.use("RESTART"); 94 8 : keys.use("UPDATE_FROM"); 95 8 : keys.use("UPDATE_UNTIL"); 96 8 : } 97 : 98 4 : PrintNDX::PrintNDX(const ActionOptions&ao): 99 : Action(ao), 100 : ActionPilot(ao), 101 : ActionAtomistic(ao), 102 4 : ActionWithArguments(ao) { 103 4 : ofile.link(*this); 104 8 : parse("FILE",file); 105 4 : if(file.length()>0) { 106 4 : ofile.open(file); 107 4 : log.printf(" on file %s\n",file.c_str()); 108 : } else { 109 0 : log.printf(" on plumed log file\n"); 110 0 : ofile.link(log); 111 : } 112 : std::vector<AtomNumber> all_atoms; 113 8 : parseAtomList("ATOMS",all_atoms); 114 4 : std::vector<std::string> argnames( getNumberOfArguments() ); 115 4 : requestAtoms( all_atoms, false ); 116 8 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 117 4 : if( getPntrToArgument(i)->getRank()!=1 || getPntrToArgument(i)->hasDerivatives() ) { 118 0 : error("arguments for print ndx should be vector"); 119 : } 120 4 : if( getPntrToArgument(i)->getShape()[0]!=all_atoms.size() ) { 121 0 : error("mismatch between number of arguments and number of input atoms"); 122 : } 123 4 : getPntrToArgument(i)->buildDataStore(true); 124 : argnames[i] = getPntrToArgument(i)->getName(); 125 : } 126 4 : log.printf(" printing ndx file containing indices of atoms that have arguments in ranges prescribed below \n"); 127 4 : log.printf(" full set of atom indices investigated are : "); 128 7988 : for(unsigned int i=0; i<all_atoms.size(); ++i) { 129 7984 : if ( (i+1) % 25 == 0 ) { 130 316 : log.printf(" \n"); 131 : } 132 7984 : log.printf(" %d", all_atoms[i].serial()); 133 : } 134 4 : log.printf("\n"); 135 : std::vector<std::string> str_upper, str_lower; 136 : std::string errors; 137 4 : parseVector("LESS_THAN_OR_EQUAL",str_upper); 138 8 : parseVector("GREATER_THAN_OR_EQUAL",str_lower); 139 4 : if( !bounds.setBounds( getNumberOfArguments(), str_lower, str_upper, errors ) ) { 140 0 : error( errors ); 141 : } 142 4 : if( bounds.wereSet() ) { 143 8 : log.printf(" %s \n", bounds.report( argnames ).c_str() ); 144 : } 145 4 : checkRead(); 146 8 : } 147 : 148 0 : std::string PrintNDX::writeInGraph() const { 149 0 : return getName() + "\n" + "FILE=" + file; 150 : } 151 : 152 4 : void PrintNDX::lockRequests() { 153 : ActionWithArguments::lockRequests(); 154 : ActionAtomistic::lockRequests(); 155 4 : } 156 : 157 4 : void PrintNDX::unlockRequests() { 158 : ActionWithArguments::unlockRequests(); 159 : ActionAtomistic::unlockRequests(); 160 4 : } 161 : 162 4 : void PrintNDX::update() { 163 : unsigned n=0; 164 4 : std::vector<double> argvals( getNumberOfArguments() ); 165 4 : ofile.printf("[ %s step %d ] \n", getLabel().c_str(), getStep() ); 166 7988 : for(unsigned i=0; i<getNumberOfAtoms(); ++i) { 167 15968 : for(unsigned j=0; j<getNumberOfArguments(); ++j) { 168 7984 : argvals[j] = getPntrToArgument(j)->get(i); 169 : } 170 7984 : if( bounds.check( argvals ) ) { 171 156 : ofile.printf("%6d", getAbsoluteIndexes()[i].serial() ); 172 156 : n++; 173 156 : if( n%15==0 ) { 174 8 : ofile.printf("\n"); 175 : } 176 : } 177 : } 178 4 : ofile.printf("\n"); 179 4 : } 180 : 181 : } 182 : 183 : 184 : }