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/ActionWithValue.h" 24 : #include "core/ActionWithArguments.h" 25 : #include "core/ActionRegister.h" 26 : #include "tools/File.h" 27 : 28 : namespace PLMD { 29 : namespace generic { 30 : 31 : //+PLUMEDOC PRINTANALYSIS DUMPDERIVATIVES 32 : /* 33 : Dump the derivatives with respect to the input parameters for scalar values (generally CVs, functions or biases). 34 : 35 : You can use this command to output the derivatives of a scalar with respect to whatever input parameters are used to 36 : calculate that scalar. For example, the following input instructs plumed to write a file called deriv that contains both the 37 : analytical and numerical derivatives of the distance between atoms 1 and 2. 38 : 39 : ```plumed 40 : distance: DISTANCE ATOMS=1,2 41 : distanceN: DISTANCE ATOMS=1,2 NUMERICAL_DERIVATIVES 42 : DUMPDERIVATIVES ARG=distance,distanceN STRIDE=1 FILE=deriv 43 : ``` 44 : 45 : This input outputs the derivative of the distance with respect to the atom positions and the cell vectors (virial-like form). 46 : It will thus output 15 deriatives for the two quantities output - the derivatives with respect to the x,y and z components of the input atoms 47 : and the 9 components of the virial. 48 : 49 : By contast the following input will only output 1 derivative; namely, the derivative of the switching function, `f`, with respect to the input distance, `d`. 50 : 51 : ```plumed 52 : d: DISTANCE ATOMS=1,2 53 : f: LESS_THAN ARG=d SWITCH={RATIONAL R_0=0.2} 54 : DUMPDERIVATIVES ARG=f STRIDE=1 FILE=deriv 55 : ``` 56 : 57 : __You can only use this command to output the derivatives of rank 0 (scalar) values. You cannot use it to output derivatives of vector, matrix of function values.__ 58 : 59 : */ 60 : //+ENDPLUMEDOC 61 : 62 : class DumpDerivatives : 63 : public ActionPilot, 64 : public ActionWithArguments { 65 : std::string file; 66 : std::string fmt; 67 : OFile of; 68 : public: 69 12418 : void calculate() override {} 70 : explicit DumpDerivatives(const ActionOptions&); 71 : static void registerKeywords(Keywords& keys); 72 12376 : void apply() override {} 73 : void update() override; 74 : ~DumpDerivatives(); 75 : }; 76 : 77 : PLUMED_REGISTER_ACTION(DumpDerivatives,"DUMPDERIVATIVES") 78 : 79 267 : void DumpDerivatives::registerKeywords(Keywords& keys) { 80 267 : Action::registerKeywords(keys); 81 267 : ActionPilot::registerKeywords(keys); 82 267 : ActionWithArguments::registerKeywords(keys); 83 534 : keys.addInputKeyword("compulsory","ARG","scalar","the labels of the values whose derivatives should be output"); 84 267 : keys.add("compulsory","STRIDE","1","the frequency with which the derivatives should be output"); 85 267 : keys.add("compulsory","FILE","the name of the file on which to output the derivatives"); 86 267 : keys.add("compulsory","FMT","%15.10f","the format with which the derivatives should be output"); 87 267 : keys.use("RESTART"); 88 267 : keys.use("UPDATE_FROM"); 89 267 : keys.use("UPDATE_UNTIL"); 90 267 : } 91 : 92 265 : DumpDerivatives::DumpDerivatives(const ActionOptions&ao): 93 : Action(ao), 94 : ActionPilot(ao), 95 : ActionWithArguments(ao), 96 265 : fmt("%15.10f") { 97 530 : parse("FILE",file); 98 265 : if( file.length()==0 ) { 99 0 : error("name of output file was not specified"); 100 : } 101 265 : parse("FMT",fmt); 102 265 : fmt=" "+fmt; 103 265 : of.link(*this); 104 265 : of.open(file); 105 265 : log.printf(" on file %s\n",file.c_str()); 106 265 : log.printf(" with format %s\n",fmt.c_str()); 107 : unsigned nargs=getNumberOfArguments(); 108 265 : if( nargs==0 ) { 109 0 : error("no arguments specified"); 110 : } 111 265 : (getPntrToArgument(0)->getPntrToAction())->turnOnDerivatives(); 112 265 : if( getPntrToArgument(0)->getRank()>0 ) { 113 0 : error("cannot dump derivatives of non-scalar objects"); 114 : } 115 265 : unsigned npar=getPntrToArgument(0)->getNumberOfDerivatives(); 116 265 : if( npar==0 ) { 117 0 : error("one or more arguments has no derivatives"); 118 : } 119 858 : for(unsigned i=1; i<nargs; i++) { 120 593 : (getPntrToArgument(i)->getPntrToAction())->turnOnDerivatives(); 121 593 : if( getPntrToArgument(i)->getRank()>0 ) { 122 0 : error("cannot dump derivatives of non-scalar objects"); 123 : } 124 593 : if( npar!=getPntrToArgument(i)->getNumberOfDerivatives() ) { 125 0 : error("the number of derivatives must be the same in all values being dumped"); 126 : } 127 : } 128 265 : checkRead(); 129 265 : } 130 : 131 : 132 9191 : void DumpDerivatives::update() { 133 9191 : unsigned npar=getPntrToArgument(0)->getNumberOfDerivatives(); 134 708454 : for(unsigned ipar=0; ipar<npar; ipar++) { 135 699263 : of.fmtField(" %f"); 136 699263 : of.printField("time",getTime()); 137 699263 : of.printField("parameter",(int)ipar); 138 3474279 : for(unsigned i=0; i<getNumberOfArguments(); i++) { 139 2775016 : of.fmtField(fmt); 140 2775016 : of.printField(getPntrToArgument(i)->getName(),getPntrToArgument(i)->getDerivative(ipar) ); 141 : } 142 699263 : of.printField(); 143 : } 144 9191 : } 145 : 146 530 : DumpDerivatives::~DumpDerivatives() { 147 530 : } 148 : 149 : } 150 : 151 : 152 : }