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] 65 : > 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) 66 : > whose projections are being output using the DUMPPROJECTIONS command 67 : 68 : */ 69 : //+ENDPLUMEDOC 70 : 71 : class DumpProjections : 72 : public ActionPilot, 73 : public ActionWithArguments { 74 : std::string file; 75 : std::string fmt; 76 : OFile of; 77 : public: 78 3 : void calculate() override {} 79 : explicit DumpProjections(const ActionOptions&); 80 : static void registerKeywords(Keywords& keys); 81 3 : void apply() override {} 82 : void update() override; 83 3 : bool checkNeedsGradients()const override { 84 3 : return true; 85 : } 86 : ~DumpProjections(); 87 : }; 88 : 89 : PLUMED_REGISTER_ACTION(DumpProjections,"DUMPPROJECTIONS") 90 : 91 3 : void DumpProjections::registerKeywords(Keywords& keys) { 92 3 : Action::registerKeywords(keys); 93 3 : ActionPilot::registerKeywords(keys); 94 3 : ActionWithArguments::registerKeywords(keys); 95 6 : keys.addInputKeyword("compulsory","ARG","scalar","the labels of the values whose gradients should be outpu"); 96 3 : keys.add("compulsory","STRIDE","1","the frequency with which the derivatives should be output"); 97 3 : keys.add("compulsory","FILE","the name of the file on which to output the derivatives"); 98 3 : keys.add("compulsory","FMT","%15.10f","the format with which the derivatives should be output"); 99 3 : keys.use("RESTART"); 100 3 : keys.use("UPDATE_FROM"); 101 3 : keys.use("UPDATE_UNTIL"); 102 3 : } 103 : 104 1 : DumpProjections::DumpProjections(const ActionOptions&ao): 105 : Action(ao), 106 : ActionPilot(ao), 107 : ActionWithArguments(ao), 108 1 : fmt("%15.10f") { 109 2 : parse("FILE",file); 110 1 : if( file.length()==0 ) { 111 0 : error("filename not specified"); 112 : } 113 1 : parse("FMT",fmt); 114 1 : fmt=" "+fmt; 115 1 : of.open(file); 116 1 : log.printf(" on file %s\n",file.c_str()); 117 1 : log.printf(" with format %s\n",fmt.c_str()); 118 1 : checkRead(); 119 : 120 3 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 121 2 : if( getPntrToArgument(i)->getRank()!=0 ) { 122 0 : error("cannot use DUMPPROJECTIONS with actions that are not scalars"); 123 : } 124 2 : (getPntrToArgument(i)->getPntrToAction())->turnOnDerivatives(); 125 : } 126 1 : } 127 : 128 : 129 3 : void DumpProjections::update() { 130 6 : of.fmtField(" %f").printField("time",getTime()); 131 9 : for(unsigned i=0; i<getNumberOfArguments(); i++) { 132 18 : for(unsigned j=0; j<getNumberOfArguments(); j++) { 133 12 : of.fmtField(fmt); 134 24 : of.printField(getPntrToArgument(i)->getName()+"-"+getPntrToArgument(j)->getName(),getProjection(i,j)); 135 : } 136 : } 137 3 : of.printField(); 138 3 : } 139 : 140 2 : DumpProjections::~DumpProjections() { 141 2 : } 142 : 143 : } 144 : 145 : 146 : }