All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
FlexibleBin.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 "FlexibleBin.h"
23 #include "ActionWithArguments.h"
24 #include <cmath>
25 #include <iostream>
26 #include <vector>
27 #include "tools/Matrix.h"
28 
29 using namespace std;
30 namespace PLMD{
31 
32 
33 FlexibleBin::FlexibleBin(int type, ActionWithArguments *paction, double const &d , vector<double> &smin, vector<double> &smax):type(type),paction(paction),sigma(d),sigmamin(smin),sigmamax(smax){
34  // initialize the averages and the variance matrices
35  if(type==diffusion){
36  unsigned ncv=paction->getNumberOfArguments();
37  vector<double> average(ncv*(ncv+1)/2);
38  vector<double> variance(ncv*(ncv+1)/2);
39  }
40  paction->log<<" Limits for sigmas using adaptive hills: \n";
41  for(unsigned i=0;i<paction->getNumberOfArguments();++i){
42  paction->log<<" CV "<<paction->getPntrToArgument(i)->getName()<<":\n";
43  if(sigmamin[i]>0.){
44  limitmin.push_back(true);
45  paction->log<<" Min "<<sigmamin[i];
46  sigmamin[i]*=sigmamin[i]; // this is because the matrix which is calculated is the sigmasquared
47  }else{
48  limitmin.push_back(false);
49  paction->log<<" Min No ";
50  }
51  if(sigmamax[i]>0.){
52  limitmax.push_back(true);
53  paction->log<<" Max "<<sigmamax[i];
54  sigmamax[i]*=sigmamax[i];
55  }else{
56  limitmax.push_back(false);
57  paction->log<<" Max No ";
58  }
59  paction->log<<" \n";
60  }
61 
62 }
63 /// Update the flexible bin
64 /// in case of diffusion based: update at every step
65 /// in case of gradient based: update only when you add the hill
66 void FlexibleBin::update(bool nowAddAHill){
67  unsigned ncv=paction->getNumberOfArguments();
68  unsigned dimension=ncv*(ncv+1)/2;
69  // this is done all the times from scratch. It is not an accumulator
70  unsigned k=0;
71  unsigned i,j;
72  vector<double> cv;
73  vector<double> delta;
74  // if you use this below then the decay is in time units
75  //double decay=paction->getTimeStep()/sigma;
76  // to be consistent with the rest of the program: everything is better to be in timesteps
77  double decay=1./sigma;
78  // here update the flexible bin according to the needs
79  switch (type){
80  // This should be called every time
81  case diffusion:
82  //
83  // THE AVERAGE VALUE
84  //
85  // beware: the pbc
86  delta.resize(ncv);
87  for(i=0;i<ncv;i++)cv.push_back(paction->getArgument(i));
88  if(average.size()==0){ // initial time: just set the initial vector
89  average.resize(ncv);
90  for(i=0;i<ncv;i++)average[i]=cv[i];
91  }else{ // accumulate
92  for(i=0;i<ncv;i++){
93  delta[i]=paction->difference(i,average[i],cv[i]);
94  average[i]+=decay*delta[i];
95  average[i]=paction->bringBackInPbc(i,average[i]); // equation 8 of "Metadynamics with adaptive Gaussians"
96  }
97 
98  }
99  //
100  // THE VARIANCE
101  //
102  if(variance.size()==0){
103  variance.resize(dimension,0.); // nonredundant members dimension=ncv*(ncv+1)/2;
104  }else{
105  k=0;
106  for(i=0;i<ncv;i++){
107  for(j=i;j<ncv;j++){ // upper diagonal loop
108  variance[k]+=decay*(delta[i]*delta[j]-variance[k]);
109  k++;
110  }
111  }
112  }
113  break;
114  case geometry:
115  //
116  //this calculates in variance the \nabla CV_i \dot \nabla CV_j
117  //
118  variance.resize(dimension);
119  //cerr<< "Doing geometry "<<endl;
120  // now the signal for retrieving the gradients should be already given by checkNeedsGradients.
121  // here just do the projections
122  // note that the call checkNeedsGradients() in BiasMetaD takes care of switching on the call to gradients
123  if (nowAddAHill){// geometry is sync with hill deposition
124  //cerr<< "add a hill "<<endl;
125  k=0;
126  for(unsigned i=0;i<ncv;i++){
127  for(unsigned j=i;j<ncv;j++){
128  // eq 12 of "Metadynamics with adaptive Gaussians"
130  k++;
131  }
132  };
133  };
134  break;
135  default:
136  cerr<< "This flexible bin is not recognized "<<endl;
137  exit(1) ;
138  }
139 
140 }
141 
142 vector<double> FlexibleBin::getMatrix() const{
143  return variance;
144 }
145 
146 ///
147 /// Calculate the matrix of (dcv_i/dx)*(dcv_j/dx)^-1
148 /// that is needed for the metrics in metadynamics
149 ///
150 ///
151 vector<double> FlexibleBin::getInverseMatrix() const{
152  unsigned ncv=paction->getNumberOfArguments();
153  Matrix<double> matrix(ncv,ncv);
154  unsigned i,j,k;
155  k=0;
156  //paction->log<<"------------ GET INVERSE MATRIX ---------------\n";
157  // place the matrix in a complete matrix for compatibility
158  for (i=0;i<ncv;i++){
159  for (j=i;j<ncv;j++){
160  matrix(j,i)=matrix(i,j)=variance[k];
161  k++;
162  }
163  }
164 // paction->log<<"MATRIX\n";
165 // matrixOut(paction->log,matrix);
166 #define NEWFLEX
167 #ifdef NEWFLEX
168  // diagonalize to impose boundaries (only if boundaries are set)
169  Matrix<double> eigenvecs(ncv,ncv);
170  vector<double> eigenvals(ncv);
171 
172  //eigenvecs: first is eigenvec number, second is eigenvec component
173  if(diagMat( matrix , eigenvals , eigenvecs )!=0){plumed_merror("diagonalization in FlexibleBin failed! This matrix is weird\n");};
174 
175 // paction->log<<"EIGENVECS \n";
176 // matrixOut(paction->log,eigenvecs);
177 
178  //for (i=0;i<ncv;i++){//loop on the dimension
179  // for (j=0;j<ncv;j++){//loop on the dimension
180  // eigenvecs[i][j]=0.;
181  // if(i==j)eigenvecs[i][j]=1.;
182  // }
183  //}
184 
185  for (i=0;i<ncv;i++){//loop on the dimension
186  if( limitmax[i] ){
187  //limit every component that is larger
188  for (j=0;j<ncv;j++){//loop on components
189  if(pow(eigenvals[j]*eigenvecs[j][i],2)>pow(sigmamax[i],2) ){
190  eigenvals[j]=sqrt(pow(sigmamax[i]/(eigenvecs[j][i]),2))*copysign(1.,eigenvals[j]);
191  }
192  }
193  }
194  }
195  for (i=0;i<ncv;i++){//loop on the dimension
196  // find the largest one: if it is smaller than min then rescale
197  if( limitmin[i] ){
198  unsigned imax;
199  double fmax=-1.e10;
200  for (j=0;j<ncv;j++){//loop on components
201  double fact=pow(eigenvals[j]*eigenvecs[j][i],2);
202  if(fact>fmax){
203  fmax=fact;imax=j;
204  }
205  }
206  if(fmax<pow(sigmamin[i],2) ){
207  eigenvals[imax]=sqrt(pow(sigmamin[i]/(eigenvecs[imax][i]),2))*copysign(1.,eigenvals[imax]);
208  }
209 
210  }
211 
212  }
213 
214  // normalize eigenvecs
215  Matrix<double> newinvmatrix(ncv,ncv);
216  for (i=0;i<ncv;i++){
217  for (j=0;j<ncv;j++){
218  newinvmatrix[j][i]=eigenvecs[j][i]/eigenvals[j];
219  }
220  }
221 
222  vector<double> uppervec(ncv*(ncv+1)/2);
223  k=0;
224  for (i=0;i<ncv;i++){
225  for (j=i;j<ncv;j++){
226  double scal=0;
227  for(unsigned l=0;l<ncv;++l){
228  scal+=eigenvecs[l][i]*newinvmatrix[l][j];
229  }
230  uppervec[k]=scal; k++;
231  }
232  }
233 #else
234  // get the inverted matrix
235  Matrix<double> invmatrix(ncv,ncv);
236  Invert(matrix,invmatrix);
237  vector<double> uppervec(ncv*(ncv+1)/2);
238  // upper diagonal of the inverted matrix (that is symmetric)
239  k=0;
240  for (i=0;i<ncv;i++){
241  for (j=i;j<ncv;j++){
242  uppervec[k]=invmatrix(i,j);
243  //paction->log<<"VV "<<i<<" "<<j<<" "<<uppervec[k]<<"\n";
244  k++;
245  }
246  }
247  //paction->log<<"------------ END GET INVERSE MATRIX ---------------\n";
248 #endif
249 
250  return uppervec;
251 }
252 
253 }
ActionWithArguments * paction
Definition: FlexibleBin.h:35
const std::string & getName() const
Get the name of the quantity.
Definition: Value.h:196
Log & log
Reference to the log stream.
Definition: Action.h:93
std::vector< double > variance
Definition: FlexibleBin.h:38
std::vector< double > getMatrix() const
std::vector< double > sigmamin
Definition: FlexibleBin.h:42
int Invert(const Matrix< T > &A, Matrix< double > &inverse)
Definition: Matrix.h:246
double difference(int, double, double) const
Takes the difference taking into account pbc for arg i.
std::vector< double > average
Definition: FlexibleBin.h:40
STL namespace.
Value * getPntrToArgument(const unsigned n)
Return a pointer to specific argument.
This is used to create PLMD::Action objects that take the output from some other Action as input...
std::vector< bool > limitmax
Definition: FlexibleBin.h:44
double bringBackInPbc(int i, double d1) const
Takes one value and brings it back into the pbc of argument i.
VectorGeneric< n > delta(const VectorGeneric< n > &v1, const VectorGeneric< n > &v2)
Definition: Vector.h:262
double getProjection(unsigned i, unsigned j) const
Get the scalar product between the gradients of two variables.
std::vector< bool > limitmin
Definition: FlexibleBin.h:45
std::vector< double > sigmamax
Definition: FlexibleBin.h:43
int diagMat(const Matrix< T > &A, std::vector< double > &eigenvals, Matrix< double > &eigenvecs)
Definition: Matrix.h:203
double getArgument(const unsigned n) const
Returns the value of an argument.
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...
Definition: FlexibleBin.cpp:66
const int type
Definition: FlexibleBin.h:33
unsigned getNumberOfArguments() const
Returns the number of arguments.