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/ActionWithValue.h"
24 : #include "core/ActionWithArguments.h"
25 : #include "core/ActionRegister.h"
26 : #include "tools/File.h"
27 :
28 : using namespace std;
29 :
30 : namespace PLMD {
31 : namespace generic {
32 :
33 : //+PLUMEDOC PRINTANALYSIS DUMPDERIVATIVES
34 : /*
35 : Dump the derivatives with respect to the input parameters for one or more objects (generally CVs, functions or biases).
36 :
37 : For a CV this line in input instructs plumed to print the derivative of the CV with respect to the atom positions
38 : and the cell vectors (virial-like form). In contrast, for a function or bias the derivative with respect to the input "CVs"
39 : will be output. This command is most often used to test whether or not analytic derivatives have been implemented correctly. This
40 : can be done by outputting the derivatives calculated analytically and numerically. You can control the buffering of output using the \ref FLUSH keyword.
41 :
42 : \par Examples
43 :
44 : The following input instructs plumed to write a file called deriv that contains both the
45 : analytical and numerical derivatives of the distance between atoms 1 and 2.
46 : \plumedfile
47 : DISTANCE ATOM=1,2 LABEL=distance
48 : DISTANCE ATOM=1,2 LABEL=distanceN NUMERICAL_DERIVATIVES
49 : DUMPDERIVATIVES ARG=distance,distanceN STRIDE=1 FILE=deriv
50 : \endplumedfile
51 :
52 : (See also \ref DISTANCE)
53 :
54 : */
55 : //+ENDPLUMEDOC
56 :
57 : class DumpDerivatives :
58 : public ActionPilot,
59 : public ActionWithArguments
60 : {
61 : string file;
62 : string fmt;
63 : OFile of;
64 : public:
65 11612 : void calculate() {}
66 : explicit DumpDerivatives(const ActionOptions&);
67 : static void registerKeywords(Keywords& keys);
68 11582 : void apply() {}
69 : void update();
70 : ~DumpDerivatives();
71 : };
72 :
73 6653 : PLUMED_REGISTER_ACTION(DumpDerivatives,"DUMPDERIVATIVES")
74 :
75 202 : void DumpDerivatives::registerKeywords(Keywords& keys) {
76 202 : Action::registerKeywords(keys);
77 202 : ActionPilot::registerKeywords(keys);
78 202 : ActionWithArguments::registerKeywords(keys);
79 404 : keys.use("ARG");
80 1010 : keys.add("compulsory","STRIDE","1","the frequency with which the derivatives should be output");
81 808 : keys.add("compulsory","FILE","the name of the file on which to output the derivatives");
82 1010 : keys.add("compulsory","FMT","%15.10f","the format with which the derivatives should be output");
83 404 : keys.use("RESTART");
84 404 : keys.use("UPDATE_FROM");
85 404 : keys.use("UPDATE_UNTIL");
86 202 : }
87 :
88 201 : DumpDerivatives::DumpDerivatives(const ActionOptions&ao):
89 : Action(ao),
90 : ActionPilot(ao),
91 : ActionWithArguments(ao),
92 402 : fmt("%15.10f")
93 : {
94 402 : parse("FILE",file);
95 201 : if( file.length()==0 ) error("name of output file was not specified");
96 402 : parse("FMT",fmt);
97 402 : fmt=" "+fmt;
98 201 : of.link(*this);
99 201 : of.open(file);
100 402 : log.printf(" on file %s\n",file.c_str());
101 402 : log.printf(" with format %s\n",fmt.c_str());
102 : unsigned nargs=getNumberOfArguments();
103 201 : if( nargs==0 ) error("no arguments specified");
104 201 : (getPntrToArgument(0)->getPntrToAction())->turnOnDerivatives();
105 201 : unsigned npar=getPntrToArgument(0)->getNumberOfDerivatives();
106 201 : if( npar==0 ) error("one or more arguments has no derivatives");
107 1057 : for(unsigned i=1; i<nargs; i++) {
108 428 : (getPntrToArgument(i)->getPntrToAction())->turnOnDerivatives();
109 428 : if( npar!=getPntrToArgument(i)->getNumberOfDerivatives() ) error("the number of derivatives must be the same in all values being dumped");
110 : }
111 201 : checkRead();
112 201 : }
113 :
114 :
115 11582 : void DumpDerivatives::update() {
116 11582 : unsigned npar=getPntrToArgument(0)->getNumberOfDerivatives();
117 1442564 : for(unsigned ipar=0; ipar<npar; ipar++) {
118 1430982 : of.fmtField(" %f");
119 1430982 : of.printField("time",getTime());
120 1430982 : of.printField("parameter",(int)ipar);
121 6327717 : for(unsigned i=0; i<getNumberOfArguments(); i++) {
122 2806113 : of.fmtField(fmt);
123 2806113 : of.printField(getPntrToArgument(i)->getName(),getPntrToArgument(i)->getDerivative(ipar) );
124 : }
125 715491 : of.printField();
126 : }
127 11582 : }
128 :
129 603 : DumpDerivatives::~DumpDerivatives() {
130 402 : }
131 :
132 : }
133 :
134 :
135 4839 : }
|