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