Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2012-2018 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 822 : 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 : /// Set the size of the data buffer
122 : void resizeBuffer( const unsigned& n );
123 : public:
124 : /// Reference to the log on which to output details
125 : Log& log;
126 : /// Reserve any keywords for this particular vessel
127 : static void registerKeywords( Keywords& keys );
128 : /// Convert the name to the label of the component
129 : static std::string transformName( const std::string& name );
130 : /// The constructor
131 : explicit Vessel( const VesselOptions& da );
132 : /// Virtual destructor needed for proper inheritance
133 468 : virtual ~Vessel() {}
134 : /// Return the name
135 : std::string getName() const ;
136 : /// Return the label
137 : std::string getLabel() const ;
138 : /// Check that readin was fine
139 : void checkRead();
140 : /// Return a description of the vessel contents
141 : virtual std::string description()=0;
142 : /// Set the start of the buffer
143 : virtual void setBufferStart( unsigned& start );
144 : /// Do something before the loop
145 20657 : virtual void prepare() {}
146 : /// This is replaced in bridges so we can transform the derivatives
147 : virtual MultiValue& transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals );
148 : /// Calculate the part of the vessel that is done in the loop
149 : virtual void calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const = 0;
150 : /// Complete the calculation once the loop is finished
151 : virtual void finish( const std::vector<double>& )=0;
152 : /// Reset the size of the buffers
153 : virtual void resize()=0;
154 : /// Retrieve the forces on the quantities in the vessel
155 : virtual bool applyForce( std::vector<double>& forces )=0;
156 : };
157 :
158 : template<class T>
159 645 : void Vessel::parse(const std::string&key, T&t ) {
160 645 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
161 :
162 : // Now try to read the keyword
163 645 : bool found=Tools::parse(line,key,t); std::string def;
164 645 : if ( !found && keywords.style(key,"compulsory") ) {
165 285 : if( keywords.getDefaultValue(key,def) ) {
166 285 : plumed_massert( def.length()!=0 && Tools::convert(def,t), "default value is dubious");
167 : } else {
168 0 : error("keyword " + key + " is comulsory for this vessel");
169 : }
170 645 : }
171 645 : }
172 :
173 : template<class T>
174 134 : void Vessel::parseVector(const std::string&key,std::vector<T>&t) {
175 : // Check keyword has been registered
176 134 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
177 134 : unsigned size=t.size(); bool skipcheck=false;
178 134 : if(size==0) skipcheck=true;
179 :
180 : // Now try to read the keyword
181 242 : bool found; std::string def; T val;
182 134 : found=Tools::parseVector(line,key,t);
183 :
184 : // Check vectors size is correct (not if this is atoms or ARG)
185 134 : if( !keywords.style(key,"atoms") && found ) {
186 133 : if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size");
187 : }
188 :
189 : // If it isn't read and it is compulsory see if a default value was specified
190 134 : if ( !found && keywords.style(key,"compulsory") ) {
191 0 : if( keywords.getDefaultValue(key,def) ) {
192 0 : if( def.length()==0 || !Tools::convert(def,val) ) {
193 0 : plumed_merror("weird default value for keyword " + key );
194 : } else {
195 0 : for(unsigned i=0; i<t.size(); ++i) t[i]=val;
196 : }
197 : } else {
198 0 : error("keyword " + key + " is compulsory");
199 : }
200 134 : } else if ( !found ) {
201 1 : t.resize(0);
202 134 : }
203 134 : }
204 :
205 : inline
206 286 : int Vessel::getNumericalLabel() const {
207 286 : return numlab;
208 : }
209 :
210 : inline
211 26789 : void Vessel::setBufferStart( unsigned& start ) {
212 26789 : bufstart=start; start+=bufsize;
213 26789 : }
214 :
215 : inline
216 408850 : MultiValue& Vessel::transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals ) {
217 408850 : return myvals;
218 : }
219 :
220 : inline
221 2477 : void Vessel::resizeBuffer( const unsigned& n ) {
222 2477 : bufsize=n;
223 2477 : }
224 :
225 : inline
226 132564 : double Vessel::getTolerance() const {
227 132564 : return action->tolerance;
228 : }
229 :
230 : inline
231 : double Vessel::getNLTolerance() const {
232 : return action->nl_tolerance;
233 : }
234 :
235 : inline
236 6695375 : ActionWithVessel* Vessel::getAction() const {
237 6695375 : return action;
238 : }
239 :
240 : }
241 : }
242 : #endif
|