Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2012-2019 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 1864 : 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 : /// A copy of the communicator
100 : Communicator& comm;
101 : /// Return the numerical label
102 : int getNumericalLabel() const ;
103 : /// Report an error
104 : void error(const std::string& errmsg);
105 : /// Parse something from the input
106 : template<class T>
107 : void parse(const std::string&key, T&t);
108 : /// Parse one keyword as std::vector
109 : template<class T>
110 : void parseVector(const std::string&key,std::vector<T>&t);
111 : /// Parse one keyword as boolean flag
112 : void parseFlag(const std::string&key,bool&t);
113 : /// This returns the whole input line (it is used for less_than/more_than/between)
114 : std::string getAllInput();
115 : /// Return a pointer to the action we are working in
116 : ActionWithVessel* getAction() const ;
117 : /// Return the value of the tolerance
118 : double getTolerance() const ;
119 : /// Return the value of the neighbor list tolerance
120 : double getNLTolerance() const ;
121 : /// Return the size of the buffer
122 : unsigned getSizeOfBuffer() const ;
123 : /// Set the size of the data buffer
124 : void resizeBuffer( const unsigned& n );
125 : public:
126 : /// Reference to the log on which to output details
127 : Log& log;
128 : /// Reserve any keywords for this particular vessel
129 : static void registerKeywords( Keywords& keys );
130 : /// Convert the name to the label of the component
131 : static std::string transformName( const std::string& name );
132 : /// The constructor
133 : explicit Vessel( const VesselOptions& da );
134 : /// Virtual destructor needed for proper inheritance
135 1068 : virtual ~Vessel() {}
136 : /// Return the name
137 : std::string getName() const ;
138 : /// Return the label
139 : std::string getLabel() const ;
140 : /// Check that readin was fine
141 : void checkRead();
142 : /// Return a description of the vessel contents
143 : virtual std::string description()=0;
144 : /// Set the start of the buffer
145 : virtual void setBufferStart( unsigned& start );
146 : /// Do something before the loop
147 25848 : virtual void prepare() {}
148 : /// This is replaced in bridges so we can transform the derivatives
149 : virtual MultiValue& transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals );
150 : /// Calculate the part of the vessel that is done in the loop
151 : virtual void calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const = 0;
152 : /// Complete the calculation once the loop is finished
153 : virtual void finish( const std::vector<double>& )=0;
154 : /// Reset the size of the buffers
155 : virtual void resize()=0;
156 : /// Retrieve the forces on the quantities in the vessel
157 : virtual bool applyForce( std::vector<double>& forces )=0;
158 : };
159 :
160 : template<class T>
161 759 : void Vessel::parse(const std::string&key, T&t ) {
162 759 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
163 :
164 : // Now try to read the keyword
165 759 : bool found=Tools::parse(line,key,t); std::string def;
166 1518 : if ( !found && keywords.style(key,"compulsory") ) {
167 1032 : if( keywords.getDefaultValue(key,def) ) {
168 344 : plumed_massert( def.length()!=0 && Tools::convert(def,t), "default value is dubious");
169 : } else {
170 0 : error("keyword " + key + " is comulsory for this vessel");
171 : }
172 : }
173 759 : }
174 :
175 : template<class T>
176 173 : void Vessel::parseVector(const std::string&key,std::vector<T>&t) {
177 : // Check keyword has been registered
178 173 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
179 173 : unsigned size=t.size(); bool skipcheck=false;
180 173 : if(size==0) skipcheck=true;
181 :
182 : // Now try to read the keyword
183 : bool found; std::string def; T val;
184 173 : found=Tools::parseVector(line,key,t);
185 :
186 : // Check vectors size is correct (not if this is atoms or ARG)
187 346 : if( !keywords.style(key,"atoms") && found ) {
188 249 : if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size");
189 : }
190 :
191 : // If it isn't read and it is compulsory see if a default value was specified
192 346 : if ( !found && keywords.style(key,"compulsory") ) {
193 0 : if( keywords.getDefaultValue(key,def) ) {
194 0 : if( def.length()==0 || !Tools::convert(def,val) ) {
195 0 : plumed_merror("weird default value for keyword " + key );
196 : } else {
197 0 : for(unsigned i=0; i<t.size(); ++i) t[i]=val;
198 : }
199 : } else {
200 0 : error("keyword " + key + " is compulsory");
201 : }
202 173 : } else if ( !found ) {
203 1 : t.resize(0);
204 : }
205 173 : }
206 :
207 : inline
208 : int Vessel::getNumericalLabel() const {
209 310 : return numlab;
210 : }
211 :
212 : inline
213 31984 : void Vessel::setBufferStart( unsigned& start ) {
214 31984 : bufstart=start; start+=bufsize;
215 31984 : }
216 :
217 : inline
218 505508 : MultiValue& Vessel::transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals ) {
219 505508 : return myvals;
220 : }
221 :
222 : inline
223 : void Vessel::resizeBuffer( const unsigned& n ) {
224 2920 : bufsize=n;
225 : }
226 :
227 : inline
228 : double Vessel::getTolerance() const {
229 133035 : return action->tolerance;
230 : }
231 :
232 : inline
233 : double Vessel::getNLTolerance() const {
234 : return action->nl_tolerance;
235 : }
236 :
237 : inline
238 : ActionWithVessel* Vessel::getAction() const {
239 4311447 : return action;
240 : }
241 :
242 : inline
243 : unsigned Vessel::getSizeOfBuffer() const {
244 : return bufsize;
245 : }
246 :
247 : }
248 : }
249 : #endif
|