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