LCOV - code coverage report
Current view: top level - core - ActionToPutData.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 130 139 93.5 %
Date: 2026-03-30 11:13:23 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        7280 : void ActionToPutData::registerKeywords(Keywords& keys) {
      41        7280 :   ActionForInterface::registerKeywords( keys );
      42       14560 :   keys.add("compulsory","SHAPE","0","the shape of the value that is being passed to PLUMED");
      43       14560 :   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       14560 :   keys.add("compulsory","FORCE_UNIT","default","the units to use for the force");
      45       14560 :   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       14560 :   keys.addFlag("CONSTANT",false,"does this quantity not depend on time");
      49       14560 :   keys.addFlag("FROM_DOMAINS",false,"is this quantity passed through the domain decomposition object");
      50       14560 :   keys.addFlag("MUTABLE",false,"can plumed change the value of the pointer that is passed from the MD code");
      51        7280 :   keys.setValueDescription("the data that was passed from the MD code");
      52        7280 : }
      53             : 
      54        8505 : ActionToPutData::ActionToPutData(const ActionOptions&ao):
      55             :   Action(ao),
      56             :   ActionForInterface(ao),
      57        8505 :   noforce(false),
      58        8505 :   fixed(false),
      59        8505 :   from_domains(false),
      60        8505 :   resetable(false),
      61        8505 :   dataCanBeSet(true),
      62        8505 :   unit(n),
      63        8505 :   mydata(DataPassingObject::create(plumed.getRealPrecision())) {
      64       15748 :   if( getName()!="ENERGY" && getName()!="PBC" ) {
      65             :     std::vector<unsigned> shape;
      66       14486 :     parseVector("SHAPE",shape);
      67        7243 :     if( shape.size()==1 && shape[0]==0 ) {
      68        1113 :       shape.resize(0);
      69        1113 :       addValue( shape );
      70             :     } else {
      71        6130 :       addValue( shape );
      72             :     }
      73             : 
      74             :     std::string unitstr, funitstr;
      75        7243 :     parse("UNIT",unitstr);
      76        7243 :     parse("FORCE_UNIT",funitstr);
      77        7243 :     setUnit( unitstr, funitstr );
      78             : 
      79             :     // Now sort out period
      80             :     std::vector<std::string> period;
      81       14486 :     parseVector("PERIODIC",period);
      82        7243 :     if( period.size()==1 ) {
      83        7241 :       if( period[0]!="NO") {
      84           0 :         error("input to PERIODIC keyword does not make sense");
      85             :       }
      86        7241 :       setNotPeriodic();
      87           2 :     } else if( period.size()==2 ) {
      88           2 :       setPeriodic( period[0], period[1] );
      89             :     } else {
      90           0 :       error("input to PERIODIC keyword does not make sense");
      91             :     }
      92             : 
      93        7243 :     parseFlag("CONSTANT",fixed);
      94        7243 :     if( fixed ) {
      95        3554 :       noforce=true;
      96        3554 :       copyOutput(0)->setConstant();
      97             :     }
      98        7243 :     parseFlag("FROM_DOMAINS",from_domains);
      99        7243 :     parseFlag("MUTABLE",resetable);
     100        7243 :   }
     101        8505 : }
     102             : 
     103        8505 : void ActionToPutData::setUnit( const std::string& unitstr, const std::string& funitstr ) {
     104        8505 :   if( unitstr=="number" ) {
     105          23 :     unit=n;
     106        8482 :   } else if( unitstr=="energy" ) {
     107         101 :     unit=e;
     108        8381 :   } else if( unitstr=="length" ) {
     109        4888 :     unit=l;
     110        3493 :   } else if( unitstr=="mass" ) {
     111        1222 :     unit=m;
     112        2271 :   } else if( unitstr=="charge" ) {
     113        1222 :     unit=q;
     114        1049 :   } else if( unitstr=="time" ) {
     115        1049 :     unit=t;
     116             :   } else {
     117           0 :     error( unitstr + " is not a valid input unit");
     118             :   }
     119             :   // Set the force units
     120        8505 :   if( funitstr=="default" ) {
     121        7283 :     funit=d;
     122        1222 :   } else if( funitstr=="energy" ) {
     123        1222 :     funit=eng;
     124             :   } else {
     125           0 :     error( funitstr + " is not a valid input force unit");
     126             :   }
     127        8505 : }
     128             : 
     129        9824 : std::string ActionToPutData::getUnitName() const {
     130        9824 :   if( unit==e ) {
     131         165 :     return "energy";
     132             :   }
     133        9659 :   if( unit==l ) {
     134        5020 :     return "length";
     135             :   }
     136        4639 :   if( unit==m ) {
     137        1255 :     return "mass";
     138             :   }
     139        3384 :   if( unit==q ) {
     140        1255 :     return "charge";
     141             :   }
     142        2129 :   if( unit==t ) {
     143        2129 :     return "time";
     144             :   }
     145           0 :   plumed_error();
     146             : }
     147             : 
     148      463802 : void ActionToPutData::setStart( const std::string& name, const unsigned& sss) {
     149      463802 :   plumed_assert( name==getLabel() );
     150             :   mydata->setStart(sss);
     151      463802 : }
     152             : 
     153      463802 : void ActionToPutData::setStride( const std::string& name, const unsigned& sss ) {
     154      463802 :   plumed_assert( name==getLabel() );
     155             :   mydata->setStride(sss);
     156      463802 : }
     157             : 
     158        9844 : void ActionToPutData::updateUnits( DataPassingTools* passtools ) {
     159             :   // Don't need to do anythign if this is just a number
     160        9844 :   if( unit==n ) {
     161             :     return ;
     162             :   }
     163             : 
     164       19648 :   double vunits=passtools->getUnitConversion( getUnitName() );
     165             :   mydata->setUnit(vunits);
     166        9824 :   if( fixed && wasset ) {
     167        2254 :     mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() );
     168             :   }
     169        9824 :   if( funit==eng ) {
     170        1255 :     mydata->setForceUnit( 1/passtools->getUnitConversion("energy"));
     171        8569 :   } else if( funit==d ) {
     172        8569 :     mydata->setForceUnit(1/passtools->getUnitConversion("energy")*vunits);
     173             :   }
     174             : }
     175             : 
     176     1989974 : bool ActionToPutData::setValuePointer( const std::string& name, const TypesafePtr & val ) {
     177     1989974 :   if( name!=getLabel() ) {
     178             :     return false;
     179             :   }
     180      464918 :   wasset=true;
     181      464924 :   plumed_massert( dataCanBeSet, "set " + getLabel() + " cannot be set at this time");
     182      464915 :   if( !from_domains ) {
     183       99186 :     if( !resetable && getPntrToComponent(0)->getRank()==0 ) {
     184        5101 :       mydata->saveValueAsDouble( val );
     185        5101 :       if( fixed ) {
     186        1112 :         mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() );
     187             :       }
     188             :     } else {
     189       94085 :       mydata->setValuePointer(val,getPntrToComponent(0)->getShape(), !resetable);
     190             :     }
     191             :   } else {
     192      731458 :     mydata->setValuePointer(val,std::vector<unsigned>(), !resetable);
     193             :   }
     194             :   return true;
     195             : }
     196             : 
     197     1006701 : bool ActionToPutData::setForcePointer( const std::string& name, const TypesafePtr & val ) {
     198     1006701 :   if( name!=getLabel() ) {
     199             :     return false;
     200             :   }
     201      291175 :   plumed_massert( dataCanBeSet, "force on " + getLabel() + " cannot be set at this time");
     202      291175 :   if( !from_domains ) {
     203       66943 :     mydata->setForcePointer(val,getPntrToComponent(0)->getShape());
     204             :   } else {
     205      448464 :     mydata->setForcePointer(val,std::vector<unsigned>());
     206             :   }
     207             :   return true;
     208             : }
     209             : 
     210        1350 : void ActionToPutData::getLocalValues( std::vector<double>& vals ) const {
     211        1350 :   mydata->share_data( vals );
     212        1350 : }
     213             : 
     214       96124 : void ActionToPutData::wait() {
     215       96124 :   dataCanBeSet=false;
     216       96124 :   if( fixed || !wasset ) {
     217             :     return;
     218             :   }
     219             :   plumed_assert( wasset );
     220       96124 :   mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() );
     221             : }
     222             : 
     223      458038 : void ActionToPutData::apply() {
     224      458038 :   if( getPntrToValue()->forcesWereAdded() && !noforce ) {
     225      190368 :     if( getName()=="ENERGY" || getDependencies().size()==0 ) {
     226       41997 :       mydata->add_force( getPntrToValue() );
     227             :     }
     228             :   }
     229      458038 : }
     230             : 
     231         150 : unsigned ActionToPutData::getNumberOfForcesToRescale() const {
     232         150 :   if( getName()!="ENERGY" || getDependencies().size()>0 ) {
     233         150 :     return copyOutput(0)->getNumberOfValues();
     234             :   }
     235           0 :   plumed_assert( getDependencies().size()==1 );
     236           0 :   plumed_assert(getDependencies()[0]); // needed for following calls, see #1046
     237           0 :   ActionForInterface* ai = getDependencies()[0]->castToActionForInterface();
     238           0 :   return ai->getNumberOfForcesToRescale();
     239             : }
     240             : 
     241         200 : void ActionToPutData::rescaleForces( const double& alpha ) {
     242         200 :   if( noforce ) {
     243             :     return;
     244             :   }
     245         150 :   wasscaled=true;
     246         150 :   mydata->rescale_force( getNumberOfForcesToRescale(), alpha, getPntrToValue() );
     247             : 
     248             : }
     249             : 
     250         798 : void ActionToPutData::writeBinary(std::ostream&o) {
     251         798 :   if(!fixed) {
     252         456 :     getPntrToValue()->writeBinary(o);
     253             :   }
     254         798 : }
     255             : 
     256         798 : void ActionToPutData::readBinary(std::istream&i) {
     257         798 :   if(!fixed) {
     258         456 :     getPntrToValue()->readBinary(i);
     259             :   }
     260         798 : }
     261             : 
     262             : }

Generated by: LCOV version 1.16