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