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 601 : 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 26782 : 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 878 : void Vessel::parse(const std::string&key, T&t ) { 158 878 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); 159 : 160 : // Now try to read the keyword 161 878 : bool found=Tools::parse(line,key,t); std::string def; 162 2005 : if ( !found && keywords.style(key,"compulsory") ) { 163 726 : if( keywords.getDefaultValue(key,def) ) { 164 363 : plumed_massert( def.length()!=0 && Tools::convertNoexcept(def,t), "default value is dubious"); 165 : } else { 166 0 : error("keyword " + key + " is comulsory for this vessel"); 167 : } 168 : } 169 878 : } 170 : 171 : template<class T> 172 245 : void Vessel::parseVector(const std::string&key,std::vector<T>&t) { 173 : // Check keyword has been registered 174 245 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered"); 175 245 : unsigned size=t.size(); bool skipcheck=false; 176 245 : if(size==0) skipcheck=true; 177 : 178 : // Now try to read the keyword 179 : bool found; std::string def; T val; 180 245 : found=Tools::parseVector(line,key,t); 181 : 182 : // Check vectors size is correct (not if this is atoms or ARG) 183 490 : if( !keywords.style(key,"atoms") && found ) { 184 237 : 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 261 : if ( !found && keywords.style(key,"compulsory") ) { 189 0 : if( keywords.getDefaultValue(key,def) ) { 190 0 : if( def.length()==0 || !Tools::convertNoexcept(def,val) ) { 191 0 : plumed_merror("weird default value for keyword " + key ); 192 : } else { 193 0 : for(unsigned i=0; i<t.size(); ++i) t[i]=val; 194 : } 195 : } else { 196 0 : error("keyword " + key + " is compulsory"); 197 : } 198 245 : } else if ( !found ) { 199 8 : t.resize(0); 200 : } 201 245 : } 202 : 203 : inline 204 : int Vessel::getNumericalLabel() const { 205 351 : return numlab; 206 : } 207 : 208 : inline 209 32918 : void Vessel::setBufferStart( unsigned& start ) { 210 32918 : bufstart=start; start+=bufsize; 211 32918 : } 212 : 213 : inline 214 508967 : MultiValue& Vessel::transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals ) { 215 508967 : return myvals; 216 : } 217 : 218 : inline 219 : void Vessel::resizeBuffer( const unsigned& n ) { 220 2828 : bufsize=n; 221 0 : } 222 : 223 : inline 224 : double Vessel::getTolerance() const { 225 134170 : return action->tolerance; 226 : } 227 : 228 : inline 229 : double Vessel::getNLTolerance() const { 230 : return action->nl_tolerance; 231 : } 232 : 233 : inline 234 : ActionWithVessel* Vessel::getAction() const { 235 3906993 : return action; 236 : } 237 : 238 : inline 239 : unsigned Vessel::getSizeOfBuffer() const { 240 : return bufsize; 241 : } 242 : 243 : } 244 : } 245 : #endif