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