Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2012-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 DUMPPROJECTIONS 32 : /* 33 : Dump the derivatives with respect to the input parameters for one or more objects (generally CVs, functions or biases). 34 : 35 : Consider the following PLUMED input: 36 : 37 : ```plumed 38 : x1: CENTER ATOMS=1-10 39 : x2: CENTER ATOMS=11-20 40 : r: DISTANCE ATOMS=x1,x2 41 : ``` 42 : 43 : The derivatives of the distance `r` with respect to the atomic positions, $X_i$, are given by: 44 : 45 : $$ 46 : \frac{\partial r}{\partial X_i} = \frac{\partial r}{\partial x_1}\frac{\partial r}{\partial x_2}\frac{\partial x_1}{\partial X_i}\frac{\partial x_2}{\partial X_i} 47 : $$ 48 : 49 : For the input above there are 69 of these derivatives in total. These include the derivatives of $r$ with respect to the $x$, $y$ and $z$ components of the 10 atomic 50 : positions that are used to calculate $x_1$, the derivatives of $r$ with respect to the $x$, $y$ and $z$ components of the 10 atomic 51 : positions that are used to calculate $x_2$ and the 9 derivatives of $r$ with respect to the cell vectors. 52 : 53 : If we add a DUMPROJECTIONS command to the above input as shown below: 54 : 55 : ```plumed 56 : x1: CENTER ATOMS=1-10 57 : x2: CENTER ATOMS=11-20 58 : d: DISTANCE ATOMS=x1,x2 59 : DUMPPROJECTIONS ARG=d FILE=proj STRIDE=20 60 : ``` 61 : 62 : PLUMED will output these 69 derivatives to the proj file. 63 : 64 : !!! caution "only works for scalars" 65 : 66 : This action cannot be used if non rank zero objects are passed between actions that are used to calculate the quantity (`d` in the above examples) 67 : whose projections are being output using the DUMPPROJECTIONS command 68 : 69 : ## RESTART, UPDATE_FROM and UPDATE_UNTIL 70 : 71 : Notice that the RESTART, UPDATE_FROM and UPDATE_UNTIL keywords keywords 72 : can be used in this action in the same way as they are used for [PRINT](PRINT.md). 73 : Consequently, if you would like to append derivatives to an existing file called `proj` instead of backing that 74 : file up at the start of the calculation and outputting the data from the calculation on a new file called `proj` 75 : you would use an input like the one shown below: 76 : 77 : ```plumed 78 : x1: CENTER ATOMS=1-10 79 : x2: CENTER ATOMS=11-20 80 : d: DISTANCE ATOMS=x1,x2 81 : DUMPPROJECTIONS ARG=d STRIDE=1 FILE=proj FMT=%10.6f RESTART=YES 82 : ``` 83 : 84 : Similarly, if you want to only output the derivatives during the 400 ps time interval after the first 85 : 100 ps of the simulation you would use an input like the one shown below: 86 : 87 : ```plumed 88 : x1: CENTER ATOMS=1-10 89 : x2: CENTER ATOMS=11-20 90 : d: DISTANCE ATOMS=x1,x2 91 : DUMPPROJECTIONS ARG=d STRIDE=1 FILE=d UPDATE_FROM=100 UPDATE_UNTIL=500 92 : ``` 93 : 94 : 95 : */ 96 : //+ENDPLUMEDOC 97 : 98 : class DumpProjections : 99 : public ActionPilot, 100 : public ActionWithArguments { 101 : std::string file; 102 : std::string fmt; 103 : OFile of; 104 : public: 105 3 : void calculate() override {} 106 : explicit DumpProjections(const ActionOptions&); 107 : static void registerKeywords(Keywords& keys); 108 3 : void apply() override {} 109 : void update() override; 110 3 : bool checkNeedsGradients()const override { 111 3 : return true; 112 : } 113 : ~DumpProjections(); 114 : }; 115 : 116 : PLUMED_REGISTER_ACTION(DumpProjections,"DUMPPROJECTIONS") 117 : 118 5 : void DumpProjections::registerKeywords(Keywords& keys) { 119 5 : Action::registerKeywords(keys); 120 5 : ActionPilot::registerKeywords(keys); 121 5 : ActionWithArguments::registerKeywords(keys); 122 10 : keys.addInputKeyword("compulsory","ARG","scalar","the labels of the values whose gradients should be outpu"); 123 5 : keys.add("compulsory","STRIDE","1","the frequency with which the derivatives should be output"); 124 5 : keys.add("compulsory","FILE","the name of the file on which to output the derivatives"); 125 5 : keys.add("compulsory","FMT","%15.10f","the format with which the derivatives should be output"); 126 5 : keys.use("RESTART"); 127 5 : keys.use("UPDATE_FROM"); 128 5 : keys.use("UPDATE_UNTIL"); 129 5 : } 130 : 131 1 : DumpProjections::DumpProjections(const ActionOptions&ao): 132 : Action(ao), 133 : ActionPilot(ao), 134 : ActionWithArguments(ao), 135 1 : fmt("%15.10f") { 136 2 : parse("FILE",file); 137 1 : if( file.length()==0 ) { 138 0 : error("filename not specified"); 139 : } 140 1 : parse("FMT",fmt); 141 1 : fmt=" "+fmt; 142 1 : of.link(*this); 143 1 : of.open(file); 144 1 : log.printf(" on file %s\n",file.c_str()); 145 1 : log.printf(" with format %s\n",fmt.c_str()); 146 1 : checkRead(); 147 : 148 3 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 149 2 : if( getPntrToArgument(i)->getRank()!=0 ) { 150 0 : error("cannot use DUMPPROJECTIONS with actions that are not scalars"); 151 : } 152 2 : (getPntrToArgument(i)->getPntrToAction())->turnOnDerivatives(); 153 : } 154 1 : } 155 : 156 : 157 3 : void DumpProjections::update() { 158 6 : of.fmtField(" %f").printField("time",getTime()); 159 9 : for(unsigned i=0; i<getNumberOfArguments(); i++) { 160 18 : for(unsigned j=0; j<getNumberOfArguments(); j++) { 161 12 : of.fmtField(fmt); 162 24 : of.printField(getPntrToArgument(i)->getName()+"-"+getPntrToArgument(j)->getName(),getProjection(i,j)); 163 : } 164 : } 165 3 : of.printField(); 166 3 : } 167 : 168 2 : DumpProjections::~DumpProjections() { 169 2 : } 170 : 171 : } 172 : 173 : 174 : }