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 7118 : void ActionToPutData::registerKeywords(Keywords& keys) {
41 7118 : ActionForInterface::registerKeywords( keys );
42 14236 : keys.add("compulsory","SHAPE","0","the shape of the value that is being passed to PLUMED");
43 14236 : 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 14236 : keys.add("compulsory","FORCE_UNIT","default","the units to use for the force");
45 14236 : 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 14236 : keys.addFlag("CONSTANT",false,"does this quantity not depend on time");
49 14236 : keys.addFlag("FROM_DOMAINS",false,"is this quantity passed through the domain decomposition object");
50 14236 : keys.addFlag("MUTABLE",false,"can plumed change the value of the pointer that is passed from the MD code");
51 7118 : keys.setValueDescription("the data that was passed from the MD code");
52 7118 : }
53 :
54 8318 : ActionToPutData::ActionToPutData(const ActionOptions&ao):
55 : Action(ao),
56 : ActionForInterface(ao),
57 8318 : noforce(false),
58 8318 : fixed(false),
59 8318 : from_domains(false),
60 8318 : resetable(false),
61 8318 : dataCanBeSet(true),
62 8318 : unit(n),
63 8318 : mydata(DataPassingObject::create(plumed.getRealPrecision()))
64 : {
65 15401 : if( getName()!="ENERGY" && getName()!="PBC" ) {
66 14166 : std::vector<unsigned> shape; parseVector("SHAPE",shape);
67 7083 : if( shape.size()==1 && shape[0]==0 ) { shape.resize(0); addValue( shape ); }
68 5995 : else { addValue( shape ); }
69 :
70 7083 : std::string unitstr, funitstr; parse("UNIT",unitstr);
71 14166 : parse("FORCE_UNIT",funitstr); setUnit( unitstr, funitstr );
72 :
73 : // Now sort out period
74 14166 : std::vector<std::string> period; parseVector("PERIODIC",period);
75 7083 : if( period.size()==1 ) {
76 7081 : if( period[0]!="NO") error("input to PERIODIC keyword does not make sense");
77 7081 : setNotPeriodic();
78 2 : } else if( period.size()==2 ) setPeriodic( period[0], period[1] );
79 0 : else error("input to PERIODIC keyword does not make sense");
80 :
81 14166 : parseFlag("CONSTANT",fixed); if( fixed ) { noforce=true; copyOutput(0)->setConstant(); }
82 14166 : parseFlag("FROM_DOMAINS",from_domains); parseFlag("MUTABLE",resetable);
83 7083 : }
84 8318 : }
85 :
86 8318 : void ActionToPutData::setUnit( const std::string& unitstr, const std::string& funitstr ) {
87 8318 : if( unitstr=="number" ) unit=n;
88 8295 : else if( unitstr=="energy" ) unit=e;
89 8194 : else if( unitstr=="length" ) unit=l;
90 3414 : else if( unitstr=="mass" ) unit=m;
91 2219 : else if( unitstr=="charge" ) unit=q;
92 1024 : else if( unitstr=="time" ) unit=t;
93 0 : else error( unitstr + " is not a valid input unit");
94 : // Set the force units
95 8318 : if( funitstr=="default" ) funit=d;
96 1195 : else if( funitstr=="energy" ) funit=eng;
97 0 : else error( funitstr + " is not a valid input force unit");
98 8318 : }
99 :
100 9612 : std::string ActionToPutData::getUnitName() const {
101 9612 : if( unit==e ) return "energy";
102 9447 : if( unit==l ) return "length";
103 4535 : if( unit==m ) return "mass";
104 3307 : if( unit==q ) return "charge";
105 2079 : if( unit==t ) return "time";
106 0 : plumed_error();
107 : }
108 :
109 451096 : void ActionToPutData::setStart( const std::string& name, const unsigned& sss) {
110 451096 : plumed_assert( name==getLabel() ); mydata->setStart(sss);
111 451096 : }
112 :
113 451096 : void ActionToPutData::setStride( const std::string& name, const unsigned& sss ) {
114 451096 : plumed_assert( name==getLabel() ); mydata->setStride(sss);
115 451096 : }
116 :
117 9632 : void ActionToPutData::updateUnits( DataPassingTools* passtools ) {
118 : // Don't need to do anythign if this is just a number
119 9632 : if( unit==n ) return ;
120 :
121 19224 : double vunits=passtools->getUnitConversion( getUnitName() );
122 9612 : mydata->setUnit(vunits); if( fixed && wasset ) mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() );
123 9612 : if( funit==eng ) mydata->setForceUnit( 1/passtools->getUnitConversion("energy"));
124 8384 : else if( funit==d ) mydata->setForceUnit(1/passtools->getUnitConversion("energy")*vunits);
125 : }
126 :
127 1932787 : bool ActionToPutData::setValuePointer( const std::string& name, const TypesafePtr & val ) {
128 1932787 : if( name!=getLabel() ) return false;
129 452193 : wasset=true; plumed_massert( dataCanBeSet, "set " + getLabel() + " cannot be set at this time");
130 452184 : if( !from_domains ) {
131 97043 : if( !resetable && getPntrToComponent(0)->getRank()==0 ) {
132 5076 : mydata->saveValueAsDouble( val );
133 5076 : if( fixed ) mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() );
134 91967 : } else mydata->setValuePointer(val,getPntrToComponent(0)->getShape(), !resetable);
135 710282 : } else mydata->setValuePointer(val,std::vector<unsigned>(), !resetable);
136 : return true;
137 : }
138 :
139 977057 : bool ActionToPutData::setForcePointer( const std::string& name, const TypesafePtr & val ) {
140 977057 : if( name!=getLabel() ) return false;
141 282703 : plumed_massert( dataCanBeSet, "force on " + getLabel() + " cannot be set at this time");
142 282703 : if( !from_domains ) mydata->setForcePointer(val,getPntrToComponent(0)->getShape());
143 435756 : else mydata->setForcePointer(val,std::vector<unsigned>());
144 : return true;
145 : }
146 :
147 1350 : void ActionToPutData::getLocalValues( std::vector<double>& vals ) const {
148 1350 : mydata->share_data( vals );
149 1350 : }
150 :
151 94006 : void ActionToPutData::wait() {
152 94006 : dataCanBeSet=false; if( fixed || !wasset ) { return; } plumed_assert( wasset );
153 94006 : mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() );
154 : }
155 :
156 445330 : void ActionToPutData::apply() {
157 445330 : if( getPntrToValue()->forcesWereAdded() && !noforce ) {
158 182000 : if( getName()=="ENERGY" || getDependencies().size()==0 ) mydata->add_force( getPntrToValue() );
159 : }
160 445330 : }
161 :
162 150 : unsigned ActionToPutData::getNumberOfForcesToRescale() const {
163 150 : if( getName()!="ENERGY" || getDependencies().size()>0 ) return copyOutput(0)->getNumberOfValues();
164 0 : plumed_assert( getDependencies().size()==1 );
165 0 : plumed_assert(getDependencies()[0]); // needed for following calls, see #1046
166 0 : ActionForInterface* ai = getDependencies()[0]->castToActionForInterface();
167 0 : return ai->getNumberOfForcesToRescale();
168 : }
169 :
170 200 : void ActionToPutData::rescaleForces( const double& alpha ) {
171 200 : if( noforce ) return; wasscaled=true;
172 150 : mydata->rescale_force( getNumberOfForcesToRescale(), alpha, getPntrToValue() );
173 :
174 : }
175 :
176 798 : void ActionToPutData::writeBinary(std::ostream&o) {
177 798 : if(!fixed) getPntrToValue()->writeBinary(o);
178 798 : }
179 :
180 798 : void ActionToPutData::readBinary(std::istream&i) {
181 798 : if(!fixed) getPntrToValue()->readBinary(i);
182 798 : }
183 :
184 : }
|