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();
91 : void calculate();
92 : void beforeUpdate();
93 : explicit UpdateIf(const ActionOptions&);
94 : static void registerKeywords(Keywords& keys);
95 28 : void apply() {}
96 : ~UpdateIf();
97 : };
98 :
99 6459 : 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 21 : 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 24 : 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 92 : 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 21 : UpdateIf::~UpdateIf() {
155 14 : }
156 :
157 : }
158 :
159 :
160 4839 : }
|