24 #include "tools/Grid.h"
25 #include "core/PlumedMain.h"
26 #include "core/Atoms.h"
27 #include "tools/Exception.h"
28 #include "core/FlexibleBin.h"
29 #include "tools/Matrix.h"
30 #include "tools/Random.h"
33 #include "tools/File.h"
37 #define DP2CUTOFF 6.25
209 Gaussian(
const vector<double> & center,
const vector<double> & sigma,
double height,
bool multivariate ):
210 center(center),sigma(sigma),height(height),multivariate(multivariate),invsigma(sigma){
211 for(
unsigned i=0;i<invsigma.size();++i)abs(invsigma[i])>1.e-20?invsigma[i]=1.0/invsigma[i]:0.;
245 void readGaussians(
IFile*);
246 bool readChunkOfGaussians(
IFile *ifile,
unsigned n);
249 double getHeight(
const vector<double>&);
250 double getBiasAndDerivatives(
const vector<double>&,
double* der=NULL);
251 double evaluateGaussian(
const vector<double>&,
const Gaussian&,
double* der=NULL);
252 void finiteDifferenceGaussian(
const vector<double>&,
const Gaussian&);
253 vector<unsigned> getGaussianSupport(
const Gaussian&);
254 bool scanOneHill(
IFile *ifile, vector<Value> &v, vector<double> ¢er, vector<double> &sigma,
double &height,
bool &multivariate );
262 static void registerKeywords(
Keywords& keys);
266 PLUMED_REGISTER_ACTION(MetaD,
"METAD")
269 Bias::registerKeywords(keys);
270 componentsAreNotOptional(keys);
271 keys.addOutputComponent(
"bias",
"default",
"the instantaneous value of the bias potential");
273 keys.add(
"compulsory",
"SIGMA",
"the widths of the Gaussian hills");
274 keys.add(
"compulsory",
"HEIGHT",
"the heights of the Gaussian hills");
275 keys.add(
"compulsory",
"PACE",
"the frequency for hill addition");
276 keys.add(
"compulsory",
"FILE",
"HILLS",
"a file in which the list of added hills is stored");
277 keys.add(
"optional",
"FMT",
"specify format for HILLS files (useful for decrease the number of digits in regtests)");
278 keys.add(
"optional",
"BIASFACTOR",
"use well tempered metadynamics and use this biasfactor. Please note you must also specify temp");
279 keys.add(
"optional",
"TEMP",
"the system temperature - this is only needed if you are doing well-tempered metadynamics");
280 keys.add(
"optional",
"GRID_MIN",
"the lower bounds for the grid");
281 keys.add(
"optional",
"GRID_MAX",
"the upper bounds for the grid");
282 keys.add(
"optional",
"GRID_BIN",
"the number of bins for the grid");
283 keys.addFlag(
"GRID_SPARSE",
false,
"use a sparse grid to store hills");
284 keys.addFlag(
"GRID_NOSPLINE",
false,
"don't use spline interpolation with grids");
285 keys.add(
"optional",
"GRID_WSTRIDE",
"write the grid to a file every N steps");
286 keys.add(
"optional",
"GRID_WFILE",
"the file on which to write the grid");
287 keys.addFlag(
"STORE_GRIDS",
false,
"store all the grid files the calculation generates. They will be deleted if this keyword is not present");
288 keys.add(
"optional",
"ADAPTIVE",
"use a geometric (=GEOM) or diffusion (=DIFF) based hills width scheme. Sigma is one number that has distance units or timestep dimensions");
289 keys.add(
"optional",
"WALKERS_ID",
"walker id");
290 keys.add(
"optional",
"WALKERS_N",
"number of walkers");
291 keys.add(
"optional",
"WALKERS_DIR",
"shared directory with the hills files from all the walkers");
292 keys.add(
"optional",
"WALKERS_RSTRIDE",
"stride for reading hills files");
293 keys.add(
"optional",
"INTERVAL",
"monodimensional lower and upper limits, outside the limits the system will not feel the biasing force.");
294 keys.add(
"optional",
"GRID_RFILE",
"a grid file from which the bias should be read at the initial step of the simulation");
295 keys.add(
"optional",
"SIGMA_MAX",
"the upper bounds for the sigmas (in CV units) when using adaptive hills. Negative number means no bounds ");
296 keys.add(
"optional",
"SIGMA_MIN",
"the lower bounds for the sigmas (in CV units) when using adaptive hills. Negative number means no bounds ");
300 if(flexbin)
delete flexbin;
301 if(BiasGrid_)
delete BiasGrid_;
303 if(wgridstride_>0) gridfile_.close();
306 for(
int i=0;i<mw_n_;++i){
307 if(ifiles[i]->isOpen()) ifiles[i]->close();
315 BiasGrid_(NULL),ExtGrid_(NULL), wgridstride_(0), grid_(false), hasextgrid_(false),
317 height0_(0.0), biasf_(1.0), temp_(0.0),
318 stride_(0), welltemp_(false),
323 mw_n_(1), mw_dir_(
"./"), mw_id_(0), mw_rstride_(1),
325 uppI_(-1), lowI_(-1), doInt_(false),
329 string adaptiveoption;
330 adaptiveoption=
"NONE";
331 parse(
"ADAPTIVE",adaptiveoption);
332 if (adaptiveoption==
"GEOM"){
333 log.
printf(
" Uses Geometry-based hills width: sigma must be in distance units and only one sigma is needed\n");
335 }
else if (adaptiveoption==
"DIFF"){
336 log.
printf(
" Uses Diffusion-based hills width: sigma must be in timesteps and only one sigma is needed\n");
338 }
else if (adaptiveoption==
"NONE"){
341 error(
"I do not know this type of adaptive scheme");
354 error(
"If you choose ADAPTIVE you need only one sigma according to your choice of type (GEOM/DIFF)");
359 plumed_merror(
"In case of adaptive hills with diffusion, the sigma must be an integer which is the number of timesteps\n");
375 if(
height0_<=0.0 )
error(
"error cannot add zero height or negative height hills");
377 if(
stride_<=0 )
error(
"frequency for hill addition is nonsensical");
378 string hillsfname=
"HILLS";
379 parse(
"FILE",hillsfname);
381 if(
biasf_<1.0 )
error(
"well tempered bias factor is nonsensical");
384 if(
temp_==0.0)
error(
"if you are doing well tempered metadynamics you must specify the temperature using TEMP");
398 if( gmin.size()!=gmax.size() || gmin.size()!=gbin.size() )
error(
"GRID MIN was specified without either GRID_MAX or GRID_BIN");
399 bool sparsegrid=
false;
403 bool spline=!nospline;
404 if(gbin.size()>0){
grid_=
true;}
409 if(
wgridstride_==0 )
error(
"frequency with which to output grid not specified use GRID_WSTRIDE");
421 if(
mw_n_<=
mw_id_)
error(
"walker ID should be a numerical value less than the total number of walkers");
426 vector<double> tmpI(2);
428 if(tmpI.size()!=2&&tmpI.size()!=0)
error(
"both a lower and an upper limits must be provided with INTERVAL");
429 else if(tmpI.size()==2) {
433 if(
uppI_<
lowI_)
error(
"The Upper limit must be greater than the Lower limit!");
445 log.
printf(
" Gaussian file %s\n",hillsfname.c_str());
450 for(
unsigned i=0;i<gmin.size();++i)
log.
printf(
" %s",gmin[i].c_str() );
453 for(
unsigned i=0;i<gmax.size();++i)
log.
printf(
" %s",gmax[i].c_str() );
456 for(
unsigned i=0;i<gbin.size();++i)
log.
printf(
" %d",gbin[i]);
458 if(spline){
log.
printf(
" Grid uses spline interpolation\n");}
459 if(sparsegrid){
log.
printf(
" Grid uses sparse grid\n");}
481 std::string funcl=
getLabel() +
".bias";
487 if(gmin[i]!=actualmin[i])
log<<
" WARNING: GRID_MIN["<<i<<
"] has been adjusted to "<<actualmin[i]<<
" to fit periodicity\n";
488 if(gmax[i]!=actualmax[i])
log<<
" WARNING: GRID_MAX["<<i<<
"] has been adjusted to "<<actualmax[i]<<
" to fit periodicity\n";
502 std::string funcl=
getLabel() +
".bias";
513 for(
int i=0;i<
mw_n_;++i){
516 stringstream out; out << i;
517 fname =
mw_dir_+
"/"+hillsfname+
"."+out.str();
546 log<<
" Bibliography "<<
plumed.cite(
"Laio and Parrinello, PNAS 99, 12562 (2002)");
548 "Barducci, Bussi, and Parrinello, Phys. Rev. Lett. 100, 020603 (2008)");
550 "Raiteri, Laio, Gervasio, Micheletti, and Parrinello, J. Phys. Chem. B 110, 3533 (2006)");
552 "Branduardi, Bussi, and Parrinello, J. Chem. Theory Comput. 8, 2247 (2012)");
554 "Baftizadeh, Cossio, Pietrucci, and Laio, Curr. Phys. Chem. 2, 79 (2012)");
562 vector<double> center(ncv);
563 vector<double> sigma(ncv);
566 bool multivariate=
false;
568 std::vector<Value> tmpvalues;
571 while(
scanOneHill(ifile,tmpvalues,center,sigma,height,multivariate)){;
576 log.
printf(
" %d Gaussians read\n",nhills);
582 vector<double> center(ncv);
583 vector<double> sigma(ncv);
586 bool multivariate=
false;
587 std::vector<Value> tmpvalues;
590 while(
scanOneHill(ifile,tmpvalues,center,sigma,height,multivariate)){;
594 log.
printf(
" %u Gaussians read\n",nhills);
599 log.
printf(
" %u Gaussians read\n",nhills);
606 for(
unsigned i=0;i<ncv;++i){
613 for(
unsigned i=0;i<ncv;i++){
614 for(
unsigned j=i;j<ncv;j++){
615 mymatrix(i,j)=mymatrix(j,i)=hill.
sigma[k];
621 Invert(mymatrix,invmatrix);
623 for(
unsigned i=0;i<ncv;i++){
624 for(
unsigned j=i;j<ncv;j++){
625 invmatrix(i,j)=invmatrix(j,i);
633 for (
unsigned i=0;i<ncv;i++){
634 for (
unsigned j=0;j<ncv-i;j++){
640 for(
unsigned i=0;i<ncv;++i)
643 double height=hill.
height;
657 vector<double> der(ncv);
658 vector<double> xx(ncv);
660 for(
unsigned i=0;i<neighbors.size();++i){
661 unsigned ineigh=neighbors[i];
662 for(
unsigned j=0;j<ncv;++j){der[j]=0.0;}
670 vector<double> allder(ncv*neighbors.size(),0.0);
671 vector<double> allbias(neighbors.size(),0.0);
672 for(
unsigned i=rank;i<neighbors.size();i+=
stride){
673 unsigned ineigh=neighbors[i];
677 comm.
Sum(&allbias[0],allbias.size());
678 comm.
Sum(&allder[0],allder.size());
679 for(
unsigned i=0;i<neighbors.size();++i){
680 unsigned ineigh=neighbors[i];
681 for(
unsigned j=0;j<ncv;++j){der[j]=allder[ncv*i+j];}
696 vector<unsigned> nneigh;
703 for(
unsigned i=0;i<ncv;i++){
704 for(
unsigned j=i;j<ncv;j++){
705 mymatrix(i,j)=mymatrix(j,i)=hill.
sigma[k];
718 vector<double> myautoval(ncv);
719 diagMat(myinv,myautoval,myautovec);
720 double maxautoval;maxautoval=0.;
721 unsigned ind_maxautoval;ind_maxautoval=ncv;
722 for (
unsigned i=0;i<ncv;i++){
723 if(myautoval[i]>maxautoval){maxautoval=myautoval[i];ind_maxautoval=i;}
725 for (
unsigned i=0;i<ncv;i++){
726 double cutoff=sqrt(2.0*
DP2CUTOFF)*abs(sqrt(maxautoval)*myautovec(i,ind_maxautoval));
728 nneigh.push_back( static_cast<unsigned>(ceil(cutoff/
BiasGrid_->
getDx()[i])) );
733 nneigh.push_back( static_cast<unsigned>(ceil(cutoff/
BiasGrid_->
getDx()[i])) );
775 (
const vector<double>& cv,
const Gaussian& hill,
double* der)
782 const double *pcv=NULL;
784 if(cv.size()>0) pcv=&cv[0];
786 plumed_assert(cv.size()==1);
789 if(cv[0]<lowI_) tmpcv[0]=lowI_;
790 if(cv[0]>uppI_) tmpcv[0]=uppI_;
794 unsigned ncv=cv.size();
797 for(
unsigned i=0;i<ncv;i++){
798 for(
unsigned j=i;j<ncv;j++){
799 mymatrix(i,j)=mymatrix(j,i)=hill.
sigma[k];
804 for(
unsigned i=0;i<cv.size();++i){
805 double dp_i=difference(i,hill.
center[i],pcv[i]);
807 for(
unsigned j=i;j<cv.size();++j){
809 dp2+=dp_i*dp_i*mymatrix(i,j)*0.5;
811 double dp_j=difference(j,hill.
center[j],pcv[j]);
812 dp2+=dp_i*dp_j*mymatrix(i,j) ;
817 bias=hill.
height*exp(-dp2);
819 for(
unsigned i=0;i<cv.size();++i){
822 for(
unsigned j=0;j<cv.size();++j){
823 tmp+= dp_[j]*mymatrix(i,j)*bias;
830 for(
unsigned i=0;i<cv.size();++i){
837 bias=hill.
height*exp(-dp2);
839 for(
unsigned i=0;i<cv.size();++i){der[i]+=-bias*dp_[i]*hill.
invsigma[i];}
844 if((cv[0]<lowI_ || cv[0]>uppI_) && der )
for(
unsigned i=0;i<cv.size();++i)der[i]=0;
867 vector<double> cv(ncv);
870 double* der=
new double[ncv];
871 for(
unsigned i=0;i<ncv;++i){der[i]=0.0;}
876 for(
unsigned i=0;i<ncv;++i){
877 const double f=-der[i];
886 vector<double> thissigma;
893 for(
unsigned i=0;i<cv.size();++i){cv[i]=
getArgument(i);}
938 for(
int i=0;i<
mw_n_;++i){
942 if(!(
ifiles[i]->isOpen())){
961 log<<
"--------- finiteDifferenceGaussian: size "<<cv.size() <<
"------------\n";
964 vector<double> oldder(cv.size());
965 vector<double> der(cv.size());
966 vector<double> mycv(cv.size());
971 for(
unsigned i=0;i<cv.size();i++)log<<
"CV "<<i<<
" V "<<mycv[i]<<
"\n";
972 for(
unsigned i=0;i<cv.size();i++)mycv[i]+=1.e-2*2*(random.
RandU01()-0.5);
973 for(
unsigned i=0;i<cv.size();i++)log<<
"NENEWWCV "<<i<<
" V "<<mycv[i]<<
"\n";
974 double oldbias=evaluateGaussian(mycv,hill,&oldder[0]);
975 for (
unsigned i=0;i<mycv.size();i++){
978 double newbias=evaluateGaussian(mycv,hill,&der[0]);
980 log<<
" ANAL "<<oldder[i]<<
" NUM "<<(newbias-oldbias)/delta<<
" DIFF "<<(oldder[i]-(newbias-oldbias)/
delta)<<
"\n";
983 log<<
"--------- END finiteDifferenceGaussian ------------\n";
987 bool MetaD::scanOneHill(
IFile *ifile, vector<Value> &tmpvalues, vector<double> ¢er, vector<double> &sigma,
double &height ,
bool &multivariate ){
991 unsigned ncv; ncv=tmpvalues.size();
992 for(
unsigned i=0;i<ncv;++i){
995 error(
"in hills file periodicity for variable " + tmpvalues[i].
getName() +
" does not match periodicity in input");
996 }
else if( tmpvalues[i].isPeriodic() ){
997 std::string imin, imax; tmpvalues[i].getDomain( imin, imax );
999 if( imin!=rmin || imax!=rmax ){
1000 error(
"in hills file periodicity for variable " + tmpvalues[i].
getName() +
" does not match periodicity in input");
1003 center[i]=tmpvalues[i].get();
1008 if(sss==
"true") multivariate=
true;
1009 else if(sss==
"false") multivariate=
false;
1010 else plumed_merror(
"cannot parse multivariate = "+ sss);
1012 sigma.resize(ncv*(ncv+1)/2);
1015 for (
unsigned i=0;i<ncv;i++){
1016 for (
unsigned j=0;j<ncv-i;j++){
1018 upper(j,j+i)=lower(j+i,j);
1027 mult(lower,upper,mymult);
1031 Invert(mymult,invmatrix);
1036 for (
unsigned i=0;i<ncv;i++){
1037 for (
unsigned j=i;j<ncv;j++){
1038 sigma[k]=invmatrix(i,j);
1043 for(
unsigned i=0;i<ncv;++i){
bool FieldExist(const std::string &s)
Check if a field exist.
void parseFlag(const std::string &key, bool &t)
Parse one keyword as boolean flag.
Log & log
Reference to the log stream.
OFile & rewind()
Rewind a file.
int Invert(const Matrix< T > &A, Matrix< double > &inverse)
void componentIsNotPeriodic(const std::string &name)
Set your value component to have no periodicity.
A class for holding the value of a function together with its derivatives.
void cholesky(const Matrix< T > &A, Matrix< T > &B)
void error(const std::string &msg) const
Crash calculation and print documentation.
virtual double getValueAndDerivatives(unsigned index, std::vector< double > &der) const
get grid value and derivatives
unsigned getDimension() const
get grid dimension
const std::string & getLabel() const
Returns the label.
FileBase & link(FILE *)
Link to an already open filed.
double getTimeStep() const
Return the timestep.
OFile & fmtField(const std::string &)
Set the format for writing double precision fields.
void checkRead()
Check if Action was properly read.
Value * getPntrToArgument(const unsigned n)
Return a pointer to specific argument.
void addComponent(const std::string &name)
Add a value with a name like label.name.
void setHeavyFlush()
Set heavyFlush flag.
OFile & addConstantField(const std::string &)
void set(double)
Set the value of the function.
void getDomain(std::string &, std::string &) const
Get the domain of the quantity.
void parse(const std::string &key, T &t)
Parse one keyword as generic type.
This class holds the keywords and their documentation.
FileBase & flush()
Flushes the file to disk.
int Get_rank() const
Obtain the rank of the present process.
IFile & open(const std::string &name)
Opens the file.
This class is used to bring the relevant information to the Action constructor.
std::vector< double > getDx() const
get bin size
virtual double getValue(unsigned index) const
get grid value
std::vector< Value * > & getArguments()
Returns an array of pointers to the arguments.
void mult(const Matrix< T > &A, const Matrix< T > &B, Matrix< T > &C)
OFile & link(OFile &)
Allows linking this OFile to another one.
virtual void addValueAndDerivatives(unsigned index, double value, std::vector< double > &der)
add to grid value and derivatives
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
void close()
Closes the file Should be used only for explicitely opened files.
const std::string & getName() const
Returns the name.
bool getExchangeStep() const
Check if we are on an exchange step.
void parseVector(const std::string &key, std::vector< T > &t)
Parse one keyword as std::vector.
VectorGeneric< n > delta(const VectorGeneric< n > &v1, const VectorGeneric< n > &v2)
void setOutputForce(int i, double g)
int diagMat(const Matrix< T > &A, std::vector< double > &eigenvals, Matrix< double > &eigenvecs)
double getArgument(const unsigned n) const
Returns the value of an argument.
virtual void writeToFile(OFile &)
dump grid on file
IFile & scanField(const std::string &, double &)
Read a double field.
long int getStep() const
Return the present timestep.
bool FileExist(const std::string &path)
Check if the file exists.
std::vector< std::string > getMax() const
get upper boundary
OFile & printField(const std::string &, double)
Set the value of a double precision field.
This is the abstract base class to use for implementing new simulation biases, within it there is inf...
bool isPeriodic() const
Check if the value is periodic.
std::vector< std::string > getMin() const
get lower boundary
std::vector< unsigned > getNbin() const
get number of bins
#define PLUMED_BIAS_INIT(ao)
OFile & clearFields()
Resets the list of fields.
std::vector< double > getPoint(unsigned index) const
Value * getPntrToComponent(int i)
Return a pointer to the component by index.
std::vector< double > getInverseMatrix() const
Calculate the matrix of (dcv_i/dx)*(dcv_j/dx)^-1 that is needed for the metrics in metadynamics...
void update(bool nowAddAHill)
update the average (always for diffusion) or calculate the geom covariance ( only when do_when_zero i...
int Get_size() const
Obtain the number of processes.
std::vector< unsigned > getNeighbors(unsigned index, const std::vector< unsigned > &neigh) const
get neighbors
unsigned getNumberOfArguments() const
Returns the number of arguments.
OFile & open(const std::string &name)
Opens the file using automatic append/backup.
void Sum(T *, int)
Wrapper for MPI_Allreduce with MPI_SUM.
OFile & setupPrintValue(Value *val)
Used to setup printing of values.
static Grid * create(const std::string &, std::vector< Value * >, IFile &, bool, bool, bool)
read grid from file
std::vector< bool > getIsPeriodic() const
get if periodic