1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 Copyright (c) 2011-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_tools_Grid_h 23 #define __PLUMED_tools_Grid_h 24 25 #include <vector> 26 #include <string> 27 #include <map> 28 #include <cmath> 29 #include <memory> 30 31 namespace PLMD { 32 33 34 // simple function to enable various weighting 35 36 class WeightBase { 37 public: 38 virtual double projectInnerLoop(double &input, double &v)=0; 39 virtual double projectOuterLoop(double &v)=0; ~WeightBase()40 virtual ~WeightBase() {} 41 }; 42 43 class BiasWeight:public WeightBase { 44 public: 45 double beta,invbeta; BiasWeight(double v)46 explicit BiasWeight(double v) {beta=v; invbeta=1./beta;} projectInnerLoop(double & input,double & v)47 double projectInnerLoop(double &input, double &v) override {return input+exp(beta*v);} projectOuterLoop(double & v)48 double projectOuterLoop(double &v) override {return -invbeta*std::log(v);} 49 }; 50 51 class ProbWeight:public WeightBase { 52 public: 53 double beta,invbeta; ProbWeight(double v)54 explicit ProbWeight(double v) {beta=v; invbeta=1./beta;} projectInnerLoop(double & input,double & v)55 double projectInnerLoop(double &input, double &v) override {return input+v;} projectOuterLoop(double & v)56 double projectOuterLoop(double &v) override {return -invbeta*std::log(v);} 57 }; 58 59 60 61 62 63 64 class Value; 65 class IFile; 66 class OFile; 67 class KernelFunctions; 68 class Communicator; 69 70 /// \ingroup TOOLBOX 71 class GridBase 72 { 73 public: 74 // we use a size_t here 75 // should be 8 bytes on all 64-bit machines 76 // and more portable than "unsigned long long" 77 typedef size_t index_t; 78 // to restore old implementation (unsigned) use the following instead: 79 // typedef unsigned index_t; 80 /// Maximum dimension (exaggerated value). 81 /// Can be used to replace local std::vectors with std::arrays (allocated on stack). 82 static constexpr size_t maxdim=64; 83 protected: 84 std::string funcname; 85 std::vector<std::string> argnames; 86 std::vector<std::string> str_min_, str_max_; 87 std::vector<double> min_,max_,dx_; 88 std::vector<unsigned> nbin_; 89 std::vector<bool> pbc_; 90 index_t maxsize_; 91 unsigned dimension_; 92 bool dospline_, usederiv_; 93 std::string fmt_; // format for output 94 /// get "neighbors" for spline 95 void getSplineNeighbors(const std::vector<unsigned> & indices, std::vector<index_t>& neigh, unsigned& nneigh )const; 96 // std::vector<index_t> getSplineNeighbors(const std::vector<unsigned> & indices)const; 97 98 99 public: 100 /// this constructor here is Value-aware 101 GridBase(const std::string& funcl, const std::vector<Value*> & args, const std::vector<std::string> & gmin, 102 const std::vector<std::string> & gmax, const std::vector<unsigned> & nbin, bool dospline, 103 bool usederiv); 104 /// this constructor here is not Value-aware 105 GridBase(const std::string& funcl, const std::vector<std::string> &names, const std::vector<std::string> & gmin, 106 const std::vector<std::string> & gmax, const std::vector<unsigned> & nbin, bool dospline, 107 bool usederiv, const std::vector<bool> &isperiodic, const std::vector<std::string> &pmin, 108 const std::vector<std::string> &pmax ); 109 /// this is the real initializator 110 void Init(const std::string & funcl, const std::vector<std::string> &names, const std::vector<std::string> & gmin, 111 const std::vector<std::string> & gmax, const std::vector<unsigned> & nbin, bool dospline, bool usederiv, 112 const std::vector<bool> &isperiodic, const std::vector<std::string> &pmin, const std::vector<std::string> &pmax); 113 /// get lower boundary 114 std::vector<std::string> getMin() const; 115 /// get upper boundary 116 std::vector<std::string> getMax() const; 117 /// get bin size 118 std::vector<double> getDx() const; 119 double getDx(index_t j) const ; 120 /// get bin volume 121 double getBinVolume() const; 122 /// get number of bins 123 std::vector<unsigned> getNbin() const; 124 /// get if periodic 125 std::vector<bool> getIsPeriodic() const; 126 /// get grid dimension 127 unsigned getDimension() const; 128 /// get argument names of this grid 129 std::vector<std::string> getArgNames() const; 130 /// get if the grid has derivatives hasDerivatives()131 bool hasDerivatives() const {return usederiv_;} 132 133 /// methods to handle grid indices 134 void getIndices(index_t index, std::vector<unsigned>& rindex) const; 135 void getIndices(const std::vector<double> & x, std::vector<unsigned>& rindex) const; 136 std::vector<unsigned> getIndices(index_t index) const; 137 std::vector<unsigned> getIndices(const std::vector<double> & x) const; 138 index_t getIndex(const std::vector<unsigned> & indices) const; 139 index_t getIndex(const std::vector<double> & x) const; 140 std::vector<double> getPoint(index_t index) const; 141 std::vector<double> getPoint(const std::vector<unsigned> & indices) const; 142 std::vector<double> getPoint(const std::vector<double> & x) const; 143 /// faster versions relying on preallocated vectors 144 void getPoint(index_t index,std::vector<double> & point) const; 145 void getPoint(const std::vector<unsigned> & indices,std::vector<double> & point) const; 146 void getPoint(const std::vector<double> & x,std::vector<double> & point) const; 147 148 /// get neighbors 149 std::vector<index_t> getNeighbors(index_t index,const std::vector<unsigned> & neigh) const; 150 std::vector<index_t> getNeighbors(const std::vector<unsigned> & indices,const std::vector<unsigned> & neigh) const; 151 std::vector<index_t> getNeighbors(const std::vector<double> & x,const std::vector<unsigned> & neigh) const; 152 /// get nearest neighbors (those separated by exactly one lattice unit) 153 std::vector<index_t> getNearestNeighbors(const index_t index) const; 154 std::vector<index_t> getNearestNeighbors(const std::vector<unsigned> &indices) const; 155 156 /// write header for grid file 157 void writeHeader(OFile& file); 158 159 /// read grid from file 160 static std::unique_ptr<GridBase> create(const std::string&,const std::vector<Value*>&,IFile&,bool,bool,bool); 161 /// read grid from file and check boundaries are what is expected from input 162 static std::unique_ptr<GridBase> create(const std::string&,const std::vector<Value*>&, IFile&, 163 const std::vector<std::string>&,const std::vector<std::string>&, 164 const std::vector<unsigned>&,bool,bool,bool); 165 /// get grid size 166 virtual index_t getSize() const=0; 167 /// get grid value 168 virtual double getValue(index_t index) const=0; 169 double getValue(const std::vector<unsigned> & indices) const; 170 double getValue(const std::vector<double> & x) const; 171 /// get grid value and derivatives 172 virtual double getValueAndDerivatives(index_t index, std::vector<double>& der) const=0; 173 double getValueAndDerivatives(const std::vector<unsigned> & indices, std::vector<double>& der) const; 174 double getValueAndDerivatives(const std::vector<double> & x, std::vector<double>& der) const; 175 176 /// set grid value 177 virtual void setValue(index_t index, double value)=0; 178 void setValue(const std::vector<unsigned> & indices, double value); 179 /// set grid value and derivatives 180 virtual void setValueAndDerivatives(index_t index, double value, std::vector<double>& der)=0; 181 void setValueAndDerivatives(const std::vector<unsigned> & indices, double value, std::vector<double>& der); 182 /// add to grid value 183 virtual void addValue(index_t index, double value)=0; 184 void addValue(const std::vector<unsigned> & indices, double value); 185 /// add to grid value and derivatives 186 virtual void addValueAndDerivatives(index_t index, double value, std::vector<double>& der)=0; 187 void addValueAndDerivatives(const std::vector<unsigned> & indices, double value, std::vector<double>& der); 188 /// add a kernel function to the grid 189 void addKernel( const KernelFunctions& kernel ); 190 191 /// get minimum value 192 virtual double getMinValue() const = 0; 193 /// get maximum value 194 virtual double getMaxValue() const = 0; 195 196 /// dump grid on file 197 virtual void writeToFile(OFile&)=0; 198 /// dump grid to gaussian cube file 199 void writeCubeFile(OFile&, const double& lunit); 200 ~GridBase()201 virtual ~GridBase() {} 202 203 /// set output format setOutputFmt(const std::string & ss)204 void setOutputFmt(const std::string & ss) {fmt_=ss;} 205 /// reset output format to the default %14.9f format resetToDefaultOutputFmt()206 void resetToDefaultOutputFmt() {fmt_="%14.9f";} 207 /// 208 /// Find the maximum over paths of the minimum value of the gridded function along the paths 209 /// for all paths of neighboring grid lattice points from a source point to a sink point. 210 double findMaximalPathMinimum(const std::vector<double> &source, const std::vector<double> &sink); 211 }; 212 213 class Grid : public GridBase 214 { 215 std::vector<double> grid_; 216 std::vector<double> der_; 217 double contour_location=0.0; 218 public: Grid(const std::string & funcl,const std::vector<Value * > & args,const std::vector<std::string> & gmin,const std::vector<std::string> & gmax,const std::vector<unsigned> & nbin,bool dospline,bool usederiv)219 Grid(const std::string& funcl, const std::vector<Value*> & args, const std::vector<std::string> & gmin, 220 const std::vector<std::string> & gmax, 221 const std::vector<unsigned> & nbin, bool dospline, bool usederiv): 222 GridBase(funcl,args,gmin,gmax,nbin,dospline,usederiv) 223 { 224 grid_.assign(maxsize_,0.0); 225 if(usederiv_) der_.assign(maxsize_*dimension_,0.0); 226 } 227 /// this constructor here is not Value-aware Grid(const std::string & funcl,const std::vector<std::string> & names,const std::vector<std::string> & gmin,const std::vector<std::string> & gmax,const std::vector<unsigned> & nbin,bool dospline,bool usederiv,const std::vector<bool> & isperiodic,const std::vector<std::string> & pmin,const std::vector<std::string> & pmax)228 Grid(const std::string& funcl, const std::vector<std::string> &names, const std::vector<std::string> & gmin, 229 const std::vector<std::string> & gmax, const std::vector<unsigned> & nbin, bool dospline, 230 bool usederiv, const std::vector<bool> &isperiodic, const std::vector<std::string> &pmin, 231 const std::vector<std::string> &pmax ): 232 GridBase(funcl,names,gmin,gmax,nbin,dospline,usederiv,isperiodic,pmin,pmax) 233 { 234 grid_.assign(maxsize_,0.0); 235 if(usederiv_) der_.assign(maxsize_*dimension_,0.0); 236 } 237 index_t getSize() const override; 238 /// this is to access to Grid:: version of these methods (allowing overloading of virtual methods) 239 using GridBase::getValue; 240 using GridBase::getValueAndDerivatives; 241 using GridBase::setValue; 242 using GridBase::setValueAndDerivatives; 243 using GridBase::addValue; 244 using GridBase::addValueAndDerivatives; 245 /// get grid value 246 double getValue(index_t index) const override; 247 /// get grid value and derivatives 248 double getValueAndDerivatives(index_t index, std::vector<double>& der) const override; 249 250 /// set grid value 251 void setValue(index_t index, double value) override; 252 /// set grid value and derivatives 253 void setValueAndDerivatives(index_t index, double value, std::vector<double>& der) override; 254 /// add to grid value 255 void addValue(index_t index, double value) override; 256 /// add to grid value and derivatives 257 void addValueAndDerivatives(index_t index, double value, std::vector<double>& der) override; 258 259 /// get minimum value 260 double getMinValue() const override; 261 /// get maximum value 262 double getMaxValue() const override; 263 /// Scale all grid values and derivatives by a constant factor 264 void scaleAllValuesAndDerivatives( const double& scalef ); 265 /// Takes the scalef times the logarithm of all grid values and derivatives 266 void logAllValuesAndDerivatives( const double& scalef ); 267 /// dump grid on file 268 void writeToFile(OFile&) override; 269 270 /// Set the minimum value of the grid to zero and translates accordingly 271 void setMinToZero(); 272 /// apply function: takes pointer to function that accepts a double and apply 273 void applyFunctionAllValuesAndDerivatives( double (*func)(double val), double (*funcder)(double valder) ); 274 /// Get the difference from the contour 275 double getDifferenceFromContour(const std::vector<double> & x, std::vector<double>& der) const ; 276 /// Find a set of points on a contour in the function 277 void findSetOfPointsOnContour(const double& target, const std::vector<bool>& nosearch, unsigned& npoints, std::vector<std::vector<double> >& points ); 278 /// Since this method returns a concrete Grid, it should be here and not in GridBase - GB 279 /// project a high dimensional grid onto a low dimensional one: this should be changed at some time 280 /// to enable many types of weighting 281 Grid project( const std::vector<std::string> & proj, WeightBase *ptr2obj ); 282 void projectOnLowDimension(double &val, std::vector<int> &varHigh, WeightBase* ptr2obj ); 283 void mpiSumValuesAndDerivatives( Communicator& comm ); 284 /// Integrate the function calculated on the grid 285 double integrate( std::vector<unsigned>& npoints ); 286 void clear(); 287 }; 288 289 290 class SparseGrid : public GridBase 291 { 292 293 std::map<index_t,double> map_; 294 std::map< index_t,std::vector<double> > der_; 295 296 public: SparseGrid(const std::string & funcl,const std::vector<Value * > & args,const std::vector<std::string> & gmin,const std::vector<std::string> & gmax,const std::vector<unsigned> & nbin,bool dospline,bool usederiv)297 SparseGrid(const std::string& funcl, const std::vector<Value*> & args, const std::vector<std::string> & gmin, 298 const std::vector<std::string> & gmax, 299 const std::vector<unsigned> & nbin, bool dospline, bool usederiv): 300 GridBase(funcl,args,gmin,gmax,nbin,dospline,usederiv) {} 301 302 index_t getSize() const override; 303 index_t getMaxSize() const; 304 305 /// this is to access to Grid:: version of these methods (allowing overloading of virtual methods) 306 using GridBase::getValue; 307 using GridBase::getValueAndDerivatives; 308 using GridBase::setValue; 309 using GridBase::setValueAndDerivatives; 310 using GridBase::addValue; 311 using GridBase::addValueAndDerivatives; 312 313 /// get grid value 314 double getValue(index_t index) const override; 315 /// get grid value and derivatives 316 double getValueAndDerivatives(index_t index, std::vector<double>& der) const override; 317 318 /// set grid value 319 void setValue(index_t index, double value) override; 320 /// set grid value and derivatives 321 void setValueAndDerivatives(index_t index, double value, std::vector<double>& der) override; 322 /// add to grid value 323 void addValue(index_t index, double value) override; 324 /// add to grid value and derivatives 325 void addValueAndDerivatives(index_t index, double value, std::vector<double>& der) override; 326 327 /// get minimum value 328 double getMinValue() const override; 329 /// get maximum value 330 double getMaxValue() const override; 331 /// dump grid on file 332 void writeToFile(OFile&) override; 333 ~SparseGrid()334 virtual ~SparseGrid() {} 335 }; 336 } 337 338 #endif 339