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 command can be used to output quantities to a file. The following demonstrates a very 34 : simple example: 35 : 36 : ```plumed 37 : d: DISTANCE ATOMS=1,2 38 : PRINT ARG=d FILE=colvar 39 : ``` 40 : 41 : This command outputs the distance between atom 1 and 2 to a file called colvar every step of 42 : trajectory. If you want to output the distance less frequently you can use the STRIDE keyword 43 : as illustrated below: 44 : 45 : ```plumed 46 : d: DISTANCE ATOMS=1,2 47 : PRINT ARG=d FILE=colvar STRIDE=10 48 : ``` 49 : 50 : With the input above the distance is only output on every 10th step. Notice this distance will only 51 : be calculated on every step as this quantity is not used on every other step. 52 : 53 : You can also use the PRINT command to output objects that have a rank that is greater than zero. 54 : For example, the following input calculates a vector of three distances. These three distances 55 : are then output to the output colvar file every step. 56 : 57 : ```plumed 58 : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4 ATOMS3=5,6 59 : PRINT ARG=d FILE=colvar 60 : ``` 61 : 62 : Alterantively, we can output a matrix by using an input like the one shown below: 63 : 64 : ```plumed 65 : d: DISTANCE_MATRIX GROUP=1-4 66 : PRINT ARG=d FILE=colvar 67 : ``` 68 : 69 : The output `colvar` file here will contain the 16 elements of the matrix on each line output. You can 70 : also use PRINT to output functions on grids. However, you are probably better using [DUMPGRID](DUMPGRID.md) or 71 : [DUMPCUBE](DUMPCUBE.md) to output functions on grids. 72 : 73 : The PRINT directive can be used multiple times in the input so you can print files with different strides or print different quantities 74 : to different files as illustrated in the example input below: 75 : 76 : ```plumed 77 : # compute distance: 78 : distance: DISTANCE ATOMS=2,5 79 : # compute total energy (potential) 80 : energy: ENERGY 81 : # print distance on a file 82 : PRINT ARG=distance STRIDE=10 FILE=COLVAR 83 : # print both variables on another file 84 : PRINT ARG=distance,energy STRIDE=1000 FILE=COLVAR_ALL 85 : ``` 86 : 87 : The input above instructs plumed to print the distance between atoms 3 and 5 on a file 88 : called COLVAR every 10 steps, and the distance and total energy on a file called COLVAR_ALL 89 : every 1000 steps. 90 : 91 : You can control the buffering of output using the [FLUSH](FLUSH.md) keyword. Furthermore, whether the output file is 92 : appended or backed up depends on whetehr or not the [RESTART](RESTART.md) action is present on the file. If you add `RESTART=yes` on the 93 : line containing the PRINT directive the file will be appended also. 94 : 95 : Printing happens in the so-called "update" phase. This implies that printing 96 : is affected by the presence of [UPDATE_IF](UPDATE_IF.md) actions. One can thus decide to start 97 : and stop printing at preassigned values of time using the `UPDATE_FROM` and `UPDATE_UNTIL` keywords. 98 : Keep into account that even on steps when the action is not updated (and thus the file is not printed) 99 : the argument will be activated. In other words, if you use `UPDATE_FROM` to start printing at a given time, 100 : the collective variables this PRINT statement depends on will be computed also before that time. 101 : 102 : */ 103 : //+ENDPLUMEDOC 104 : 105 : class Print : 106 : public ActionPilot, 107 : public ActionWithArguments { 108 : std::string file; 109 : OFile ofile; 110 : std::string fmt; 111 : // small internal utility 112 : ///////////////////////////////////////// 113 : // these are crazy things just for debug: 114 : // they allow to change regularly the 115 : // printed argument 116 : int rotate; 117 : int rotateCountdown; 118 : int rotateLast; 119 : std::vector<Value*> rotateArguments; 120 : ///////////////////////////////////////// 121 : public: 122 227868 : void calculate() override {} 123 : void prepare() override; 124 : std::string writeInGraph() const override; 125 : explicit Print(const ActionOptions&); 126 : static void registerKeywords(Keywords& keys); 127 227746 : void apply() override {} 128 : void update() override; 129 : ~Print(); 130 : }; 131 : 132 : PLUMED_REGISTER_ACTION(Print,"PRINT") 133 : 134 1156 : void Print::registerKeywords(Keywords& keys) { 135 1156 : Action::registerKeywords(keys); 136 1156 : ActionPilot::registerKeywords(keys); 137 1156 : ActionWithArguments::registerKeywords(keys); 138 2312 : keys.addInputKeyword("compulsory","ARG","scalar/vector/matrix","the labels of the values that you would like to print to the file"); 139 1156 : keys.add("compulsory","STRIDE","1","the frequency with which the quantities of interest should be output"); 140 1156 : keys.add("optional","FILE","the name of the file on which to output these quantities"); 141 1156 : keys.add("optional","FMT","the format that should be used to output real numbers"); 142 1156 : keys.add("hidden","_ROTATE","some funky thing implemented by GBussi"); 143 1156 : keys.use("RESTART"); 144 1156 : keys.use("UPDATE_FROM"); 145 1156 : keys.use("UPDATE_UNTIL"); 146 1156 : } 147 : 148 1154 : Print::Print(const ActionOptions&ao): 149 : Action(ao), 150 : ActionPilot(ao), 151 : ActionWithArguments(ao), 152 1154 : fmt("%f"), 153 2308 : rotate(0) { 154 1154 : ofile.link(*this); 155 2308 : parse("FILE",file); 156 1154 : if(file.length()>0) { 157 1154 : ofile.open(file); 158 1154 : log.printf(" on file %s\n",file.c_str()); 159 : } else { 160 0 : log.printf(" on plumed log file\n"); 161 0 : ofile.link(log); 162 : } 163 1154 : parse("FMT",fmt); 164 1154 : fmt=" "+fmt; 165 1154 : log.printf(" with format %s\n",fmt.c_str()); 166 7565 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 167 6411 : ofile.setupPrintValue( getPntrToArgument(i) ); 168 6411 : getPntrToArgument(i)->buildDataStore(true); 169 : } 170 : ///////////////////////////////////////// 171 : // these are crazy things just for debug: 172 : // they allow to change regularly the 173 : // printed argument 174 1154 : parse("_ROTATE",rotate); 175 1154 : if(rotate>0) { 176 1 : rotateCountdown=rotate; 177 4 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 178 3 : rotateArguments.push_back( getPntrToArgument(i) ); 179 : } 180 1 : std::vector<Value*> a(1,rotateArguments[0]); 181 1 : requestArguments(std::vector<Value*>(1,rotateArguments[0])); 182 1 : rotateLast=0; 183 : } 184 : ///////////////////////////////////////// 185 1154 : checkRead(); 186 1154 : } 187 : 188 8 : std::string Print::writeInGraph() const { 189 16 : return getName() + "\n" + "FILE=" + file; 190 : } 191 : 192 228012 : void Print::prepare() { 193 : ///////////////////////////////////////// 194 : // these are crazy things just for debug: 195 : // they allow to change regularly the 196 : // printed argument 197 228012 : if(rotate>0) { 198 5 : rotateCountdown--; 199 5 : if(rotateCountdown==0) { 200 2 : rotateCountdown=rotate; 201 2 : rotateLast++; 202 2 : rotateLast%=rotateArguments.size(); 203 4 : requestArguments(std::vector<Value*>(1,rotateArguments[rotateLast])); 204 : } 205 : } 206 : ///////////////////////////////////////// 207 228012 : } 208 : 209 220574 : void Print::update() { 210 220574 : ofile.fmtField(" %f"); 211 220574 : ofile.printField("time",getTime()); 212 775474 : for(unsigned i=0; i<getNumberOfArguments(); i++) { 213 554900 : ofile.fmtField(fmt); 214 554900 : getPntrToArgument(i)->print( ofile ); 215 : } 216 220574 : ofile.printField(); 217 220574 : } 218 : 219 2308 : Print::~Print() { 220 2308 : } 221 : 222 : } 223 : 224 : 225 : }