All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Grid.cpp
Go to the documentation of this file.
1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2  Copyright (c) 2013 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-code.org for more information.
6 
7  This file is part of plumed, version 2.0.
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 #include <vector>
23 #include <cmath>
24 #include <iostream>
25 #include <sstream>
26 #include <cstdio>
27 #include <cfloat>
28 
29 #include "Grid.h"
30 #include "Tools.h"
31 #include "core/Value.h"
32 #include "File.h"
33 #include "Exception.h"
34 #include "KernelFunctions.h"
35 
36 using namespace std;
37 namespace PLMD{
38 
39 Grid::Grid(const std::string& funcl, std::vector<Value*> args, const vector<std::string> & gmin,
40  const vector<std::string> & gmax, const vector<unsigned> & nbin, bool dospline, bool usederiv, bool doclear){
41 // various checks
42  plumed_massert(args.size()==gmin.size(),"grid dimensions in input do not match number of arguments");
43  plumed_massert(args.size()==nbin.size(),"grid dimensions in input do not match number of arguments");
44  plumed_massert(args.size()==gmax.size(),"grid dimensions in input do not match number of arguments");
45  unsigned dim=gmax.size();
46  std::vector<std::string> names;
47  std::vector<bool> isperiodic;
48  std::vector<string> pmin,pmax;
49  names.resize( dim );
50  isperiodic.resize( dim );
51  pmin.resize( dim );
52  pmax.resize( dim );
53  for(unsigned int i=0;i<dim;++i){
54  names[i]=args[i]->getName();
55  if( args[i]->isPeriodic() ){
56  isperiodic[i]=true;
57  args[i]->getDomain( pmin[i], pmax[i] );
58  } else {
59  isperiodic[i]=false;
60  pmin[i]="0.";
61  pmax[i]="0.";
62  }
63  }
64  // this is a value-independent initializator
65  Init(funcl,names,gmin,gmax,nbin,dospline,usederiv,doclear,isperiodic,pmin,pmax);
66 }
67 
68 Grid::Grid(const std::string& funcl, const std::vector<string> &names, const std::vector<std::string> & gmin,
69  const vector<std::string> & gmax, const std::vector<unsigned> & nbin, bool dospline, bool usederiv, bool doclear, const std::vector<bool> &isperiodic, const std::vector<std::string> &pmin, const std::vector<std::string> &pmax ){
70  // this calls the initializator
71  Init(funcl,names,gmin,gmax,nbin,dospline,usederiv,doclear,isperiodic,pmin,pmax);
72 }
73 
74 void Grid::Init(const std::string& funcl, const std::vector<std::string> &names, const vector<std::string> & gmin,
75  const std::vector<std::string> & gmax, const std::vector<unsigned> & nbin, bool dospline, bool usederiv, bool doclear,
76  const std::vector<bool> &isperiodic, const std::vector<std::string> &pmin, const std::vector<std::string> &pmax ){
77  fmt_="%14.9f";
78 // various checks
79  plumed_massert(names.size()==gmin.size(),"grid dimensions in input do not match number of arguments");
80  plumed_massert(names.size()==nbin.size(),"grid dimensions in input do not match number of arguments");
81  plumed_massert(names.size()==gmax.size(),"grid dimensions in input do not match number of arguments");
82  dimension_=gmax.size();
83  str_min_=gmin; str_max_=gmax;
84  argnames.resize( dimension_ );
85  min_.resize( dimension_ );
86  max_.resize( dimension_ );
87  pbc_.resize( dimension_ );
88  for(unsigned int i=0;i<dimension_;++i){
89  argnames[i]=names[i];
90  if( isperiodic[i] ){
91  pbc_[i]=true;
92  str_min_[i]=pmin[i];
93  str_max_[i]=pmax[i];
94  } else {
95  pbc_[i]=false;
96  }
97  Tools::convert(str_min_[i],min_[i]);
98  Tools::convert(str_max_[i],max_[i]);
99  funcname=funcl;
100  plumed_massert(max_[i]>min_[i],"maximum in grid must be larger than minimum");
101  plumed_massert(nbin[i]>0,"number of grid points must be greater than zero");
102  }
103  nbin_=nbin;
104  dospline_=dospline;
105  usederiv_=usederiv;
106  if(dospline_) plumed_assert(dospline_==usederiv_);
107  maxsize_=1;
108  for(unsigned int i=0;i<dimension_;++i){
109  dx_.push_back( (max_[i]-min_[i])/static_cast<double>( nbin_[i] ) );
110  if( !pbc_[i] ){ max_[i] += dx_[i]; nbin_[i] += 1; }
111  maxsize_*=nbin_[i];
112  }
113  if(doclear) clear();
114 }
115 
116 void Grid::clear(){
117  grid_.resize(maxsize_);
118  if(usederiv_) der_.resize(maxsize_);
119  for(unsigned int i=0;i<maxsize_;++i){
120  grid_[i]=0.0;
121  if(usederiv_){
122  (der_[i]).resize(dimension_);
123  for(unsigned int j=0;j<dimension_;++j) der_[i][j]=0.0;
124  }
125  }
126 }
127 
128 vector<std::string> Grid::getMin() const {
129  return str_min_;
130 }
131 
132 vector<std::string> Grid::getMax() const {
133  return str_max_;
134 }
135 
136 vector<double> Grid::getDx() const {
137  return dx_;
138 }
139 
140 double Grid::getBinVolume() const {
141  double vol=1.;
142  for(unsigned i=0;i<dx_.size();++i) vol*=dx_[i];
143  return vol;
144 }
145 
146 vector<bool> Grid::getIsPeriodic() const {
147  return pbc_;
148 }
149 
150 vector<unsigned> Grid::getNbin() const {
151  return nbin_;
152 }
153 
154 vector<string> Grid::getArgNames() const {
155  return argnames;
156 }
157 
158 
159 unsigned Grid::getSize() const {
160  return maxsize_;
161 }
162 
163 unsigned Grid::getDimension() const {
164  return dimension_;
165 }
166 
167 // we are flattening arrays using a column-major order
168 unsigned Grid::getIndex(const vector<unsigned> & indices) const {
169  plumed_assert(indices.size()==dimension_);
170  for(unsigned int i=0;i<dimension_;i++)
171  if(indices[i]>=nbin_[i]) {
172  std::string is;
173  Tools::convert(i,is);
174  std::string msg="ERROR: the system is looking for a value outside the grid along the " + is;
175  plumed_merror(msg+" index!");
176  }
177  unsigned index=indices[dimension_-1];
178  for(unsigned int i=dimension_-1;i>0;--i){
179  index=index*nbin_[i-1]+indices[i-1];
180  }
181  return index;
182 }
183 
184 unsigned Grid::getIndex(const vector<double> & x) const {
185  plumed_assert(x.size()==dimension_);
186  return getIndex(getIndices(x));
187 }
188 
189 // we are flattening arrays using a column-major order
190 vector<unsigned> Grid::getIndices(unsigned index) const {
191  vector<unsigned> indices(dimension_);
192  unsigned kk=index;
193  indices[0]=(index%nbin_[0]);
194  for(unsigned int i=1;i<dimension_-1;++i){
195  kk=(kk-indices[i-1])/nbin_[i-1];
196  indices[i]=(kk%nbin_[i]);
197  }
198  if(dimension_>=2){
199  indices[dimension_-1]=((kk-indices[dimension_-2])/nbin_[dimension_-2]);
200  }
201  return indices;
202 }
203 
204 vector<unsigned> Grid::getIndices(const vector<double> & x) const {
205  plumed_assert(x.size()==dimension_);
206  vector<unsigned> indices;
207  for(unsigned int i=0;i<dimension_;++i){
208  indices.push_back(unsigned(floor((x[i]-min_[i])/dx_[i])));
209  }
210  return indices;
211 }
212 
213 vector<double> Grid::getPoint(const vector<unsigned> & indices) const {
214  plumed_assert(indices.size()==dimension_);
215  vector<double> x;
216  for(unsigned int i=0;i<dimension_;++i){
217  x.push_back(min_[i]+(double)(indices[i])*dx_[i]);
218  }
219  return x;
220 }
221 
222 vector<double> Grid::getPoint(unsigned index) const {
223  plumed_assert(index<maxsize_);
224  return getPoint(getIndices(index));
225 }
226 
227 vector<double> Grid::getPoint(const vector<double> & x) const {
228  plumed_assert(x.size()==dimension_);
229  return getPoint(getIndices(x));
230 }
231 
232 void Grid::getPoint(unsigned index,std::vector<double> & point) const{
233  plumed_assert(index<maxsize_);
234  getPoint(getIndices(index),point);
235 }
236 
237 void Grid::getPoint(const std::vector<unsigned> & indices,std::vector<double> & point) const{
238  plumed_assert(indices.size()==dimension_);
239  plumed_assert(point.size()==dimension_);
240  for(unsigned int i=0;i<dimension_;++i){
241  point[i]=(min_[i]+(double)(indices[i])*dx_[i]);
242  }
243 }
244 
245 void Grid::getPoint(const std::vector<double> & x,std::vector<double> & point) const{
246  plumed_assert(x.size()==dimension_);
247  getPoint(getIndices(x),point);
248 }
249 
250 
251 vector<unsigned> Grid::getNeighbors
252  (const vector<unsigned> &indices,const vector<unsigned> &nneigh)const{
253  plumed_assert(indices.size()==dimension_ && nneigh.size()==dimension_);
254 
255  vector<unsigned> neighbors;
256  vector<unsigned> small_bin(dimension_);
257 
258  unsigned small_nbin=1;
259  for(unsigned j=0;j<dimension_;++j){
260  small_bin[j]=(2*nneigh[j]+1);
261  small_nbin*=small_bin[j];
262  }
263 
264  vector<unsigned> small_indices(dimension_);
265  vector<unsigned> tmp_indices;
266  for(unsigned index=0;index<small_nbin;++index){
267  tmp_indices.resize(dimension_);
268  unsigned kk=index;
269  small_indices[0]=(index%small_bin[0]);
270  for(unsigned i=1;i<dimension_-1;++i){
271  kk=(kk-small_indices[i-1])/small_bin[i-1];
272  small_indices[i]=(kk%small_bin[i]);
273  }
274  if(dimension_>=2){
275  small_indices[dimension_-1]=((kk-small_indices[dimension_-2])/small_bin[dimension_-2]);
276  }
277  unsigned ll=0;
278  for(unsigned i=0;i<dimension_;++i){
279  int i0=small_indices[i]-nneigh[i]+indices[i];
280  if(!pbc_[i] && i0<0) continue;
281  if(!pbc_[i] && i0>=nbin_[i]) continue;
282  if( pbc_[i] && i0<0) i0=nbin_[i]-(-i0)%nbin_[i];
283  if( pbc_[i] && i0>=nbin_[i]) i0%=nbin_[i];
284  tmp_indices[ll]=((unsigned)i0);
285  ll++;
286  }
287  tmp_indices.resize(ll);
288  if(tmp_indices.size()==dimension_){neighbors.push_back(getIndex(tmp_indices));}
289  }
290  return neighbors;
291 }
292 
293 vector<unsigned> Grid::getNeighbors
294  (const vector<double> & x,const vector<unsigned> & nneigh)const{
295  plumed_assert(x.size()==dimension_ && nneigh.size()==dimension_);
296  return getNeighbors(getIndices(x),nneigh);
297 }
298 
299 vector<unsigned> Grid::getNeighbors
300  (unsigned index,const vector<unsigned> & nneigh)const{
301  plumed_assert(index<maxsize_ && nneigh.size()==dimension_);
302  return getNeighbors(getIndices(index),nneigh);
303 }
304 
305 vector<unsigned> Grid::getSplineNeighbors(const vector<unsigned> & indices)const{
306  plumed_assert(indices.size()==dimension_);
307  vector<unsigned> neighbors;
308  unsigned nneigh=unsigned(pow(2.0,int(dimension_)));
309 
310  for(unsigned int i=0;i<nneigh;++i){
311  unsigned tmp=i;
312  vector<unsigned> nindices;
313  for(unsigned int j=0;j<dimension_;++j){
314  unsigned i0=tmp%2+indices[j];
315  tmp/=2;
316  if(!pbc_[j] && i0==nbin_[j]) continue;
317  if( pbc_[j] && i0==nbin_[j]) i0=0;
318  nindices.push_back(i0);
319  }
320  if(nindices.size()==dimension_) neighbors.push_back(getIndex(nindices));
321  }
322  return neighbors;
323 }
324 
325 void Grid::addKernel( const KernelFunctions& kernel ){
326  plumed_assert( kernel.ndim()==dimension_ );
327  std::vector<unsigned> nneighb=kernel.getSupport( dx_ );
328  std::vector<unsigned> neighbors=getNeighbors( kernel.getCenter(), nneighb );
329  std::vector<double> xx( dimension_ ); std::vector<Value*> vv( dimension_ );
330  std::string str_min, str_max;
331  for(unsigned i=0;i<dimension_;++i){
332  vv[i]=new Value();
333  if( pbc_[i] ){
334  Tools::convert(min_[i],str_min);
335  Tools::convert(max_[i],str_max);
336  vv[i]->setDomain( str_min, str_max );
337  } else {
338  vv[i]->setNotPeriodic();
339  }
340  }
341 
342  double newval; std::vector<double> der( dimension_ );
343  for(unsigned i=0;i<neighbors.size();++i){
344  unsigned ineigh=neighbors[i];
345  getPoint( ineigh, xx );
346  for(unsigned j=0;j<dimension_;++j) vv[j]->set(xx[j]);
347  newval = kernel.evaluate( vv, der, usederiv_ );
348  if( usederiv_ ) addValueAndDerivatives( ineigh, newval, der );
349  else addValue( ineigh, newval );
350  }
351 
352  for(unsigned i=0;i<dimension_;++i) delete vv[i];
353 }
354 
355 double Grid::getValue(unsigned index) const {
356  plumed_assert(index<maxsize_);
357  return grid_[index];
358 }
359 
360 double Grid::getMinValue() const {
361  double minval;
362  minval=DBL_MAX;
363  for(unsigned i=0;i<grid_.size();++i){
364  if(grid_[i]<minval)minval=grid_[i];
365  }
366  return minval;
367 }
368 
369 double Grid::getMaxValue() const {
370  double maxval;
371  maxval=DBL_MIN;
372  for(unsigned i=0;i<grid_.size();++i){
373  if(grid_[i]>maxval)maxval=grid_[i];
374  }
375  return maxval;
376 }
377 
378 
379 
380 
381 double Grid::getValue(const vector<unsigned> & indices) const {
382  return getValue(getIndex(indices));
383 }
384 
385 double Grid::getValue(const vector<double> & x) const {
386  if(!dospline_){
387  return getValue(getIndex(x));
388  } else {
389  vector<double> der(dimension_);
390  return getValueAndDerivatives(x,der);
391  }
392 }
393 
394 double Grid::getValueAndDerivatives
395  (unsigned index, vector<double>& der) const{
396  plumed_assert(index<maxsize_ && usederiv_ && der.size()==dimension_);
397  der=der_[index];
398  return grid_[index];
399 }
400 
401 double Grid::getValueAndDerivatives
402  (const vector<unsigned> & indices, vector<double>& der) const{
403  return getValueAndDerivatives(getIndex(indices),der);
404 }
405 
406 double Grid::getValueAndDerivatives
407 (const vector<double> & x, vector<double>& der) const {
408  plumed_assert(der.size()==dimension_ && usederiv_);
409 
410  if(dospline_){
411  double X,X2,X3,value;
412  vector<double> fd(dimension_);
413  vector<double> C(dimension_);
414  vector<double> D(dimension_);
415  vector<double> dder(dimension_);
416 // reset
417  value=0.0;
418  for(unsigned int i=0;i<dimension_;++i) der[i]=0.0;
419 
420  vector<unsigned> indices=getIndices(x);
421  vector<unsigned> neigh=getSplineNeighbors(indices);
422  vector<double> xfloor=getPoint(x);
423 
424 // loop over neighbors
425  for(unsigned int ipoint=0;ipoint<neigh.size();++ipoint){
426  double grid=getValueAndDerivatives(neigh[ipoint],dder);
427  vector<unsigned> nindices=getIndices(neigh[ipoint]);
428  double ff=1.0;
429 
430  for(unsigned j=0;j<dimension_;++j){
431  int x0=1;
432  if(nindices[j]==indices[j]) x0=0;
433  double dx=getDx()[j];
434  X=fabs((x[j]-xfloor[j])/dx-(double)x0);
435  X2=X*X;
436  X3=X2*X;
437  double yy;
438  if(fabs(grid)<0.0000001) yy=0.0;
439  else yy=-dder[j]/grid;
440  C[j]=(1.0-3.0*X2+2.0*X3) - (x0?-1.0:1.0)*yy*(X-2.0*X2+X3)*dx;
441  D[j]=( -6.0*X +6.0*X2) - (x0?-1.0:1.0)*yy*(1.0-4.0*X +3.0*X2)*dx;
442  D[j]*=(x0?-1.0:1.0)/dx;
443  ff*=C[j];
444  }
445  for(unsigned j=0;j<dimension_;++j){
446  fd[j]=D[j];
447  for(unsigned i=0;i<dimension_;++i) if(i!=j) fd[j]*=C[i];
448  }
449  value+=grid*ff;
450  for(unsigned j=0;j<dimension_;++j) der[j]+=grid*fd[j];
451  }
452  return value;
453  }else{
454  return getValueAndDerivatives(getIndex(x),der);
455  }
456 }
457 
458 void Grid::setValue(unsigned index, double value){
459  plumed_assert(index<maxsize_ && !usederiv_);
460  grid_[index]=value;
461 }
462 
463 void Grid::setValue(const vector<unsigned> & indices, double value){
464  setValue(getIndex(indices),value);
465 }
466 
467 void Grid::setValueAndDerivatives
468  (unsigned index, double value, vector<double>& der){
469  plumed_assert(index<maxsize_ && usederiv_ && der.size()==dimension_);
470  grid_[index]=value;
471  der_[index]=der;
472 }
473 
474 void Grid::setValueAndDerivatives
475  (const vector<unsigned> & indices, double value, vector<double>& der){
476  setValueAndDerivatives(getIndex(indices),value,der);
477 }
478 
479 void Grid::addValue(unsigned index, double value){
480  plumed_assert(index<maxsize_ && !usederiv_);
481  grid_[index]+=value;
482 }
483 
484 void Grid::addValue(const vector<unsigned> & indices, double value){
485  addValue(getIndex(indices),value);
486 }
487 
488 void Grid::addValueAndDerivatives
489  (unsigned index, double value, vector<double>& der){
490  plumed_assert(index<maxsize_ && usederiv_ && der.size()==dimension_);
491  grid_[index]+=value;
492  for(unsigned int i=0;i<dimension_;++i) der_[index][i]+=der[i];
493 }
494 
495 void Grid::addValueAndDerivatives
496  (const vector<unsigned> & indices, double value, vector<double>& der){
497  addValueAndDerivatives(getIndex(indices),value,der);
498 }
499 
500 void Grid::scaleAllValuesAndDerivatives( const double& scalef ){
501  if(usederiv_){
502  for(unsigned i=0;i<grid_.size();++i){
503  grid_[i]*=scalef;
504  for(unsigned j=0;j<dimension_;++j) der_[i][j]*=scalef;
505  }
506  } else {
507  for(unsigned i=0;i<grid_.size();++i) grid_[i]*=scalef;
508  }
509 }
510 
511 void Grid::applyFunctionAllValuesAndDerivatives( double (*func)(double val), double (*funcder)(double valder) ){
512  if(usederiv_){
513  for(unsigned i=0;i<grid_.size();++i){
514  grid_[i]=func(grid_[i]);
515  for(unsigned j=0;j<dimension_;++j) der_[i][j]=funcder(der_[i][j]);
516  }
517  } else {
518  for(unsigned i=0;i<grid_.size();++i) grid_[i]=func(grid_[i]);
519  }
520 }
521 
522 void Grid::writeHeader(OFile& ofile){
523  for(unsigned i=0;i<dimension_;++i){
524  ofile.addConstantField("min_" + argnames[i]);
525  ofile.addConstantField("max_" + argnames[i]);
526  ofile.addConstantField("nbins_" + argnames[i]);
527  ofile.addConstantField("periodic_" + argnames[i]);
528  }
529 }
530 
531 void Grid::writeToFile(OFile& ofile){
532  vector<double> xx(dimension_);
533  vector<double> der(dimension_);
534  double f;
535  writeHeader(ofile);
536  for(unsigned i=0;i<getSize();++i){
537  xx=getPoint(i);
538  if(usederiv_){f=getValueAndDerivatives(i,der);}
539  else{f=getValue(i);}
540  if(i>0 && dimension_>1 && getIndices(i)[dimension_-2]==0) ofile.printf("\n");
541  for(unsigned j=0;j<dimension_;++j){
542  ofile.printField("min_" + argnames[j], str_min_[j] );
543  ofile.printField("max_" + argnames[j], str_max_[j] );
544  ofile.printField("nbins_" + argnames[j], static_cast<int>(nbin_[j]) );
545  if( pbc_[j] ) ofile.printField("periodic_" + argnames[j], "true" );
546  else ofile.printField("periodic_" + argnames[j], "false" );
547  }
548  for(unsigned j=0;j<dimension_;++j){ ofile.fmtField(" "+fmt_); ofile.printField(argnames[j],xx[j]); }
549  ofile.fmtField(" "+fmt_); ofile.printField(funcname,f);
550  if(usederiv_) for(unsigned j=0;j<dimension_;++j){ ofile.fmtField(" "+fmt_); ofile.printField("der_" + argnames[j] ,der[j]); }
551  ofile.printField();
552  }
553 }
554 
555 Grid* Grid::create(const std::string& funcl, std::vector<Value*> args, IFile& ifile,
556  const vector<std::string> & gmin,const vector<std::string> & gmax,
557  const vector<unsigned> & nbin,bool dosparse, bool dospline, bool doder){
558  Grid* grid=Grid::create(funcl,args,ifile,dosparse,dospline,doder);
559  std::vector<unsigned> cbin( grid->getNbin() );
560  std::vector<std::string> cmin( grid->getMin() ), cmax( grid->getMax() );
561  for(unsigned i=0;i<args.size();++i){
562  plumed_massert( cmin[i]==gmin[i], "mismatched grid min" );
563  plumed_massert( cmax[i]==gmax[i], "mismatched grid max" );
564  if( args[i]->isPeriodic() ){
565  plumed_massert( cbin[i]==nbin[i], "mismatched grid nbins" );
566  } else {
567  plumed_massert( (cbin[i]-1)==nbin[i], "mismatched grid nbins");
568  }
569  }
570  return grid;
571 }
572 
573 Grid* Grid::create(const std::string& funcl, std::vector<Value*> args, IFile& ifile, bool dosparse, bool dospline, bool doder)
574 {
575  Grid* grid=NULL;
576  unsigned nvar=args.size(); bool hasder=false; std::string pstring;
577  std::vector<int> gbin1(nvar); std::vector<unsigned> gbin(nvar);
578  std::vector<std::string> labels(nvar),gmin(nvar),gmax(nvar);
579  std::vector<std::string> fieldnames; ifile.scanFieldList( fieldnames );
580  // Retrieve names for fields
581  for(unsigned i=0;i<args.size();++i) labels[i]=args[i]->getName();
582  // And read the stuff from the header
583  plumed_massert( ifile.FieldExist( funcl ) , "no column labelled " + funcl + " in in grid input");
584  for(unsigned i=0;i<args.size();++i){
585  ifile.scanField( "min_" + labels[i], gmin[i]);
586  ifile.scanField( "max_" + labels[i], gmax[i]);
587  ifile.scanField( "periodic_" + labels[i], pstring );
588  ifile.scanField( "nbins_" + labels[i], gbin1[i]);
589  plumed_assert( gbin1[i]>0 );
590  if( args[i]->isPeriodic() ){
591  plumed_massert( pstring=="true", "input value is periodic but grid is not");
592  std::string pmin, pmax;
593  args[i]->getDomain( pmin, pmax ); gbin[i]=gbin1[i];
594  if( pmin!=gmin[i] || pmax!=gmax[i] ) plumed_merror("mismatch between grid boundaries and periods of values");
595  } else {
596  gbin[i]=gbin1[i]-1; // Note header in grid file indicates one more bin that there should be when data is not periodic
597  plumed_massert( pstring=="false", "input value is not periodic but grid is");
598  }
599  hasder=ifile.FieldExist( "der_" + args[i]->getName() );
600  if( doder && !hasder ) plumed_merror("missing derivatives from grid file");
601  for(unsigned j=0;j<fieldnames.size();++j){
602  for(unsigned k=i+1;k<args.size();++k){
603  if( fieldnames[j]==labels[k] ) plumed_merror("arguments in input are not in same order as in grid file");
604  }
605  if( fieldnames[j]==labels[i] ) break;
606  }
607  }
608 
609  if(!dosparse){grid=new Grid(funcl,args,gmin,gmax,gbin,dospline,doder);}
610  else{grid=new SparseGrid(funcl,args,gmin,gmax,gbin,dospline,doder);}
611 
612  vector<double> xx(nvar),dder(nvar);
613  vector<double> dx=grid->getDx();
614  double f,x;
615  while( ifile.scanField(funcl,f) ){
616  for(unsigned i=0;i<nvar;++i){
617  ifile.scanField(labels[i],x); xx[i]=x+dx[i]/2.0;
618  ifile.scanField( "min_" + labels[i], gmin[i]);
619  ifile.scanField( "max_" + labels[i], gmax[i]);
620  ifile.scanField( "nbins_" + labels[i], gbin1[i]);
621  ifile.scanField( "periodic_" + labels[i], pstring );
622  }
623  if(hasder){ for(unsigned i=0;i<nvar;++i){ ifile.scanField( "der_" + args[i]->getName(), dder[i] ); } }
624  unsigned index=grid->getIndex(xx);
625  if(doder){grid->setValueAndDerivatives(index,f,dder);}
626  else{grid->setValue(index,f);}
627  ifile.scanField();
628  }
629  return grid;
630 }
631 
632 // Sparse version of grid with map
633 void SparseGrid::clear(){
634  map_.clear();
635 }
636 
637 unsigned SparseGrid::getSize() const{
638  return map_.size();
639 }
640 
641 unsigned SparseGrid::getMaxSize() const {
642  return maxsize_;
643 }
644 
645 double SparseGrid::getValue(unsigned index)const{
646  plumed_assert(index<maxsize_);
647  double value=0.0;
648  iterator it=map_.find(index);
649  if(it!=map_.end()) value=it->second;
650  return value;
651 }
652 
653 double SparseGrid::getValueAndDerivatives
654  (unsigned index, vector<double>& der)const{
655  plumed_assert(index<maxsize_ && usederiv_ && der.size()==dimension_);
656  double value=0.0;
657  for(unsigned int i=0;i<dimension_;++i) der[i]=0.0;
658  iterator it=map_.find(index);
659  if(it!=map_.end()) value=it->second;
660  iterator_der itder=der_.find(index);
661  if(itder!=der_.end()) der=itder->second;
662  return value;
663 }
664 
665 void SparseGrid::setValue(unsigned index, double value){
666  plumed_assert(index<maxsize_ && !usederiv_);
667  map_[index]=value;
668 }
669 
670 void SparseGrid::setValueAndDerivatives
671  (unsigned index, double value, vector<double>& der){
672  plumed_assert(index<maxsize_ && usederiv_ && der.size()==dimension_);
673  map_[index]=value;
674  der_[index]=der;
675 }
676 
677 void SparseGrid::addValue(unsigned index, double value){
678  plumed_assert(index<maxsize_ && !usederiv_);
679  map_[index]+=value;
680 }
681 
682 void SparseGrid::addValueAndDerivatives
683  (unsigned index, double value, vector<double>& der){
684  plumed_assert(index<maxsize_ && usederiv_ && der.size()==dimension_);
685  map_[index]+=value;
686  der_[index].resize(dimension_);
687  for(unsigned int i=0;i<dimension_;++i) der_[index][i]+=der[i];
688 }
689 
690 void SparseGrid::writeToFile(OFile& ofile){
691  vector<double> xx(dimension_);
692  vector<double> der(dimension_);
693  double f;
694  writeHeader(ofile);
695  ofile.fmtField(" "+fmt_);
696  for(iterator it=map_.begin();it!=map_.end();++it){
697  unsigned i=(*it).first;
698  xx=getPoint(i);
699  if(usederiv_){f=getValueAndDerivatives(i,der);}
700  else{f=getValue(i);}
701  if(i>0 && dimension_>1 && getIndices(i)[dimension_-2]==0) ofile.printf("\n");
702  for(unsigned j=0;j<dimension_;++j){
703  ofile.printField("min_" + argnames[j], str_min_[j] );
704  ofile.printField("max_" + argnames[j], str_max_[j] );
705  ofile.printField("nbins_" + argnames[j], static_cast<int>(nbin_[j]) );
706  if( pbc_[j] ) ofile.printField("periodic_" + argnames[j], "true" );
707  else ofile.printField("periodic_" + argnames[j], "false" );
708  }
709  for(unsigned j=0;j<dimension_;++j) ofile.printField(argnames[j],xx[j]);
710  ofile.printField(funcname, f);
711  if(usederiv_){ for(unsigned j=0;j<dimension_;++j) ofile.printField("der_" + argnames[j],der[j]); }
712  ofile.printField();
713  }
714 }
715 
716 
717 void Grid::projectOnLowDimension(double &val, std::vector<int> &vHigh, WeightBase * ptr2obj ){
718  unsigned i=0;
719  for(i=0;i<vHigh.size();i++){
720  if(vHigh[i]<0){// this bin needs to be integrated out
721  // parallelize here???
722  for(unsigned j=0;j<(getNbin())[i];j++){
723  vHigh[i]=int(j);
724  projectOnLowDimension(val,vHigh,ptr2obj); // recursive function: this is the core of the mechanism
725  vHigh[i]=-1;
726  }
727  return; //
728  }
729  }
730  // when there are no more bin to dig in then retrieve the value
731  if(i==vHigh.size()){
732  //std::cerr<<"POINT: ";
733  //for(unsigned j=0;j<vHigh.size();j++){
734  // std::cerr<<vHigh[j]<<" ";
735  //}
736  std::vector<unsigned> vv(vHigh.size());
737  for(unsigned j=0;j<vHigh.size();j++)vv[j]=unsigned(vHigh[j]);
738  //
739  // this is the real assignment !!!!! (hack this to have bias or other stuff)
740  //
741 
742  // this case: produce fes
743  //val+=exp(beta*getValue(vv)) ;
744  double myv=getValue(vv);
745  val=ptr2obj->projectInnerLoop(val,myv) ;
746  // to be added: bias (same as before without negative sign)
747  //std::cerr<<" VAL: "<<val <<endl;
748  }
749 }
750 
751 Grid Grid::project(const std::vector<std::string> & proj , WeightBase *ptr2obj ){
752  // find extrema only for the projection
753  vector<string> smallMin,smallMax;
754  vector<unsigned> smallBin;
755  vector<unsigned> dimMapping;
756  vector<bool> smallIsPeriodic;
757  vector<string> smallName;
758 
759  // check if the two key methods are there
760  WeightBase* pp = dynamic_cast<WeightBase*>(ptr2obj);
761  if (!pp)plumed_merror("This WeightBase is not complete: you need a projectInnerLoop and projectOuterLoop ");
762 
763  for(unsigned j=0;j<proj.size();j++){
764  for(unsigned i=0;i<getArgNames().size();i++){
765  if(proj[j]==getArgNames()[i]){
766  unsigned offset;
767  // note that at sizetime the non periodic dimension get a bin more
768  if(getIsPeriodic()[i]){offset=0;}else{offset=1;}
769  smallMax.push_back(getMax()[i]);
770  smallMin.push_back(getMin()[i]);
771  smallBin.push_back(getNbin()[i]-offset);
772  smallIsPeriodic.push_back(getIsPeriodic()[i]);
773  dimMapping.push_back(i);
774  smallName.push_back(getArgNames()[i]);
775  break;
776  }
777  }
778  }
779  Grid smallgrid("projection",smallName,smallMin,smallMax,smallBin,false,false,true,smallIsPeriodic,smallMin,smallMax);
780  // check that the two grids are commensurate
781  for(unsigned i=0;i<dimMapping.size();i++){
782  plumed_massert( (smallgrid.getMax())[i] == (getMax())[dimMapping[i]], "the two input grids are not compatible in max" );
783  plumed_massert( (smallgrid.getMin())[i] == (getMin())[dimMapping[i]], "the two input grids are not compatible in min" );
784  plumed_massert( (smallgrid.getNbin())[i]== (getNbin())[dimMapping[i]], "the two input grids are not compatible in bin" );
785  }
786  vector<unsigned> toBeIntegrated;
787  for(unsigned i=0;i<getArgNames().size();i++){
788  bool doappend=true;
789  for(unsigned j=0;j<dimMapping.size();j++){
790  if(dimMapping[j]==i){doappend=false; break;}
791  }
792  if(doappend)toBeIntegrated.push_back(i);
793  }
794  //for(unsigned i=0;i<dimMapping.size();i++ ){
795  // cerr<<"Dimension to preserve "<<dimMapping[i]<<endl;
796  //}
797  //for(unsigned i=0;i<toBeIntegrated.size();i++ ){
798  // cerr<<"Dimension to integrate "<<toBeIntegrated[i]<<endl;
799  //}
800 
801  // loop over all the points in the Grid, find the corresponding fixed index, rotate over all the other ones
802  for(unsigned i=0;i<smallgrid.getSize();i++){
803  std::vector<unsigned> v;
804  v=smallgrid.getIndices(i);
805  std::vector<int> vHigh((getArgNames()).size(),-1);
806  for(unsigned j=0;j<dimMapping.size();j++)vHigh[dimMapping[j]]=int(v[j]);
807  // the vector vhigh now contains at the beginning the index of the low dimension and -1 for the values that need to be integrated
808  double initval=0.;
809  projectOnLowDimension(initval,vHigh, ptr2obj);
810  smallgrid.setValue(i,initval);
811  }
812  // reset to zero just for biasing (this option can be evtl enabled in a future...)
813  //double vmin;vmin=-smallgrid.getMinValue()+1;
814  for(unsigned i=0;i<smallgrid.getSize();i++){
815  // //if(dynamic_cast<BiasWeight*>(ptr2obj)){
816  // // smallgrid.addValue(i,vmin);// go to 1
817  // //}
818  double vv=smallgrid.getValue(i);
819  smallgrid.setValue(i,ptr2obj->projectOuterLoop(vv));
820  // //if(dynamic_cast<BiasWeight*>(ptr2obj)){
821  // // smallgrid.addValue(i,-vmin);// bring back to the value
822  // //}
823  }
824 
825  return smallgrid;
826 }
827 
828 }
bool FieldExist(const std::string &s)
Check if a field exist.
Definition: IFile.cpp:104
virtual double projectInnerLoop(double &input, double &v)=0
std::vector< unsigned > getSupport(const std::vector< double > &dx) const
Get the support.
std::vector< double > getCenter() const
Get the position of the center.
double evaluate(const std::vector< Value * > &pos, std::vector< double > &derivatives, bool usederiv=true) const
Evaluate the kernel function.
A class for holding the value of a function together with its derivatives.
Definition: Value.h:46
virtual void clear()
clear grid
Definition: Grid.cpp:116
OFile & fmtField(const std::string &)
Set the format for writing double precision fields.
Definition: OFile.cpp:135
STL namespace.
std::map< unsigned, std::vector< double > >::const_iterator iterator_der
Definition: Grid.h:201
OFile & addConstantField(const std::string &)
Definition: OFile.cpp:120
std::vector< unsigned > getIndices(unsigned index) const
methods to handle grid indices
Definition: Grid.cpp:190
virtual void setValue(unsigned index, double value)
set grid value
Definition: Grid.cpp:458
unsigned ndim() const
Get the dimensionality of the kernel.
std::map< unsigned, double >::const_iterator iterator
Definition: Grid.h:199
std::vector< double > getDx() const
get bin size
Definition: Grid.cpp:136
virtual double getValue(unsigned index) const
get grid value
Definition: Grid.cpp:355
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
Definition: OFile.cpp:82
virtual unsigned getSize() const
get grid size
Definition: Grid.cpp:159
Class for input files.
Definition: IFile.h:40
IFile & scanField(const std::string &, double &)
Read a double field.
Definition: IFile.cpp:121
Class for output files.
Definition: OFile.h:84
std::vector< std::string > getMax() const
get upper boundary
Definition: Grid.cpp:132
virtual void setValueAndDerivatives(unsigned index, double value, std::vector< double > &der)
set grid value and derivatives
Definition: Grid.cpp:468
OFile & printField(const std::string &, double)
Set the value of a double precision field.
Definition: OFile.cpp:145
unsigned getIndex(const std::vector< unsigned > &indices) const
Definition: Grid.cpp:168
virtual double projectOuterLoop(double &v)=0
std::vector< std::string > getMin() const
get lower boundary
Definition: Grid.cpp:128
std::vector< unsigned > getNbin() const
get number of bins
Definition: Grid.cpp:150
IFile & scanFieldList(std::vector< std::string > &)
Gets the list of all fields.
Definition: IFile.cpp:95