Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2015-2018 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 : \verbatim
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 : \endverbatim
77 : (See also \ref GROUP, \ref COORDINATION, and \ref DUMPATOMS)
78 :
79 : */
80 : //+ENDPLUMEDOC
81 :
82 : class UpdateIf:
83 : public ActionPilot,
84 : public ActionWithArguments
85 : {
86 : std::vector<double> lower;
87 : std::vector<double> upper;
88 : bool on;
89 : bool end;
90 : public:
91 : void prepare();
92 : void calculate();
93 : void beforeUpdate();
94 : explicit UpdateIf(const ActionOptions&);
95 : static void registerKeywords(Keywords& keys);
96 28 : void apply() {}
97 : ~UpdateIf();
98 : };
99 :
100 2530 : PLUMED_REGISTER_ACTION(UpdateIf,"UPDATE_IF")
101 :
102 8 : void UpdateIf::registerKeywords(Keywords& keys) {
103 8 : Action::registerKeywords(keys);
104 8 : ActionPilot::registerKeywords(keys);
105 8 : ActionWithArguments::registerKeywords(keys);
106 8 : keys.use("ARG");
107 8 : keys.add("compulsory","STRIDE","1","the frequency with which the quantities of interest should be output");
108 8 : keys.addFlag("END",false,"end");
109 8 : keys.add("optional","LESS_THAN","upper bound");
110 8 : keys.add("optional","MORE_THAN","lower bound");
111 8 : }
112 :
113 7 : UpdateIf::UpdateIf(const ActionOptions&ao):
114 : Action(ao),
115 : ActionPilot(ao),
116 : ActionWithArguments(ao),
117 : on(false),
118 7 : end(false)
119 : {
120 7 : parseFlag("END",end);
121 7 : parseVector("LESS_THAN",upper);
122 7 : parseVector("MORE_THAN",lower);
123 7 : if(end && upper.size()!=0) error("END and LESS_THAN are not compatible");
124 7 : if(end && lower.size()!=0) error("END and MORE_THAN are not compatible");
125 7 : if(upper.size()==0) upper.assign(getNumberOfArguments(),+std::numeric_limits<double>::max());
126 7 : if(lower.size()==0) lower.assign(getNumberOfArguments(),-std::numeric_limits<double>::max());
127 7 : if(upper.size()!=getNumberOfArguments()) error("LESS_THAN should have the same size as ARG");
128 7 : if(lower.size()!=getNumberOfArguments()) error("MORE_THAN should have the same size as ARG");
129 15 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
130 8 : log<<" boundaries for argument "<<i<<" "<<lower[i]<<" "<<upper[i]<<"\n";
131 : }
132 7 : checkRead();
133 7 : }
134 :
135 28 : void UpdateIf::prepare() {
136 28 : on=false;
137 28 : }
138 :
139 28 : void UpdateIf::calculate() {
140 28 : on=true;
141 60 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
142 32 : if(getArgument(i)>=upper[i] || getArgument(i)<=lower[i]) on=false;
143 : }
144 28 : }
145 :
146 28 : void UpdateIf::beforeUpdate() {
147 28 : if(end) plumed.updateFlagsPop();
148 : else {
149 16 : if(on) plumed.updateFlagsPush(plumed.updateFlagsTop());
150 9 : else plumed.updateFlagsPush(false);
151 : }
152 28 : }
153 :
154 :
155 21 : UpdateIf::~UpdateIf() {
156 21 : }
157 :
158 : }
159 :
160 :
161 2523 : }
|