Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2012-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 : #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 : [[noreturn]] 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 131 621 : 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 143 26892 : 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> 157 918 : void Vessel::parse(const std::string&key, T&t ) { 158 918 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); 159 : 160 : // Now try to read the keyword 161 918 : bool found=Tools::parse(line,key,t); 162 : std::string def; 163 2105 : if ( !found && keywords.style(key,"compulsory") ) { 164 383 : if( keywords.getDefaultValue(key,def) ) { 165 383 : plumed_massert( def.length()!=0 && Tools::convertNoexcept(def,t), "default value is dubious"); 166 : } else { 167 0 : error("keyword " + key + " is comulsory for this vessel"); 168 : } 169 : } 170 918 : } 171 : 172 : template<class T> 173 245 : void Vessel::parseVector(const std::string&key,std::vector<T>&t) { 174 : // Check keyword has been registered 175 245 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered"); 176 245 : unsigned size=t.size(); 177 : bool skipcheck=false; 178 245 : if(size==0) { 179 : skipcheck=true; 180 : } 181 : 182 : // Now try to read the keyword 183 : bool found; 184 : std::string def; 185 : T val; 186 245 : found=Tools::parseVector(line,key,t); 187 : 188 : // Check vectors size is correct (not if this is atoms or ARG) 189 490 : if( !keywords.style(key,"atoms") && found ) { 190 237 : if( !skipcheck && t.size()!=size ) { 191 0 : error("vector read in for keyword " + key + " has the wrong size"); 192 : } 193 : } 194 : 195 : // If it isn't read and it is compulsory see if a default value was specified 196 261 : if ( !found && keywords.style(key,"compulsory") ) { 197 0 : if( keywords.getDefaultValue(key,def) ) { 198 0 : if( def.length()==0 || !Tools::convertNoexcept(def,val) ) { 199 0 : plumed_merror("weird default value for keyword " + key ); 200 : } else { 201 0 : for(unsigned i=0; i<t.size(); ++i) { 202 0 : t[i]=val; 203 : } 204 : } 205 : } else { 206 0 : error("keyword " + key + " is compulsory"); 207 : } 208 245 : } else if ( !found ) { 209 8 : t.resize(0); 210 : } 211 245 : } 212 : 213 : inline 214 : int Vessel::getNumericalLabel() const { 215 371 : return numlab; 216 : } 217 : 218 : inline 219 33028 : void Vessel::setBufferStart( unsigned& start ) { 220 33028 : bufstart=start; 221 33028 : start+=bufsize; 222 33028 : } 223 : 224 : inline 225 557711 : MultiValue& Vessel::transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals ) { 226 557711 : return myvals; 227 : } 228 : 229 : inline 230 : void Vessel::resizeBuffer( const unsigned& n ) { 231 2848 : bufsize=n; 232 0 : } 233 : 234 : inline 235 : double Vessel::getTolerance() const { 236 182818 : return action->tolerance; 237 : } 238 : 239 : inline 240 : double Vessel::getNLTolerance() const { 241 : return action->nl_tolerance; 242 : } 243 : 244 : inline 245 : ActionWithVessel* Vessel::getAction() const { 246 3960207 : return action; 247 : } 248 : 249 : inline 250 : unsigned Vessel::getSizeOfBuffer() const { 251 : return bufsize; 252 : } 253 : 254 : } 255 : } 256 : #endif