Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2015-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/ActionWithArguments.h" 24 : #include "core/ActionRegister.h" 25 : #include "core/PlumedMain.h" 26 : 27 : namespace PLMD { 28 : namespace generic { 29 : 30 : //+PLUMEDOC PRINTANALYSIS UPDATE_IF 31 : /* 32 : Conditional update of other actions. 33 : 34 : This action can be used to enable and disable the update step for the following actions 35 : depending on the value of its arguments. This allows one to extract snapshots 36 : with value of some CVs in a given range. 37 : 38 : When called with MORE_THAN and/or LESS_THAN keywords, this action starts an if block. 39 : The block is executed if all the arguments are less than all the respective values 40 : in the LESS_THAN keyword (if present) and all the arguments are more than all the 41 : respective values in the MORE_THAN keyword (if present). 42 : 43 : When called with the END flag, this action ends the corresponding IF block. 44 : Notice that in this case one should also provide the ARG keyword. It is recommended to 45 : use the same ARG keyword that was used to begin the block, so as to make the input more readable. 46 : 47 : Of course, blocks can be nested at will. 48 : 49 : There are many potential usages for this keyword. One might e.g. decide to analyze some variable 50 : only when another variable is within a given range. 51 : 52 : > [!CAUTION] 53 : > Notice that not all the possible usage make 54 : > particular sense. For example, conditionally updating a \ref METAD keyword 55 : > (that is: adding hills only if a variable is within a given range) 56 : > can lead to unexpected results. 57 : 58 : ## Examples 59 : 60 : The following input instructs plumed dump all the snapshots where an atom is in touch with 61 : the solute. 62 : 63 : ```plumed 64 : solute: GROUP ATOMS=1-124 65 : coord: COORDINATION GROUPA=solute GROUPB=500 R_0=0.5 66 : 67 : # A coordination number higher than 0.5 indicate that there is at least one 68 : # atom of group `solute` at less than 5 A from atom number 500 69 : 70 : UPDATE_IF ARG=coord MORE_THAN=0.5 71 : DUMPATOMS ATOMS=solute,500 FILE=output.xyz 72 : UPDATE_IF ARG=coord END 73 : ``` 74 : 75 : */ 76 : //+ENDPLUMEDOC 77 : 78 : class UpdateIf: 79 : public ActionPilot, 80 : public ActionWithArguments { 81 : std::vector<double> lower; 82 : std::vector<double> upper; 83 : bool on; 84 : bool end; 85 : public: 86 : void prepare() override; 87 : void calculate() override; 88 : void beforeUpdate() override; 89 : explicit UpdateIf(const ActionOptions&); 90 : static void registerKeywords(Keywords& keys); 91 28 : void apply() override {} 92 : ~UpdateIf(); 93 : }; 94 : 95 : PLUMED_REGISTER_ACTION(UpdateIf,"UPDATE_IF") 96 : 97 9 : void UpdateIf::registerKeywords(Keywords& keys) { 98 9 : Action::registerKeywords(keys); 99 9 : ActionPilot::registerKeywords(keys); 100 9 : ActionWithArguments::registerKeywords(keys); 101 18 : keys.addInputKeyword("compulsory","ARG","scalar","the labels of values that should be used to make the decision on whether to update or not"); 102 9 : keys.add("compulsory","STRIDE","1","the frequency with which the quantities of interest should be output"); 103 9 : keys.addFlag("END",false,"end"); 104 9 : keys.add("optional","LESS_THAN","upper bound"); 105 9 : keys.add("optional","MORE_THAN","lower bound"); 106 9 : } 107 : 108 7 : UpdateIf::UpdateIf(const ActionOptions&ao): 109 : Action(ao), 110 : ActionPilot(ao), 111 : ActionWithArguments(ao), 112 7 : on(false), 113 7 : end(false) { 114 7 : parseFlag("END",end); 115 7 : parseVector("LESS_THAN",upper); 116 7 : parseVector("MORE_THAN",lower); 117 7 : if(end && upper.size()!=0) { 118 0 : error("END and LESS_THAN are not compatible"); 119 : } 120 7 : if(end && lower.size()!=0) { 121 0 : error("END and MORE_THAN are not compatible"); 122 : } 123 7 : if(upper.size()==0) { 124 4 : upper.assign(getNumberOfArguments(),+std::numeric_limits<double>::max()); 125 : } 126 7 : if(lower.size()==0) { 127 5 : lower.assign(getNumberOfArguments(),-std::numeric_limits<double>::max()); 128 : } 129 7 : if(upper.size()!=getNumberOfArguments()) { 130 0 : error("LESS_THAN should have the same size as ARG"); 131 : } 132 7 : if(lower.size()!=getNumberOfArguments()) { 133 0 : error("MORE_THAN should have the same size as ARG"); 134 : } 135 15 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 136 8 : log<<" boundaries for argument "<<i<<" "<<lower[i]<<" "<<upper[i]<<"\n"; 137 : } 138 7 : checkRead(); 139 7 : } 140 : 141 28 : void UpdateIf::prepare() { 142 28 : on=false; 143 28 : } 144 : 145 28 : void UpdateIf::calculate() { 146 28 : on=true; 147 60 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 148 32 : if(getArgument(i)>=upper[i] || getArgument(i)<=lower[i]) { 149 10 : on=false; 150 : } 151 : } 152 28 : } 153 : 154 28 : void UpdateIf::beforeUpdate() { 155 28 : if(end) { 156 12 : plumed.updateFlagsPop(); 157 : } else { 158 16 : if(on) { 159 14 : plumed.updateFlagsPush(plumed.updateFlagsTop()); 160 : } else { 161 9 : plumed.updateFlagsPush(false); 162 : } 163 : } 164 28 : } 165 : 166 : 167 14 : UpdateIf::~UpdateIf() { 168 14 : } 169 : 170 : } 171 : 172 : 173 : }