1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 Copyright (c) 2012-2021 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 #ifndef __PLUMED_vesselbase_Vessel_h
23 #define __PLUMED_vesselbase_Vessel_h
24
25 #include <string>
26 #include <cstring>
27 #include <vector>
28 #include <algorithm>
29 #include "tools/Exception.h"
30 #include "tools/Keywords.h"
31 #include "ActionWithVessel.h"
32
33 namespace PLMD {
34
35 class Communicator;
36 class Log;
37
38 namespace vesselbase {
39
40 /**
41 \ingroup TOOLBOX
42 Vessels are an important component of class PLMD::ActionWithVessel. This class
43 contains a large buffer array of doubles. The various elements of this array
44 can be accessed through vessels which are used to structure the elements of the
45 double array. As the buffer array is just a vector of doubles it can be easily
46 mpi gathered or passed to another node.
47 */
48
49 //class ActionWithVessel;
50 class Vessel;
51
52 /// This class is used to pass the input to Vessels
53 class VesselOptions {
54 friend class Vessel;
55 private:
56 /// The name of the particular vessel
57 std::string myname;
58 /// The label for this particular vessel;
59 std::string mylabel;
60 /// The numerical label for this vessel
61 int numlab;
62 /// Pointer to ActionWithVessel that this if from
63 ActionWithVessel* action;
64 /// The keywords
65 const Keywords& keywords;
66 static Keywords emptyKeys;
67 public:
68 /// The parameters that are read into the function
69 std::string parameters;
70 /// The constructor
71 VesselOptions( const std::string& thisname, const std::string& thislab, const unsigned& nlab, const std::string& params, ActionWithVessel* aa );
72 VesselOptions(const VesselOptions& da, const Keywords& keys );
73 };
74
75 class Vessel {
76 friend class ActionWithVessel;
77 private:
78 /// The keyword for the vessel in the input file
79 std::string myname;
80 /// The label for the vessel for referencing
81 std::string mylabel;
82 /// The numerical label for this object
83 const int numlab;
84 /// The action that this vessel is created within
85 ActionWithVessel* action;
86 /// The number of elements in this vessel's buffered data
87 unsigned bufsize;
88 /// Directive line.
89 /// This line is progressively erased during vessel construction
90 /// so as to check if all the present keywords are correct.
91 std::vector<std::string> line;
92 /// The keywords
93 const PLMD::Keywords& keywords;
94 /// This just checks we have done checkRead
95 bool finished_read;
96 protected:
97 /// The start of this Vessel's buffer in buffer in the underlying ActionWithVessel
98 unsigned bufstart;
99 /// Return the numerical label
100 int getNumericalLabel() const ;
101 /// Report an error
102 void error(const std::string& errmsg);
103 /// Parse something from the input
104 template<class T>
105 void parse(const std::string&key, T&t);
106 /// Parse one keyword as std::vector
107 template<class T>
108 void parseVector(const std::string&key,std::vector<T>&t);
109 /// Parse one keyword as boolean flag
110 void parseFlag(const std::string&key,bool&t);
111 /// This returns the whole input line (it is used for less_than/more_than/between)
112 std::string getAllInput();
113 /// Return a pointer to the action we are working in
114 ActionWithVessel* getAction() const ;
115 /// Return the value of the tolerance
116 double getTolerance() const ;
117 /// Return the value of the neighbor list tolerance
118 double getNLTolerance() const ;
119 /// Return the size of the buffer
120 unsigned getSizeOfBuffer() const ;
121 /// Set the size of the data buffer
122 void resizeBuffer( const unsigned& n );
123 public:
124 /// Reserve any keywords for this particular vessel
125 static void registerKeywords( Keywords& keys );
126 /// Convert the name to the label of the component
127 static std::string transformName( const std::string& name );
128 /// The constructor
129 explicit Vessel( const VesselOptions& da );
130 /// Virtual destructor needed for proper inheritance
~Vessel()131 virtual ~Vessel() {}
132 /// Return the name
133 std::string getName() const ;
134 /// Return the label
135 std::string getLabel() const ;
136 /// Check that readin was fine
137 void checkRead();
138 /// Return a description of the vessel contents
139 virtual std::string description()=0;
140 /// Set the start of the buffer
141 virtual void setBufferStart( unsigned& start );
142 /// Do something before the loop
prepare()143 virtual void prepare() {}
144 /// This is replaced in bridges so we can transform the derivatives
145 virtual MultiValue& transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals );
146 /// Calculate the part of the vessel that is done in the loop
147 virtual void calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const = 0;
148 /// Complete the calculation once the loop is finished
149 virtual void finish( const std::vector<double>& )=0;
150 /// Reset the size of the buffers
151 virtual void resize()=0;
152 /// Retrieve the forces on the quantities in the vessel
153 virtual bool applyForce( std::vector<double>& forces )=0;
154 };
155
156 template<class T>
parse(const std::string & key,T & t)157 void Vessel::parse(const std::string&key, T&t ) {
158 plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
159
160 // Now try to read the keyword
161 bool found=Tools::parse(line,key,t); std::string def;
162 if ( !found && keywords.style(key,"compulsory") ) {
163 if( keywords.getDefaultValue(key,def) ) {
164 plumed_massert( def.length()!=0 && Tools::convert(def,t), "default value is dubious");
165 } else {
166 error("keyword " + key + " is comulsory for this vessel");
167 }
168 }
169 }
170
171 template<class T>
parseVector(const std::string & key,std::vector<T> & t)172 void Vessel::parseVector(const std::string&key,std::vector<T>&t) {
173 // Check keyword has been registered
174 plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
175 unsigned size=t.size(); bool skipcheck=false;
176 if(size==0) skipcheck=true;
177
178 // Now try to read the keyword
179 bool found; std::string def; T val;
180 found=Tools::parseVector(line,key,t);
181
182 // Check vectors size is correct (not if this is atoms or ARG)
183 if( !keywords.style(key,"atoms") && found ) {
184 if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size");
185 }
186
187 // If it isn't read and it is compulsory see if a default value was specified
188 if ( !found && keywords.style(key,"compulsory") ) {
189 if( keywords.getDefaultValue(key,def) ) {
190 if( def.length()==0 || !Tools::convert(def,val) ) {
191 plumed_merror("weird default value for keyword " + key );
192 } else {
193 for(unsigned i=0; i<t.size(); ++i) t[i]=val;
194 }
195 } else {
196 error("keyword " + key + " is compulsory");
197 }
198 } else if ( !found ) {
199 t.resize(0);
200 }
201 }
202
203 inline
getNumericalLabel()204 int Vessel::getNumericalLabel() const {
205 return numlab;
206 }
207
208 inline
setBufferStart(unsigned & start)209 void Vessel::setBufferStart( unsigned& start ) {
210 bufstart=start; start+=bufsize;
211 }
212
213 inline
transformDerivatives(const unsigned & current,MultiValue & myvals,MultiValue & bvals)214 MultiValue& Vessel::transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals ) {
215 return myvals;
216 }
217
218 inline
resizeBuffer(const unsigned & n)219 void Vessel::resizeBuffer( const unsigned& n ) {
220 bufsize=n;
221 }
222
223 inline
getTolerance()224 double Vessel::getTolerance() const {
225 return action->tolerance;
226 }
227
228 inline
getNLTolerance()229 double Vessel::getNLTolerance() const {
230 return action->nl_tolerance;
231 }
232
233 inline
getAction()234 ActionWithVessel* Vessel::getAction() const {
235 return action;
236 }
237
238 inline
getSizeOfBuffer()239 unsigned Vessel::getSizeOfBuffer() const {
240 return bufsize;
241 }
242
243 }
244 }
245 #endif
246