LCOV - code coverage report
Current view: top level - core - ActionToPutData.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 137 144 95.1 %
Date: 2026-11-12 10:48:31 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2017-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 "ActionToPutData.h"
      23             : #include "ActionRegister.h"
      24             : #include "PlumedMain.h"
      25             : #include "ActionSet.h"
      26             : 
      27             : //+PLUMEDOC ANALYSIS PUT
      28             : /*
      29             : Pass data into PLUMED
      30             : 
      31             : \par Examples
      32             : 
      33             : */
      34             : //+ENDPLUMEDOC
      35             : 
      36             : namespace PLMD {
      37             : 
      38             : PLUMED_REGISTER_ACTION(ActionToPutData,"PUT")
      39             : 
      40        9332 : void ActionToPutData::registerKeywords(Keywords& keys) {
      41        9332 :   ActionForInterface::registerKeywords( keys );
      42       18664 :   keys.add("compulsory","SHAPE","0","the shape of the value that is being passed to PLUMED");
      43       18664 :   keys.add("compulsory","UNIT","the unit of the quantity that is being passed to PLUMED through this value.  Can be either number, energy, time, length, mass or charge");
      44       18664 :   keys.add("compulsory","FORCE_UNIT","default","the units to use for the force");
      45       18664 :   keys.add("compulsory","PERIODIC","if the value being passed to plumed is periodic then you should specify the periodicity of the function.  If the value "
      46             :            "is not periodic you must state this using PERIODIC=NO.  Positions are passed with PERIODIC=NO even though special methods are used "
      47             :            "to deal with pbc");
      48       18664 :   keys.addFlag("CONSTANT",false,"does this quantity not depend on time");
      49       18664 :   keys.addFlag("FROM_DOMAINS",false,"is this quantity passed through the domain decomposition object");
      50       18664 :   keys.addFlag("MUTABLE",false,"can plumed change the value of the pointer that is passed from the MD code");
      51       18664 :   keys.addFlag("ROUND_TO_BASE_TEN",false,"is this quantity written by the user in base ten, as the timestep is.  If the MD code "
      52             :                "passes floats, the extra digits that appear when converting them to double are removed");
      53        9332 :   keys.setValueDescription("the data that was passed from the MD code");
      54        9332 : }
      55             : 
      56       10869 : ActionToPutData::ActionToPutData(const ActionOptions&ao):
      57             :   Action(ao),
      58             :   ActionForInterface(ao),
      59       10869 :   noforce(false),
      60       10869 :   forces_added_elsewhere(false),
      61       10869 :   fixed(false),
      62       10869 :   from_domains(false),
      63       10869 :   resetable(false),
      64       10869 :   dataCanBeSet(true),
      65       10869 :   unit(n),
      66       10869 :   mydata(DataPassingObject::create(plumed.getRealPrecision())) {
      67       10869 :   if( getName()!="ENERGY" && getName()!="PBC" ) {
      68             :     std::vector<unsigned> shape;
      69       18590 :     parseVector("SHAPE",shape);
      70        9295 :     if( shape.size()==1 && shape[0]==0 ) {
      71        1593 :       shape.resize(0);
      72        1593 :       addValue( shape );
      73             :     } else {
      74        7702 :       addValue( shape );
      75             :     }
      76             : 
      77             :     std::string unitstr, funitstr;
      78        9295 :     parse("UNIT",unitstr);
      79        9295 :     parse("FORCE_UNIT",funitstr);
      80        9295 :     setUnit( unitstr, funitstr );
      81             : 
      82             :     // Now sort out period
      83             :     std::vector<std::string> period;
      84       18590 :     parseVector("PERIODIC",period);
      85        9295 :     if( period.size()==1 ) {
      86        9293 :       if( period[0]!="NO") {
      87           0 :         error("input to PERIODIC keyword does not make sense");
      88             :       }
      89        9293 :       setNotPeriodic();
      90           2 :     } else if( period.size()==2 ) {
      91           2 :       setPeriodic( period[0], period[1] );
      92             :     } else {
      93           0 :       error("input to PERIODIC keyword does not make sense");
      94             :     }
      95             : 
      96        9295 :     parseFlag("CONSTANT",fixed);
      97        9295 :     if( fixed ) {
      98        4658 :       noforce=true;
      99        4658 :       copyOutput(0)->setConstant();
     100             :     }
     101        9295 :     parseFlag("FROM_DOMAINS",from_domains);
     102        9295 :     parseFlag("MUTABLE",resetable);
     103        9295 :     bool round_to_base_ten=false;
     104       18590 :     parseFlag("ROUND_TO_BASE_TEN",round_to_base_ten);
     105             :     mydata->setRoundToBaseTen( round_to_base_ten );
     106        9295 :   }
     107       10869 : }
     108             : 
     109       10869 : void ActionToPutData::setUnit( const std::string& unitstr, const std::string& funitstr ) {
     110       10869 :   if( unitstr=="number" ) {
     111          43 :     unit=n;
     112       10826 :   } else if( unitstr=="energy" ) {
     113         260 :     unit=e;
     114       10566 :   } else if( unitstr=="length" ) {
     115        6136 :     unit=l;
     116        4430 :   } else if( unitstr=="mass" ) {
     117        1534 :     unit=m;
     118        2896 :   } else if( unitstr=="charge" ) {
     119        1534 :     unit=q;
     120        1362 :   } else if( unitstr=="time" ) {
     121        1362 :     unit=t;
     122             :   } else {
     123           0 :     error( unitstr + " is not a valid input unit");
     124             :   }
     125             :   // Set the force units
     126       10869 :   if( funitstr=="default" ) {
     127        9335 :     funit=d;
     128        1534 :   } else if( funitstr=="energy" ) {
     129        1534 :     funit=eng;
     130             :   } else {
     131           0 :     error( funitstr + " is not a valid input force unit");
     132             :   }
     133       10869 : }
     134             : 
     135       12647 : std::string ActionToPutData::getUnitName() const {
     136       12647 :   if( unit==e ) {
     137         483 :     return "energy";
     138             :   }
     139       12164 :   if( unit==l ) {
     140        6272 :     return "length";
     141             :   }
     142        5892 :   if( unit==m ) {
     143        1568 :     return "mass";
     144             :   }
     145        4324 :   if( unit==q ) {
     146        1568 :     return "charge";
     147             :   }
     148        2756 :   if( unit==t ) {
     149        2756 :     return "time";
     150             :   }
     151           0 :   plumed_error();
     152             : }
     153             : 
     154      818399 : void ActionToPutData::setStart( const std::string& name, const unsigned& sss) {
     155      818399 :   plumed_assert( name==getLabel() );
     156             :   mydata->setStart(sss);
     157      818399 : }
     158             : 
     159      818399 : void ActionToPutData::setStride( const std::string& name, const unsigned& sss ) {
     160      818399 :   plumed_assert( name==getLabel() );
     161             :   mydata->setStride(sss);
     162      818399 : }
     163             : 
     164       12679 : void ActionToPutData::updateUnits( DataPassingTools* passtools ) {
     165             :   // Don't need to do anythign if this is just a number
     166       12679 :   if( unit==n ) {
     167             :     return ;
     168             :   }
     169             : 
     170       25294 :   double vunits=passtools->getUnitConversion( getUnitName() );
     171             :   mydata->setUnit(vunits);
     172       12647 :   if( fixed && wasset ) {
     173        3199 :     mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() );
     174             :   }
     175       12647 :   if( funit==eng ) {
     176        1568 :     mydata->setForceUnit( 1/passtools->getUnitConversion("energy"));
     177       11079 :   } else if( funit==d ) {
     178       11079 :     mydata->setForceUnit(1/passtools->getUnitConversion("energy")*vunits);
     179             :   }
     180             : }
     181             : 
     182     3028685 : bool ActionToPutData::setValuePointer( const std::string& name, const TypesafePtr & val ) {
     183     3028685 :   if( name!=getLabel() ) {
     184             :     return false;
     185             :   }
     186      819987 :   wasset=true;
     187      819993 :   plumed_massert( dataCanBeSet, "set " + getLabel() + " cannot be set at this time");
     188      819984 :   if( !from_domains ) {
     189      188730 :     if( !resetable && getPntrToComponent(0)->getRank()==0 ) {
     190        5581 :       mydata->saveValueAsDouble( val );
     191        5581 :       if( fixed ) {
     192        1592 :         mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() );
     193             :       }
     194             :     } else {
     195      183149 :       mydata->setValuePointer(val,getPntrToComponent(0)->getShape(), !resetable);
     196             :     }
     197             :   } else {
     198     1262508 :     mydata->setValuePointer(val,std::vector<unsigned>(), !resetable);
     199             :   }
     200             :   return true;
     201             : }
     202             : 
     203     1671811 : bool ActionToPutData::setForcePointer( const std::string& name, const TypesafePtr & val ) {
     204     1671811 :   if( name!=getLabel() ) {
     205             :     return false;
     206             :   }
     207      555645 :   plumed_massert( dataCanBeSet, "force on " + getLabel() + " cannot be set at this time");
     208      555645 :   if( !from_domains ) {
     209      133023 :     mydata->setForcePointer(val,getPntrToComponent(0)->getShape());
     210             :   } else {
     211      845244 :     mydata->setForcePointer(val,std::vector<unsigned>());
     212             :   }
     213             :   return true;
     214             : }
     215             : 
     216        1350 : void ActionToPutData::getLocalValues( std::vector<double>& vals ) const {
     217        1350 :   mydata->share_data( vals );
     218        1350 : }
     219             : 
     220      186697 : void ActionToPutData::wait() {
     221      186697 :   dataCanBeSet=false;
     222      186697 :   if( fixed || !wasset ) {
     223             :     return;
     224             :   }
     225             :   plumed_assert( wasset );
     226      185146 :   mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() );
     227             : }
     228             : 
     229      877402 : void ActionToPutData::apply() {
     230      877402 :   if( getPntrToValue()->forcesWereAdded() && !noforce && !forces_added_elsewhere ) {
     231      451815 :     if( getName()=="ENERGY" || getDependencies().size()==0 ) {
     232      106968 :       mydata->add_force( getPntrToValue() );
     233             :     }
     234             :   }
     235      877402 : }
     236             : 
     237         150 : unsigned ActionToPutData::getNumberOfForcesToRescale() const {
     238             :   // Values that are passed through the domain decomposition only store the atoms
     239             :   // that are local to this rank, so the number of forces held in the buffer of the
     240             :   // MD code is the number of local atoms and not the number of values
     241         150 :   if( !from_domains || getDependencies().size()!=1 ) {
     242           0 :     return copyOutput(0)->getNumberOfValues();
     243             :   }
     244         150 :   plumed_assert(getDependencies()[0]); // needed for following calls, see #1046
     245         150 :   ActionForInterface* ai = getDependencies()[0]->castToActionForInterface();
     246         150 :   if( !ai ) {
     247           0 :     return copyOutput(0)->getNumberOfValues();
     248             :   }
     249         150 :   return ai->getNumberOfForcesToRescale();
     250             : }
     251             : 
     252         200 : void ActionToPutData::rescaleForces( const double& alpha ) {
     253         200 :   if( noforce ) {
     254             :     return;
     255             :   }
     256         150 :   wasscaled=true;
     257         150 :   mydata->rescale_force( getNumberOfForcesToRescale(), alpha, getPntrToValue() );
     258             : 
     259             : }
     260             : 
     261         798 : void ActionToPutData::writeBinary(std::ostream&o) {
     262         798 :   if(!fixed) {
     263         456 :     getPntrToValue()->writeBinary(o);
     264             :   }
     265         798 : }
     266             : 
     267         798 : void ActionToPutData::readBinary(std::istream&i) {
     268         798 :   if(!fixed) {
     269         456 :     getPntrToValue()->readBinary(i);
     270             :   }
     271         798 : }
     272             : 
     273             : }

Generated by: LCOV version 1.16