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/ActionRegister.h" 25 : 26 : namespace PLMD { 27 : namespace generic { 28 : 29 : //+PLUMEDOC PRINTANALYSIS PRINT 30 : /* 31 : Print quantities to a file. 32 : 33 : This directive can be used multiple times 34 : in the input so you can print files with different strides or print different quantities 35 : to different files. You can control the buffering of output using the \subpage FLUSH keyword. 36 : Output file is either appended or backed up depending on the presence of the \ref RESTART action. 37 : A per-action `RESTART` keyword can be used as well. 38 : 39 : Notice that printing happens in the so-called "update" phase. This implies that printing 40 : is affected by the presence of \ref UPDATE_IF actions. In addition, one might decide to start 41 : and stop printing at preassigned values of time using the `UPDATE_FROM` and `UPDATE_UNTIL` keywords. 42 : Keep into account that even on steps when the action is not updated (and thus the file is not printed) 43 : the argument will be activated. In other words, if you use `UPDATE_FROM` to start printing at a given time, 44 : the collective variables this PRINT statement depends on will be computed also before that time. 45 : 46 : \par Examples 47 : 48 : The following input instructs plumed to print the distance between atoms 3 and 5 on a file 49 : called COLVAR every 10 steps, and the distance and total energy on a file called COLVAR_ALL 50 : every 1000 steps. 51 : \plumedfile 52 : # compute distance: 53 : distance: DISTANCE ATOMS=2,5 54 : # compute total energy (potential) 55 : energy: ENERGY 56 : # print distance on a file 57 : PRINT ARG=distance STRIDE=10 FILE=COLVAR 58 : # print both variables on another file 59 : PRINT ARG=distance,energy STRIDE=1000 FILE=COLVAR_ALL 60 : \endplumedfile 61 : 62 : Notice that \ref DISTANCE and \ref ENERGY are computed respectively every 10 and 1000 steps, that is 63 : only when required. 64 : 65 : */ 66 : //+ENDPLUMEDOC 67 : 68 : class Print : 69 : public ActionPilot, 70 : public ActionWithArguments 71 : { 72 : std::string file; 73 : OFile ofile; 74 : std::string fmt; 75 : // small internal utility 76 : ///////////////////////////////////////// 77 : // these are crazy things just for debug: 78 : // they allow to change regularly the 79 : // printed argument 80 : int rotate; 81 : int rotateCountdown; 82 : int rotateLast; 83 : std::vector<Value*> rotateArguments; 84 : ///////////////////////////////////////// 85 : public: 86 225707 : void calculate() override {} 87 : void prepare() override; 88 : std::string writeInGraph() const override; 89 : explicit Print(const ActionOptions&); 90 : static void registerKeywords(Keywords& keys); 91 225585 : void apply() override {} 92 : void update() override; 93 : ~Print(); 94 : }; 95 : 96 : PLUMED_REGISTER_ACTION(Print,"PRINT") 97 : 98 1126 : void Print::registerKeywords(Keywords& keys) { 99 1126 : Action::registerKeywords(keys); 100 1126 : ActionPilot::registerKeywords(keys); 101 1126 : ActionWithArguments::registerKeywords(keys); 102 2252 : keys.addInputKeyword("compulsory","ARG","scalar/vector/matrix","the labels of the values that you would like to print to the file"); 103 2252 : keys.add("compulsory","STRIDE","1","the frequency with which the quantities of interest should be output"); 104 2252 : keys.add("optional","FILE","the name of the file on which to output these quantities"); 105 2252 : keys.add("optional","FMT","the format that should be used to output real numbers"); 106 2252 : keys.add("hidden","_ROTATE","some funky thing implemented by GBussi"); 107 1126 : keys.use("RESTART"); 108 1126 : keys.use("UPDATE_FROM"); 109 1126 : keys.use("UPDATE_UNTIL"); 110 1126 : } 111 : 112 1124 : Print::Print(const ActionOptions&ao): 113 : Action(ao), 114 : ActionPilot(ao), 115 : ActionWithArguments(ao), 116 1124 : fmt("%f"), 117 2248 : rotate(0) 118 : { 119 1124 : ofile.link(*this); 120 2248 : parse("FILE",file); 121 1124 : if(file.length()>0) { 122 1124 : ofile.open(file); 123 1124 : log.printf(" on file %s\n",file.c_str()); 124 : } else { 125 0 : log.printf(" on plumed log file\n"); 126 0 : ofile.link(log); 127 : } 128 1124 : parse("FMT",fmt); 129 1124 : fmt=" "+fmt; 130 1124 : log.printf(" with format %s\n",fmt.c_str()); 131 7415 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 132 6291 : ofile.setupPrintValue( getPntrToArgument(i) ); 133 6291 : getPntrToArgument(i)->buildDataStore(true); 134 : } 135 : ///////////////////////////////////////// 136 : // these are crazy things just for debug: 137 : // they allow to change regularly the 138 : // printed argument 139 1124 : parse("_ROTATE",rotate); 140 1124 : if(rotate>0) { 141 1 : rotateCountdown=rotate; 142 4 : for(unsigned i=0; i<getNumberOfArguments(); ++i) rotateArguments.push_back( getPntrToArgument(i) ); 143 1 : std::vector<Value*> a(1,rotateArguments[0]); 144 1 : requestArguments(std::vector<Value*>(1,rotateArguments[0])); 145 1 : rotateLast=0; 146 : } 147 : ///////////////////////////////////////// 148 1124 : checkRead(); 149 1124 : } 150 : 151 8 : std::string Print::writeInGraph() const { 152 16 : return getName() + "\n" + "FILE=" + file; 153 : } 154 : 155 225851 : void Print::prepare() { 156 : ///////////////////////////////////////// 157 : // these are crazy things just for debug: 158 : // they allow to change regularly the 159 : // printed argument 160 225851 : if(rotate>0) { 161 5 : rotateCountdown--; 162 5 : if(rotateCountdown==0) { 163 2 : rotateCountdown=rotate; 164 2 : rotateLast++; 165 2 : rotateLast%=rotateArguments.size(); 166 4 : requestArguments(std::vector<Value*>(1,rotateArguments[rotateLast])); 167 : } 168 : } 169 : ///////////////////////////////////////// 170 225851 : } 171 : 172 218413 : void Print::update() { 173 218413 : ofile.fmtField(" %f"); 174 218413 : ofile.printField("time",getTime()); 175 766629 : for(unsigned i=0; i<getNumberOfArguments(); i++) { 176 548216 : ofile.fmtField(fmt); getPntrToArgument(i)->print( ofile ); 177 : } 178 218413 : ofile.printField(); 179 218413 : } 180 : 181 2248 : Print::~Print() { 182 2248 : } 183 : 184 : } 185 : 186 : 187 : }