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