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 ATOMS=1,2 LABEL=distance 48 : DISTANCE ATOMS=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 11880 : void calculate() override {} 66 : explicit DumpDerivatives(const ActionOptions&); 67 : static void registerKeywords(Keywords& keys); 68 11850 : void apply() override {} 69 : void update() override; 70 : ~DumpDerivatives(); 71 : }; 72 : 73 8294 : PLUMED_REGISTER_ACTION(DumpDerivatives,"DUMPDERIVATIVES") 74 : 75 232 : void DumpDerivatives::registerKeywords(Keywords& keys) { 76 232 : Action::registerKeywords(keys); 77 232 : ActionPilot::registerKeywords(keys); 78 232 : ActionWithArguments::registerKeywords(keys); 79 464 : keys.use("ARG"); 80 1160 : keys.add("compulsory","STRIDE","1","the frequency with which the derivatives should be output"); 81 928 : keys.add("compulsory","FILE","the name of the file on which to output the derivatives"); 82 1160 : keys.add("compulsory","FMT","%15.10f","the format with which the derivatives should be output"); 83 464 : keys.use("RESTART"); 84 464 : keys.use("UPDATE_FROM"); 85 464 : keys.use("UPDATE_UNTIL"); 86 232 : } 87 : 88 231 : DumpDerivatives::DumpDerivatives(const ActionOptions&ao): 89 : Action(ao), 90 : ActionPilot(ao), 91 : ActionWithArguments(ao), 92 462 : fmt("%15.10f") 93 : { 94 462 : parse("FILE",file); 95 231 : if( file.length()==0 ) error("name of output file was not specified"); 96 462 : parse("FMT",fmt); 97 462 : fmt=" "+fmt; 98 231 : of.link(*this); 99 231 : of.open(file); 100 231 : log.printf(" on file %s\n",file.c_str()); 101 231 : log.printf(" with format %s\n",fmt.c_str()); 102 : unsigned nargs=getNumberOfArguments(); 103 231 : if( nargs==0 ) error("no arguments specified"); 104 231 : (getPntrToArgument(0)->getPntrToAction())->turnOnDerivatives(); 105 231 : unsigned npar=getPntrToArgument(0)->getNumberOfDerivatives(); 106 231 : if( npar==0 ) error("one or more arguments has no derivatives"); 107 524 : for(unsigned i=1; i<nargs; i++) { 108 524 : (getPntrToArgument(i)->getPntrToAction())->turnOnDerivatives(); 109 524 : if( npar!=getPntrToArgument(i)->getNumberOfDerivatives() ) error("the number of derivatives must be the same in all values being dumped"); 110 : } 111 231 : checkRead(); 112 231 : } 113 : 114 : 115 11835 : void DumpDerivatives::update() { 116 11835 : unsigned npar=getPntrToArgument(0)->getNumberOfDerivatives(); 117 804908 : for(unsigned ipar=0; ipar<npar; ipar++) { 118 1586146 : of.fmtField(" %f"); 119 1586146 : of.printField("time",getTime()); 120 1586146 : of.printField("parameter",(int)ipar); 121 3768083 : for(unsigned i=0; i<getNumberOfArguments(); i++) { 122 2975010 : of.fmtField(fmt); 123 2975010 : of.printField(getPntrToArgument(i)->getName(),getPntrToArgument(i)->getDerivative(ipar) ); 124 : } 125 793073 : of.printField(); 126 : } 127 11835 : } 128 : 129 924 : DumpDerivatives::~DumpDerivatives() { 130 462 : } 131 : 132 : } 133 : 134 : 135 5874 : }