LCOV - code coverage report
Current view: top level - generic - UpdateIf.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 47 51 92.2 %
Date: 2025-04-08 21:11:17 Functions: 8 10 80.0 %

          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             : }

Generated by: LCOV version 1.16