Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2015-2019 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 : #include "Bias.h"
23 : #include "ActionRegister.h"
24 : #include "core/ActionSet.h"
25 : #include "tools/Grid.h"
26 : #include "core/PlumedMain.h"
27 : #include "core/Atoms.h"
28 : #include "tools/Exception.h"
29 : #include "core/FlexibleBin.h"
30 : #include "tools/Matrix.h"
31 : #include "tools/Random.h"
32 : #include <string>
33 : #include <cstring>
34 : #include "tools/File.h"
35 : #include <iostream>
36 : #include <limits>
37 : #include <ctime>
38 :
39 : #define DP2CUTOFF 6.25
40 :
41 : using namespace std;
42 :
43 :
44 : namespace PLMD {
45 : namespace bias {
46 :
47 : //+PLUMEDOC BIAS PBMETAD
48 : /*
49 : Used to performed Parallel Bias MetaDynamics.
50 :
51 : This action activate Parallel Bias MetaDynamics (PBMetaD) \cite pbmetad, a version of MetaDynamics \cite metad in which
52 : multiple low-dimensional bias potentials are applied in parallel.
53 : In the current implementation, these have the form of mono-dimensional MetaDynamics bias
54 : potentials:
55 :
56 : \f[
57 : {V(s_1,t), ..., V(s_N,t)}
58 : \f]
59 :
60 : where:
61 :
62 : \f[
63 : V(s_i,t) = \sum_{ k \tau < t} W_i(k \tau)
64 : \exp\left(
65 : - \frac{(s_i-s_i^{(0)}(k \tau))^2}{2\sigma_i^2}
66 : \right).
67 : \f]
68 :
69 : To ensure the convergence of each mono-dimensional bias potential to the corresponding free energy,
70 : at each deposition step the Gaussian heights are multiplied by the so-called conditional term:
71 :
72 : \f[
73 : W_i(k \tau)=W_0 \frac{\exp\left(
74 : - \frac{V(s_i,k \tau)}{k_B T}
75 : \right)}{\sum_{i=1}^N
76 : \exp\left(
77 : - \frac{V(s_i,k \tau)}{k_B T}
78 : \right)}
79 : \f]
80 :
81 : where \f$W_0\f$ is the initial Gaussian height.
82 :
83 : The PBMetaD bias potential is defined by:
84 :
85 : \f[
86 : V_{PB}(\vec{s},t) = -k_B T \log{\sum_{i=1}^N
87 : \exp\left(
88 : - \frac{V(s_i,t)}{k_B T}
89 : \right)}.
90 : \f]
91 :
92 :
93 : Information on the Gaussian functions that build each bias potential are printed to
94 : multiple HILLS files, which
95 : are used both to restart the calculation and to reconstruct the mono-dimensional
96 : free energies as a function of the corresponding CVs.
97 : These can be reconstructed using the \ref sum_hills utility because the final bias is given
98 : by:
99 :
100 : \f[
101 : V(s_i) = -F(s_i)
102 : \f]
103 :
104 : Currently, only a subset of the \ref METAD options are available in PBMetaD.
105 :
106 : The bias potentials can be stored on a grid to increase performances of long PBMetaD simulations.
107 : You should
108 : provide either the number of bins for every collective variable (GRID_BIN) or
109 : the desired grid spacing (GRID_SPACING). In case you provide both PLUMED will use
110 : the most conservative choice (highest number of bins) for each dimension.
111 : In case you do not provide any information about bin size (neither GRID_BIN nor GRID_SPACING)
112 : and if Gaussian width is fixed PLUMED will use 1/5 of the Gaussian width as grid spacing.
113 : This default choice should be reasonable for most applications.
114 :
115 : Another option that is available is well-tempered metadynamics \cite Barducci:2008. In this
116 : variant of PBMetaD the heights of the Gaussian hills are rescaled at each step by the
117 : additional well-tempered metadynamics term.
118 : This ensures that each bias converges more smoothly. It should be noted that, in the case of well-tempered metadynamics, in
119 : the output printed the Gaussian height is re-scaled using the bias factor.
120 : Also notice that with well-tempered metadynamics the HILLS files do not contain the bias,
121 : but the negative of the free-energy estimate. This choice has the advantage that
122 : one can restart a simulation using a different value for the \f$\Delta T\f$. The applied bias will be scaled accordingly.
123 :
124 : Note that you can use here also the flexible gaussian approach \cite Branduardi:2012dl
125 : in which you can adapt the gaussian to the extent of Cartesian space covered by a variable or
126 : to the space in collective variable covered in a given time. In this case the width of the deposited
127 : gaussian potential is denoted by one value only that is a Cartesian space (ADAPTIVE=GEOM) or a time
128 : (ADAPTIVE=DIFF). Note that a specific integration technique for the deposited gaussians
129 : should be used in this case. Check the documentation for utility sum_hills.
130 :
131 : With the keyword INTERVAL one changes the metadynamics algorithm setting the bias force equal to zero
132 : outside boundary \cite baftizadeh2012protein. If, for example, metadynamics is performed on a CV s and one is interested only
133 : to the free energy for s > sw, the history dependent potential is still updated according to the above
134 : equations but the metadynamics force is set to zero for s < sw. Notice that Gaussians are added also
135 : if s < sw, as the tails of these Gaussians influence VG in the relevant region s > sw. In this way, the
136 : force on the system in the region s > sw comes from both metadynamics and the force field, in the region
137 : s < sw only from the latter. This approach allows obtaining a history-dependent bias potential VG that
138 : fluctuates around a stable estimator, equal to the negative of the free energy far enough from the
139 : boundaries. Note that:
140 : - It works only for one-dimensional biases;
141 : - It works both with and without GRID;
142 : - The interval limit sw in a region where the free energy derivative is not large;
143 : - If in the region outside the limit sw the system has a free energy minimum, the INTERVAL keyword should
144 : be used together with a \ref UPPER_WALLS or \ref LOWER_WALLS at sw.
145 :
146 : Multiple walkers \cite multiplewalkers can also be used. See below the examples.
147 :
148 : \par Examples
149 :
150 : The following input is for PBMetaD calculation using as
151 : collective variables the distance between atoms 3 and 5
152 : and the distance between atoms 2 and 4. The value of the CVs and
153 : the PBMetaD bias potential are written to the COLVAR file every 100 steps.
154 : \plumedfile
155 : DISTANCE ATOMS=3,5 LABEL=d1
156 : DISTANCE ATOMS=2,4 LABEL=d2
157 : PBMETAD ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 PACE=500 LABEL=pb FILE=HILLS_d1,HILLS_d2
158 : PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR
159 : \endplumedfile
160 : (See also \ref DISTANCE and \ref PRINT).
161 :
162 : \par
163 : If you use well-tempered metadynamics, you should specify a single biasfactor and initial
164 : Gaussian height.
165 : \plumedfile
166 : DISTANCE ATOMS=3,5 LABEL=d1
167 : DISTANCE ATOMS=2,4 LABEL=d2
168 : PBMETAD ...
169 : ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3
170 : PACE=500 BIASFACTOR=8 LABEL=pb
171 : FILE=HILLS_d1,HILLS_d2
172 : ... PBMETAD
173 : PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR
174 : \endplumedfile
175 :
176 : \par
177 : The following input enables the MPI version of multiple-walkers.
178 : \plumedfile
179 : DISTANCE ATOMS=3,5 LABEL=d1
180 : DISTANCE ATOMS=2,4 LABEL=d2
181 : PBMETAD ...
182 : ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3
183 : PACE=500 BIASFACTOR=8 LABEL=pb
184 : FILE=HILLS_d1,HILLS_d2
185 : WALKERS_MPI
186 : ... PBMETAD
187 : PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR
188 : \endplumedfile
189 :
190 : \par
191 : The disk version of multiple-walkers can be
192 : enabled by setting the number of walker used, the id of the
193 : current walker which interprets the input file, the directory where the
194 : hills containing files resides, and the frequency to read the other walkers.
195 : Here is an example
196 : \plumedfile
197 : DISTANCE ATOMS=3,5 LABEL=d1
198 : DISTANCE ATOMS=2,4 LABEL=d2
199 : PBMETAD ...
200 : ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3
201 : PACE=500 BIASFACTOR=8 LABEL=pb
202 : FILE=HILLS_d1,HILLS_d2
203 : WALKERS_N=10
204 : WALKERS_ID=3
205 : WALKERS_DIR=../
206 : WALKERS_RSTRIDE=100
207 : ... PBMETAD
208 : PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR
209 : \endplumedfile
210 : where WALKERS_N is the total number of walkers, WALKERS_ID is the
211 : id of the present walker (starting from 0 ) and the WALKERS_DIR is the directory
212 : where all the walkers are located. WALKERS_RSTRIDE is the number of step between
213 : one update and the other.
214 :
215 : */
216 : //+ENDPLUMEDOC
217 :
218 : class PBMetaD : public Bias {
219 :
220 : private:
221 10686 : struct Gaussian {
222 : vector<double> center;
223 : vector<double> sigma;
224 : double height;
225 : bool multivariate; // this is required to discriminate the one dimensional case
226 : vector<double> invsigma;
227 896 : Gaussian(const vector<double> & center,const vector<double> & sigma, double height, bool multivariate):
228 896 : center(center),sigma(sigma),height(height),multivariate(multivariate),invsigma(sigma) {
229 : // to avoid troubles from zero element in flexible hills
230 5376 : for(unsigned i=0; i<invsigma.size(); ++i) abs(invsigma[i])>1.e-20?invsigma[i]=1.0/invsigma[i]:0.;
231 896 : }
232 : };
233 : vector<double> sigma0_;
234 : vector<double> sigma0min_;
235 : vector<double> sigma0max_;
236 : vector< vector<Gaussian> > hills_;
237 : vector<OFile*> hillsOfiles_;
238 : vector<OFile*> gridfiles_;
239 : vector<Grid*> BiasGrids_;
240 : bool grid_;
241 : double height0_;
242 : double biasf_;
243 : double kbt_;
244 : int stride_;
245 : int wgridstride_;
246 : bool welltemp_;
247 : int mw_n_;
248 : string mw_dir_;
249 : int mw_id_;
250 : int mw_rstride_;
251 : bool walkers_mpi;
252 : unsigned mpi_nw_;
253 : unsigned mpi_id_;
254 : vector<string> hillsfname;
255 : vector<IFile*> ifiles;
256 : vector<string> ifilesnames;
257 : vector<double> uppI_;
258 : vector<double> lowI_;
259 : vector<bool> doInt_;
260 : int adaptive_;
261 : vector<FlexibleBin> flexbin;
262 : bool isFirstStep;
263 : // variable for selector
264 : string selector_;
265 : bool do_select_;
266 : unsigned select_value_;
267 : unsigned current_value_;
268 :
269 : void readGaussians(unsigned iarg, IFile*);
270 : bool readChunkOfGaussians(unsigned iarg, IFile *ifile, unsigned n);
271 : void writeGaussian(unsigned iarg, const Gaussian&, OFile*);
272 : void addGaussian(unsigned iarg, const Gaussian&);
273 : double getBiasAndDerivatives(unsigned iarg, const vector<double>&, double* der=NULL);
274 : double evaluateGaussian(unsigned iarg, const vector<double>&, const Gaussian&,double* der=NULL);
275 : vector<unsigned> getGaussianSupport(unsigned iarg, const Gaussian&);
276 : bool scanOneHill(unsigned iarg, IFile *ifile, vector<Value> &v, vector<double> ¢er, vector<double> &sigma, double &height, bool &multivariate);
277 : std::string fmt;
278 :
279 : public:
280 : explicit PBMetaD(const ActionOptions&);
281 : ~PBMetaD();
282 : void calculate();
283 : void update();
284 : static void registerKeywords(Keywords& keys);
285 : bool checkNeedsGradients()const;
286 : };
287 :
288 6482 : PLUMED_REGISTER_ACTION(PBMetaD,"PBMETAD")
289 :
290 31 : void PBMetaD::registerKeywords(Keywords& keys) {
291 31 : Bias::registerKeywords(keys);
292 62 : keys.use("ARG");
293 124 : keys.add("compulsory","SIGMA","the widths of the Gaussian hills");
294 124 : keys.add("compulsory","PACE","the frequency for hill addition, one for all biases");
295 124 : keys.add("optional","FILE","files in which the lists of added hills are stored, default names are assigned using arguments if FILE is not found");
296 124 : keys.add("optional","HEIGHT","the height of the Gaussian hills, one for all biases. Compulsory unless TAU, TEMP and BIASFACTOR are given");
297 124 : keys.add("optional","FMT","specify format for HILLS files (useful for decrease the number of digits in regtests)");
298 124 : keys.add("optional","BIASFACTOR","use well tempered metadynamics with this biasfactor, one for all biases. Please note you must also specify temp");
299 124 : keys.add("optional","TEMP","the system temperature - this is only needed if you are doing well-tempered metadynamics");
300 124 : keys.add("optional","TAU","in well tempered metadynamics, sets height to (kb*DeltaT*pace*timestep)/tau");
301 124 : keys.add("optional","GRID_RFILES", "read grid for the bias");
302 124 : keys.add("optional","GRID_WSTRIDE", "frequency for dumping the grid");
303 124 : keys.add("optional","GRID_WFILES", "dump grid for the bias, default names are used if GRID_WSTRIDE is used without GRID_WFILES.");
304 124 : keys.add("optional","GRID_MIN","the lower bounds for the grid");
305 124 : keys.add("optional","GRID_MAX","the upper bounds for the grid");
306 124 : keys.add("optional","GRID_BIN","the number of bins for the grid");
307 124 : keys.add("optional","GRID_SPACING","the approximate grid spacing (to be used as an alternative or together with GRID_BIN)");
308 93 : keys.addFlag("GRID_SPARSE",false,"use a sparse grid to store hills");
309 93 : keys.addFlag("GRID_NOSPLINE",false,"don't use spline interpolation with grids");
310 124 : keys.add("optional","SELECTOR", "add forces and do update based on the value of SELECTOR");
311 124 : keys.add("optional","SELECTOR_ID", "value of SELECTOR");
312 124 : keys.add("optional","WALKERS_ID", "walker id");
313 124 : keys.add("optional","WALKERS_N", "number of walkers");
314 124 : keys.add("optional","WALKERS_DIR", "shared directory with the hills files from all the walkers");
315 124 : keys.add("optional","WALKERS_RSTRIDE","stride for reading hills files");
316 124 : keys.add("optional","INTERVAL_MIN","monodimensional lower limits, outside the limits the system will not feel the biasing force.");
317 124 : keys.add("optional","INTERVAL_MAX","monodimensional upper limits, outside the limits the system will not feel the biasing force.");
318 124 : 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");
319 124 : keys.add("optional","SIGMA_MAX","the upper bounds for the sigmas (in CV units) when using adaptive hills. Negative number means no bounds ");
320 124 : keys.add("optional","SIGMA_MIN","the lower bounds for the sigmas (in CV units) when using adaptive hills. Negative number means no bounds ");
321 93 : keys.addFlag("WALKERS_MPI",false,"Switch on MPI version of multiple walkers - not compatible with WALKERS_* options other than WALKERS_DIR");
322 62 : keys.use("RESTART");
323 62 : keys.use("UPDATE_FROM");
324 62 : keys.use("UPDATE_UNTIL");
325 31 : }
326 :
327 210 : PBMetaD::~PBMetaD() {
328 66 : for(unsigned i=0; i<BiasGrids_.size(); ++i) delete BiasGrids_[i];
329 240 : for(unsigned i=0; i<hillsOfiles_.size(); ++i) {
330 60 : hillsOfiles_[i]->close();
331 60 : delete hillsOfiles_[i];
332 : }
333 30 : if(wgridstride_ > 0) {
334 8 : for(unsigned i=0; i<gridfiles_.size(); ++i) {
335 2 : gridfiles_[i]->close();
336 2 : delete gridfiles_[i];
337 : }
338 : }
339 : // close files
340 240 : for(unsigned i=0; i<ifiles.size(); ++i) {
341 60 : if(ifiles[i]->isOpen()) ifiles[i]->close();
342 60 : delete ifiles[i];
343 : }
344 60 : }
345 :
346 30 : PBMetaD::PBMetaD(const ActionOptions& ao):
347 : PLUMED_BIAS_INIT(ao),
348 : grid_(false), height0_(std::numeric_limits<double>::max()),
349 : biasf_(1.0), kbt_(0.0), stride_(0), wgridstride_(0), welltemp_(false),
350 : mw_n_(1), mw_dir_(""), mw_id_(0), mw_rstride_(1),
351 : walkers_mpi(false), mpi_nw_(0),
352 : adaptive_(FlexibleBin::none),
353 : isFirstStep(true),
354 480 : do_select_(false)
355 : {
356 : // parse the flexible hills
357 : string adaptiveoption;
358 : adaptiveoption="NONE";
359 60 : parse("ADAPTIVE",adaptiveoption);
360 30 : if(adaptiveoption=="GEOM") {
361 0 : log.printf(" Uses Geometry-based hills width: sigma must be in distance units and only one sigma is needed\n");
362 0 : adaptive_=FlexibleBin::geometry;
363 30 : } else if(adaptiveoption=="DIFF") {
364 0 : log.printf(" Uses Diffusion-based hills width: sigma must be in timesteps and only one sigma is needed\n");
365 0 : adaptive_=FlexibleBin::diffusion;
366 30 : } else if(adaptiveoption=="NONE") {
367 30 : adaptive_=FlexibleBin::none;
368 : } else {
369 0 : error("I do not know this type of adaptive scheme");
370 : }
371 :
372 60 : parse("FMT",fmt);
373 :
374 : // parse the sigma
375 60 : parseVector("SIGMA",sigma0_);
376 30 : if(adaptive_==FlexibleBin::none) {
377 : // if you use normal sigma you need one sigma per argument
378 30 : if( sigma0_.size()!=getNumberOfArguments() ) error("number of arguments does not match number of SIGMA parameters");
379 : } else {
380 : // if you use flexible hills you need one sigma
381 0 : if(sigma0_.size()!=1) {
382 0 : error("If you choose ADAPTIVE you need only one sigma according to your choice of type (GEOM/DIFF)");
383 : }
384 : // if adaptive then the number must be an integer
385 0 : if(adaptive_==FlexibleBin::diffusion) {
386 0 : if(int(sigma0_[0])-sigma0_[0]>1.e-9 || int(sigma0_[0])-sigma0_[0] <-1.e-9 || int(sigma0_[0])<1 ) {
387 0 : error("In case of adaptive hills with diffusion, the sigma must be an integer which is the number of timesteps\n");
388 : }
389 : }
390 : // here evtl parse the sigma min and max values
391 0 : parseVector("SIGMA_MIN",sigma0min_);
392 0 : if(sigma0min_.size()>0 && sigma0min_.size()!=getNumberOfArguments()) {
393 0 : error("the number of SIGMA_MIN values be the same of the number of the arguments");
394 0 : } else if(sigma0min_.size()==0) {
395 0 : sigma0min_.resize(getNumberOfArguments());
396 0 : for(unsigned i=0; i<getNumberOfArguments(); i++) {sigma0min_[i]=-1.;}
397 : }
398 :
399 0 : parseVector("SIGMA_MAX",sigma0max_);
400 0 : if(sigma0max_.size()>0 && sigma0max_.size()!=getNumberOfArguments()) {
401 0 : error("the number of SIGMA_MAX values be the same of the number of the arguments");
402 0 : } else if(sigma0max_.size()==0) {
403 0 : sigma0max_.resize(getNumberOfArguments());
404 0 : for(unsigned i=0; i<getNumberOfArguments(); i++) {sigma0max_[i]=-1.;}
405 : }
406 :
407 0 : for(unsigned i=0; i<getNumberOfArguments(); i++) {
408 : vector<double> tmp_smin, tmp_smax;
409 0 : tmp_smin.resize(1,sigma0min_[i]);
410 0 : tmp_smax.resize(1,sigma0max_[i]);
411 0 : flexbin.push_back(FlexibleBin(adaptive_,this,i,sigma0_[0],tmp_smin,tmp_smax));
412 : }
413 : }
414 :
415 : // note: HEIGHT is not compulsory, since one could use the TAU keyword, see below
416 60 : parse("HEIGHT",height0_);
417 60 : parse("PACE",stride_);
418 30 : if(stride_<=0) error("frequency for hill addition is nonsensical");
419 :
420 60 : parseVector("FILE",hillsfname);
421 30 : if(hillsfname.size()==0) {
422 0 : for(unsigned i=0; i<getNumberOfArguments(); i++) hillsfname.push_back("HILLS."+getPntrToArgument(i)->getName());
423 : }
424 30 : if( hillsfname.size()!=getNumberOfArguments() ) {
425 0 : error("number of FILE arguments does not match number of HILLS files");
426 : }
427 :
428 60 : parse("BIASFACTOR",biasf_);
429 30 : if( biasf_<1.0 ) error("well tempered bias factor is nonsensical");
430 30 : double temp=0.0;
431 60 : parse("TEMP",temp);
432 60 : if(temp>0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp;
433 0 : else kbt_=plumed.getAtoms().getKbT();
434 30 : if(biasf_>1.0) {
435 29 : if(kbt_==0.0) error("Unless the MD engine passes the temperature to plumed, with well-tempered metad you must specify it using TEMP");
436 29 : welltemp_=true;
437 : }
438 30 : double tau=0.0;
439 60 : parse("TAU",tau);
440 30 : if(tau==0.0) {
441 30 : if(height0_==std::numeric_limits<double>::max()) error("At least one between HEIGHT and TAU should be specified");
442 : // if tau is not set, we compute it here from the other input parameters
443 30 : if(welltemp_) tau=(kbt_*(biasf_-1.0))/height0_*getTimeStep()*stride_;
444 : } else {
445 0 : if(!welltemp_)error("TAU only makes sense in well-tempered metadynamics");
446 0 : if(height0_!=std::numeric_limits<double>::max()) error("At most one between HEIGHT and TAU should be specified");
447 0 : height0_=(kbt_*(biasf_-1.0))/tau*getTimeStep()*stride_;
448 : }
449 :
450 : // Multiple walkers
451 60 : parse("WALKERS_N",mw_n_);
452 60 : parse("WALKERS_ID",mw_id_);
453 30 : if(mw_n_<=mw_id_) error("walker ID should be a numerical value less than the total number of walkers");
454 60 : parse("WALKERS_DIR",mw_dir_);
455 60 : parse("WALKERS_RSTRIDE",mw_rstride_);
456 :
457 : // MPI version
458 60 : parseFlag("WALKERS_MPI",walkers_mpi);
459 :
460 : // Grid file
461 60 : parse("GRID_WSTRIDE",wgridstride_);
462 30 : vector<string> gridfilenames_;
463 60 : parseVector("GRID_WFILES",gridfilenames_);
464 59 : if (wgridstride_ == 0 && gridfilenames_.size() > 0) {
465 0 : error("frequency with which to output grid not specified use GRID_WSTRIDE");
466 : }
467 30 : if(gridfilenames_.size()==0 && wgridstride_ > 0) {
468 0 : for(unsigned i=0; i<getNumberOfArguments(); i++) gridfilenames_.push_back("GRID."+getPntrToArgument(i)->getName());
469 : }
470 31 : if(gridfilenames_.size() > 0 && hillsfname.size() > 0 && gridfilenames_.size() != hillsfname.size())
471 0 : error("number of GRID_WFILES arguments does not match number of HILLS files");
472 :
473 : // Read grid
474 30 : vector<string> gridreadfilenames_;
475 60 : parseVector("GRID_RFILES",gridreadfilenames_);
476 :
477 : // Grid Stuff
478 60 : vector<std::string> gmin(getNumberOfArguments());
479 60 : parseVector("GRID_MIN",gmin);
480 30 : if(gmin.size()!=getNumberOfArguments() && gmin.size()!=0) error("not enough values for GRID_MIN");
481 60 : vector<std::string> gmax(getNumberOfArguments());
482 60 : parseVector("GRID_MAX",gmax);
483 30 : if(gmax.size()!=getNumberOfArguments() && gmax.size()!=0) error("not enough values for GRID_MAX");
484 30 : vector<unsigned> gbin(getNumberOfArguments());
485 : vector<double> gspacing;
486 60 : parseVector("GRID_BIN",gbin);
487 30 : if(gbin.size()!=getNumberOfArguments() && gbin.size()!=0) error("not enough values for GRID_BIN");
488 60 : parseVector("GRID_SPACING",gspacing);
489 30 : if(gspacing.size()!=getNumberOfArguments() && gspacing.size()!=0) error("not enough values for GRID_SPACING");
490 30 : if(gmin.size()!=gmax.size()) error("GRID_MAX and GRID_MIN should be either present or absent");
491 30 : if(gspacing.size()!=0 && gmin.size()==0) error("If GRID_SPACING is present also GRID_MIN should be present");
492 30 : if(gbin.size()!=0 && gmin.size()==0) error("If GRID_SPACING is present also GRID_MIN should be present");
493 30 : if(gmin.size()!=0) {
494 2 : if(gbin.size()==0 && gspacing.size()==0) {
495 1 : if(adaptive_==FlexibleBin::none) {
496 1 : log<<" Binsize not specified, 1/10 of sigma will be be used\n";
497 1 : plumed_assert(sigma0_.size()==getNumberOfArguments());
498 1 : gspacing.resize(getNumberOfArguments());
499 10 : for(unsigned i=0; i<gspacing.size(); i++) gspacing[i]=0.1*sigma0_[i];
500 : } else {
501 : // with adaptive hills and grid a sigma min must be specified
502 0 : for(unsigned i=0; i<sigma0min_.size(); i++) if(sigma0min_[i]<=0) error("When using Adaptive Gaussians on a grid SIGMA_MIN must be specified");
503 0 : log<<" Binsize not specified, 1/5 of sigma_min will be be used\n";
504 0 : gspacing.resize(getNumberOfArguments());
505 0 : for(unsigned i=0; i<gspacing.size(); i++) gspacing[i]=0.2*sigma0min_[i];
506 : }
507 0 : } else if(gspacing.size()!=0 && gbin.size()==0) {
508 0 : log<<" The number of bins will be estimated from GRID_SPACING\n";
509 0 : } else if(gspacing.size()!=0 && gbin.size()!=0) {
510 0 : log<<" You specified both GRID_BIN and GRID_SPACING\n";
511 0 : log<<" The more conservative (highest) number of bins will be used for each variable\n";
512 : }
513 3 : if(gbin.size()==0) gbin.assign(getNumberOfArguments(),1);
514 6 : if(gspacing.size()!=0) for(unsigned i=0; i<getNumberOfArguments(); i++) {
515 : double a,b;
516 4 : Tools::convert(gmin[i],a);
517 2 : Tools::convert(gmax[i],b);
518 4 : unsigned n=((b-a)/gspacing[i])+1;
519 2 : if(gbin[i]<n) gbin[i]=n;
520 : }
521 : }
522 30 : bool sparsegrid=false;
523 60 : parseFlag("GRID_SPARSE",sparsegrid);
524 30 : bool nospline=false;
525 60 : parseFlag("GRID_NOSPLINE",nospline);
526 30 : bool spline=!nospline;
527 30 : if(gbin.size()>0) {grid_=true;}
528 59 : if(!grid_&&gridfilenames_.size() > 0) error("To write a grid you need first to define it!");
529 59 : if(!grid_&&gridreadfilenames_.size() > 0) error("To read a grid you need first to define it!");
530 :
531 30 : doInt_.resize(getNumberOfArguments(),false);
532 : // Interval keyword
533 60 : parseVector("INTERVAL_MIN",lowI_);
534 60 : parseVector("INTERVAL_MAX",uppI_);
535 : // various checks
536 30 : if(lowI_.size()!=uppI_.size()) error("both a lower and an upper limits must be provided with INTERVAL");
537 30 : if(lowI_.size()!=0 && lowI_.size()!=getNumberOfArguments()) error("check number of argument of INTERVAL");
538 60 : for(unsigned i=0; i<lowI_.size(); ++i) {
539 0 : if(uppI_[i]<lowI_[i]) error("The Upper limit must be greater than the Lower limit!");
540 0 : if(getPntrToArgument(i)->isPeriodic()) warning("INTERVAL is not used for periodic variables");
541 : else doInt_[i]=true;
542 : }
543 :
544 : // parse selector stuff
545 60 : parse("SELECTOR", selector_);
546 30 : if(selector_.length()>0) {
547 0 : do_select_ = true;
548 0 : parse("SELECTOR_ID", select_value_);
549 : }
550 :
551 30 : checkRead();
552 :
553 30 : log.printf(" Gaussian width ");
554 30 : if (adaptive_==FlexibleBin::diffusion)log.printf(" (Note: The units of sigma are in timesteps) ");
555 30 : if (adaptive_==FlexibleBin::geometry)log.printf(" (Note: The units of sigma are in dist units) ");
556 240 : for(unsigned i=0; i<sigma0_.size(); ++i) log.printf(" %f",sigma0_[i]);
557 30 : log.printf(" Gaussian height %f\n",height0_);
558 30 : log.printf(" Gaussian deposition pace %d\n",stride_);
559 :
560 30 : log.printf(" Gaussian files ");
561 240 : for(unsigned i=0; i<hillsfname.size(); ++i) log.printf("%s ",hillsfname[i].c_str());
562 30 : log.printf("\n");
563 30 : if(welltemp_) {
564 29 : log.printf(" Well-Tempered Bias Factor %f\n",biasf_);
565 29 : log.printf(" Hills relaxation time (tau) %f\n",tau);
566 29 : log.printf(" KbT %f\n",kbt_);
567 : }
568 :
569 30 : if(do_select_) {
570 0 : log.printf(" Add forces and update bias based on the value of SELECTOR %s\n",selector_.c_str());
571 0 : log.printf(" Id of the SELECTOR for this action %u\n", select_value_);
572 : }
573 :
574 30 : if(mw_n_>1) {
575 0 : if(walkers_mpi) error("MPI version of multiple walkers is not compatible with filesystem version of multiple walkers");
576 0 : log.printf(" %d multiple walkers active\n",mw_n_);
577 0 : log.printf(" walker id %d\n",mw_id_);
578 0 : log.printf(" reading stride %d\n",mw_rstride_);
579 0 : if(mw_dir_!="")log.printf(" directory with hills files %s\n",mw_dir_.c_str());
580 : } else {
581 30 : if(walkers_mpi) {
582 28 : log.printf(" Multiple walkers active using MPI communnication\n");
583 28 : if(mw_dir_!="")log.printf(" directory with hills files %s\n",mw_dir_.c_str());
584 28 : if(comm.Get_rank()==0) {
585 : // Only root of group can communicate with other walkers
586 14 : mpi_nw_ = multi_sim_comm.Get_size();
587 14 : mpi_id_ = multi_sim_comm.Get_rank();
588 : }
589 : // Communicate to the other members of the same group
590 : // info abount number of walkers and walker index
591 28 : comm.Bcast(mpi_nw_,0);
592 28 : comm.Bcast(mpi_id_,0);
593 : }
594 : }
595 :
596 240 : for(unsigned i=0; i<doInt_.size(); i++) {
597 60 : if(doInt_[i]) log.printf(" Upper and Lower limits boundaries for the bias of CV %u are activated\n", i);
598 : }
599 30 : if(grid_) {
600 1 : log.printf(" Grid min");
601 8 : for(unsigned i=0; i<gmin.size(); ++i) log.printf(" %s",gmin[i].c_str() );
602 1 : log.printf("\n");
603 1 : log.printf(" Grid max");
604 8 : for(unsigned i=0; i<gmax.size(); ++i) log.printf(" %s",gmax[i].c_str() );
605 1 : log.printf("\n");
606 1 : log.printf(" Grid bin");
607 8 : for(unsigned i=0; i<gbin.size(); ++i) log.printf(" %u",gbin[i]);
608 1 : log.printf("\n");
609 1 : if(spline) {log.printf(" Grid uses spline interpolation\n");}
610 1 : if(sparsegrid) {log.printf(" Grid uses sparse grid\n");}
611 1 : if(wgridstride_>0) {
612 8 : for(unsigned i=0; i<gridfilenames_.size(); ++i) {
613 4 : log.printf(" Grid is written on file %s with stride %d\n",gridfilenames_[i].c_str(),wgridstride_);
614 : }
615 : }
616 1 : if(gridreadfilenames_.size()>0) {
617 0 : for(unsigned i=0; i<gridreadfilenames_.size(); ++i) {
618 0 : log.printf(" Reading bias from grid in file %s \n",gridreadfilenames_[i].c_str());
619 : }
620 : }
621 : }
622 :
623 : // initializing vector of hills
624 30 : hills_.resize(getNumberOfArguments());
625 :
626 : // restart from external grid
627 : bool restartedFromGrid=false;
628 :
629 : // initializing and checking grid
630 30 : if(grid_) {
631 : // check for mesh and sigma size
632 5 : for(unsigned i=0; i<getNumberOfArguments(); i++) {
633 : double a,b;
634 4 : Tools::convert(gmin[i],a);
635 2 : Tools::convert(gmax[i],b);
636 4 : double mesh=(b-a)/((double)gbin[i]);
637 2 : if(adaptive_==FlexibleBin::none) {
638 2 : if(mesh>0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n";
639 : } else {
640 0 : if(mesh>0.5*sigma0min_[i]||sigma0min_[i]<0.) log<<" WARNING: to use a METAD with a GRID and ADAPTIVE you need to set a Grid Spacing larger than half of the Gaussians \n";
641 : }
642 : }
643 1 : std::string funcl=getLabel() + ".bias";
644 5 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
645 2 : std::vector<Value*> args(1);
646 2 : args[0] = getPntrToArgument(i);
647 4 : vector<std::string> gmin_t(1);
648 4 : vector<std::string> gmax_t(1);
649 2 : vector<unsigned> gbin_t(1);
650 : gmin_t[0] = gmin[i];
651 : gmax_t[0] = gmax[i];
652 2 : gbin_t[0] = gbin[i];
653 : Grid* BiasGrid_;
654 : // Read grid from file
655 2 : if(gridreadfilenames_.size()>0) {
656 0 : IFile gridfile;
657 0 : gridfile.link(*this);
658 0 : if(gridfile.FileExist(gridreadfilenames_[i])) {
659 0 : gridfile.open(gridreadfilenames_[i]);
660 : } else {
661 0 : error("The GRID file you want to read: " + gridreadfilenames_[i] + ", cannot be found!");
662 : }
663 0 : string funcl = getLabel() + ".bias";
664 0 : BiasGrid_ = Grid::create(funcl, args, gridfile, gmin_t, gmax_t, gbin_t, sparsegrid, spline, true);
665 0 : gridfile.close();
666 0 : if(BiasGrid_->getDimension() != args.size()) {
667 0 : error("mismatch between dimensionality of input grid and number of arguments");
668 : }
669 0 : if(getPntrToArgument(i)->isPeriodic() != BiasGrid_->getIsPeriodic()[0]) {
670 0 : error("periodicity mismatch between arguments and input bias");
671 : }
672 0 : log.printf(" Restarting from %s:",gridreadfilenames_[i].c_str());
673 0 : if(getRestart()) restartedFromGrid=true;
674 : } else {
675 2 : if(!sparsegrid) {BiasGrid_=new Grid(funcl,args,gmin_t,gmax_t,gbin_t,spline,true);}
676 0 : else {BiasGrid_=new SparseGrid(funcl,args,gmin_t,gmax_t,gbin_t,spline,true);}
677 4 : std::vector<std::string> actualmin=BiasGrid_->getMin();
678 4 : std::vector<std::string> actualmax=BiasGrid_->getMax();
679 : std::string is;
680 2 : Tools::convert(i,is);
681 2 : if(gmin_t[0]!=actualmin[0]) error("GRID_MIN["+is+"] must be adjusted to "+actualmin[0]+" to fit periodicity");
682 2 : if(gmax_t[0]!=actualmax[0]) error("GRID_MAX["+is+"] must be adjusted to "+actualmax[0]+" to fit periodicity");
683 : }
684 2 : BiasGrids_.push_back(BiasGrid_);
685 : }
686 : }
687 :
688 :
689 : // creating vector of ifile* for hills reading
690 : // open all files at the beginning and read Gaussians if restarting
691 90 : for(int j=0; j<mw_n_; ++j) {
692 240 : for(unsigned i=0; i<hillsfname.size(); ++i) {
693 60 : unsigned k=j*hillsfname.size()+i;
694 : string fname;
695 60 : if(mw_dir_!="") {
696 0 : if(mw_n_>1) {
697 0 : stringstream out; out << j;
698 0 : fname = mw_dir_+"/"+hillsfname[i]+"."+out.str();
699 0 : } else if(walkers_mpi) {
700 0 : fname = mw_dir_+"/"+hillsfname[i];
701 : } else {
702 : fname = hillsfname[i];
703 : }
704 : } else {
705 60 : if(mw_n_>1) {
706 0 : stringstream out; out << j;
707 0 : fname = hillsfname[i]+"."+out.str();
708 : } else {
709 : fname = hillsfname[i];
710 : }
711 : }
712 60 : IFile *ifile = new IFile();
713 60 : ifile->link(*this);
714 60 : ifiles.push_back(ifile);
715 60 : ifilesnames.push_back(fname);
716 60 : if(ifile->FileExist(fname)) {
717 16 : ifile->open(fname);
718 16 : if(getRestart()&&!restartedFromGrid) {
719 0 : log.printf(" Restarting from %s:",ifilesnames[k].c_str());
720 0 : readGaussians(i,ifiles[k]);
721 : }
722 32 : ifiles[k]->reset(false);
723 : // close only the walker own hills file for later writing
724 32 : if(j==mw_id_) ifiles[k]->close();
725 : } else {
726 : // in case a file does not exist and we are restarting, complain that the file was not found
727 44 : if(getRestart()) log<<" WARNING: restart file "<<fname<<" not found\n";
728 : }
729 : }
730 : }
731 :
732 30 : comm.Barrier();
733 30 : if(comm.Get_rank()==0 && walkers_mpi) multi_sim_comm.Barrier();
734 :
735 : // open hills files for writing
736 240 : for(unsigned i=0; i<hillsfname.size(); ++i) {
737 60 : OFile *ofile = new OFile();
738 60 : ofile->link(*this);
739 : // if MPI multiple walkers, only rank 0 will write to file
740 60 : if(walkers_mpi) {
741 56 : int r=0;
742 56 : if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank();
743 56 : comm.Bcast(r,0);
744 84 : if(r>0) ifilesnames[mw_id_*hillsfname.size()+i]="/dev/null";
745 112 : ofile->enforceSuffix("");
746 : }
747 60 : if(mw_n_>1) ofile->enforceSuffix("");
748 180 : ofile->open(ifilesnames[mw_id_*hillsfname.size()+i]);
749 60 : if(fmt.length()>0) ofile->fmtField(fmt);
750 120 : ofile->addConstantField("multivariate");
751 60 : if(doInt_[i]) {
752 0 : ofile->addConstantField("lower_int").printField("lower_int",lowI_[i]);
753 0 : ofile->addConstantField("upper_int").printField("upper_int",uppI_[i]);
754 : }
755 60 : ofile->setHeavyFlush();
756 : // output periodicities of variables
757 60 : ofile->setupPrintValue( getPntrToArgument(i) );
758 : // push back
759 60 : hillsOfiles_.push_back(ofile);
760 : }
761 :
762 : // Dump grid to files
763 30 : if(wgridstride_ > 0) {
764 8 : for(unsigned i = 0; i < gridfilenames_.size(); ++i) {
765 2 : OFile *ofile = new OFile();
766 2 : ofile->link(*this);
767 : string gridfname_tmp = gridfilenames_[i];
768 2 : if(walkers_mpi) {
769 0 : int r = 0;
770 0 : if(comm.Get_rank() == 0) {
771 0 : r = multi_sim_comm.Get_rank();
772 : }
773 0 : comm.Bcast(r, 0);
774 0 : if(r>0) {
775 : gridfname_tmp = "/dev/null";
776 : }
777 0 : ofile->enforceSuffix("");
778 : }
779 2 : if(mw_n_>1) ofile->enforceSuffix("");
780 2 : ofile->open(gridfname_tmp);
781 2 : ofile->setHeavyFlush();
782 2 : gridfiles_.push_back(ofile);
783 : }
784 : }
785 :
786 90 : log<<" Bibliography "<<plumed.cite("Pfaendtner and Bonomi. J. Chem. Theory Comput. 11, 5062 (2015)");
787 30 : if(doInt_[0]) log<<plumed.cite(
788 0 : "Baftizadeh, Cossio, Pietrucci, and Laio, Curr. Phys. Chem. 2, 79 (2012)");
789 114 : if(mw_n_>1||walkers_mpi) log<<plumed.cite(
790 28 : "Raiteri, Laio, Gervasio, Micheletti, and Parrinello, J. Phys. Chem. B 110, 3533 (2006)");
791 30 : if(adaptive_!=FlexibleBin::none) log<<plumed.cite(
792 0 : "Branduardi, Bussi, and Parrinello, J. Chem. Theory Comput. 8, 2247 (2012)");
793 30 : log<<"\n";
794 30 : }
795 :
796 0 : void PBMetaD::readGaussians(unsigned iarg, IFile *ifile)
797 : {
798 0 : vector<double> center(1);
799 0 : vector<double> sigma(1);
800 : double height;
801 : int nhills=0;
802 0 : bool multivariate=false;
803 :
804 0 : std::vector<Value> tmpvalues;
805 0 : tmpvalues.push_back( Value( this, getPntrToArgument(iarg)->getName(), false ) );
806 :
807 0 : while(scanOneHill(iarg,ifile,tmpvalues,center,sigma,height,multivariate)) {
808 : ;
809 0 : nhills++;
810 0 : if(welltemp_) {height*=(biasf_-1.0)/biasf_;}
811 0 : addGaussian(iarg, Gaussian(center,sigma,height,multivariate));
812 : }
813 0 : log.printf(" %d Gaussians read\n",nhills);
814 0 : }
815 :
816 0 : bool PBMetaD::readChunkOfGaussians(unsigned iarg, IFile *ifile, unsigned n)
817 : {
818 0 : vector<double> center(1);
819 0 : vector<double> sigma(1);
820 : double height;
821 : unsigned nhills=0;
822 0 : bool multivariate=false;
823 0 : std::vector<Value> tmpvalues;
824 0 : tmpvalues.push_back( Value( this, getPntrToArgument(iarg)->getName(), false ) );
825 :
826 0 : while(scanOneHill(iarg,ifile,tmpvalues,center,sigma,height,multivariate)) {
827 : ;
828 0 : if(welltemp_) {height*=(biasf_-1.0)/biasf_;}
829 0 : addGaussian(iarg, Gaussian(center,sigma,height,multivariate));
830 0 : if(nhills==n) {
831 0 : log.printf(" %u Gaussians read\n",nhills);
832 : return true;
833 : }
834 0 : nhills++;
835 : }
836 0 : log.printf(" %u Gaussians read\n",nhills);
837 : return false;
838 : }
839 :
840 896 : void PBMetaD::writeGaussian(unsigned iarg, const Gaussian& hill, OFile *ofile)
841 : {
842 1792 : ofile->printField("time",getTimeStep()*getStep());
843 896 : ofile->printField(getPntrToArgument(iarg),hill.center[0]);
844 :
845 896 : if(hill.multivariate) {
846 0 : ofile->printField("multivariate","true");
847 0 : double lower = sqrt(1./hill.sigma[0]);
848 0 : ofile->printField("sigma_"+getPntrToArgument(iarg)->getName()+"_"+
849 : getPntrToArgument(iarg)->getName(),lower);
850 : } else {
851 2688 : ofile->printField("multivariate","false");
852 2688 : ofile->printField("sigma_"+getPntrToArgument(iarg)->getName(),hill.sigma[0]);
853 : }
854 896 : double height=hill.height;
855 896 : if(welltemp_) height *= biasf_/(biasf_-1.0);
856 1792 : ofile->printField("height",height);
857 1792 : ofile->printField("biasf",biasf_);
858 896 : if(mw_n_>1) ofile->printField("clock",int(std::time(0)));
859 896 : ofile->printField();
860 896 : }
861 :
862 896 : void PBMetaD::addGaussian(unsigned iarg, const Gaussian& hill)
863 : {
864 1784 : if(!grid_) {hills_[iarg].push_back(hill);}
865 : else {
866 8 : vector<unsigned> nneighb=getGaussianSupport(iarg, hill);
867 16 : vector<Grid::index_t> neighbors=BiasGrids_[iarg]->getNeighbors(hill.center,nneighb);
868 8 : vector<double> der(1);
869 8 : vector<double> xx(1);
870 8 : if(comm.Get_size()==1) {
871 1768 : for(unsigned i=0; i<neighbors.size(); ++i) {
872 584 : Grid::index_t ineigh=neighbors[i];
873 584 : der[0]=0.0;
874 584 : BiasGrids_[iarg]->getPoint(ineigh,xx);
875 584 : double bias=evaluateGaussian(iarg,xx,hill,&der[0]);
876 584 : BiasGrids_[iarg]->addValueAndDerivatives(ineigh,bias,der);
877 : }
878 : } else {
879 0 : unsigned stride=comm.Get_size();
880 0 : unsigned rank=comm.Get_rank();
881 0 : vector<double> allder(neighbors.size(),0.0);
882 0 : vector<double> allbias(neighbors.size(),0.0);
883 0 : for(unsigned i=rank; i<neighbors.size(); i+=stride) {
884 0 : Grid::index_t ineigh=neighbors[i];
885 0 : BiasGrids_[iarg]->getPoint(ineigh,xx);
886 0 : allbias[i]=evaluateGaussian(iarg,xx,hill,&allder[i]);
887 : }
888 0 : comm.Sum(allbias);
889 0 : comm.Sum(allder);
890 0 : for(unsigned i=0; i<neighbors.size(); ++i) {
891 0 : Grid::index_t ineigh=neighbors[i];
892 0 : der[0]=allder[i];
893 0 : BiasGrids_[iarg]->addValueAndDerivatives(ineigh,allbias[i],der);
894 : }
895 : }
896 : }
897 896 : }
898 :
899 8 : vector<unsigned> PBMetaD::getGaussianSupport(unsigned iarg, const Gaussian& hill)
900 : {
901 : vector<unsigned> nneigh;
902 : double cutoff;
903 8 : if(hill.multivariate) {
904 0 : double maxautoval=1./hill.sigma[0];
905 0 : cutoff=sqrt(2.0*DP2CUTOFF*maxautoval);
906 : } else {
907 8 : cutoff=sqrt(2.0*DP2CUTOFF)*hill.sigma[0];
908 : }
909 :
910 16 : if(doInt_[iarg]) {
911 0 : if(hill.center[0]+cutoff > uppI_[iarg] || hill.center[0]-cutoff < lowI_[iarg]) {
912 : // in this case, we updated the entire grid to avoid problems
913 0 : return BiasGrids_[iarg]->getNbin();
914 : } else {
915 0 : nneigh.push_back( static_cast<unsigned>(ceil(cutoff/BiasGrids_[iarg]->getDx()[0])));
916 : return nneigh;
917 : }
918 : }
919 :
920 32 : nneigh.push_back( static_cast<unsigned>(ceil(cutoff/BiasGrids_[iarg]->getDx()[0])) );
921 :
922 : return nneigh;
923 : }
924 :
925 972 : double PBMetaD::getBiasAndDerivatives(unsigned iarg, const vector<double>& cv, double* der)
926 : {
927 972 : double bias=0.0;
928 972 : if(!grid_) {
929 954 : unsigned stride=comm.Get_size();
930 954 : unsigned rank=comm.Get_rank();
931 15180 : for(unsigned i=rank; i<hills_[iarg].size(); i+=stride) {
932 4424 : bias += evaluateGaussian(iarg,cv,hills_[iarg][i],der);
933 : }
934 954 : comm.Sum(bias);
935 954 : if(der) comm.Sum(der,1);
936 : } else {
937 18 : if(der) {
938 10 : vector<double> vder(1);
939 20 : bias = BiasGrids_[iarg]->getValueAndDerivatives(cv,vder);
940 10 : der[0] = vder[0];
941 : } else {
942 16 : bias = BiasGrids_[iarg]->getValue(cv);
943 : }
944 : }
945 :
946 972 : return bias;
947 : }
948 :
949 5008 : double PBMetaD::evaluateGaussian(unsigned iarg, const vector<double>& cv, const Gaussian& hill, double* der)
950 : {
951 : double bias=0.0;
952 : // I use a pointer here because cv is const (and should be const)
953 : // but when using doInt it is easier to locally replace cv[0] with
954 : // the upper/lower limit in case it is out of range
955 : const double *pcv=NULL;
956 : double tmpcv[1]; // tmp array with cv (to be used with doInt_)
957 5008 : tmpcv[0]=cv[0];
958 : bool isOutOfInt = false;
959 10016 : if(doInt_[iarg]) {
960 0 : if(cv[0]<lowI_[iarg]) { tmpcv[0]=lowI_[iarg]; isOutOfInt = true; }
961 0 : else if(cv[0]>uppI_[iarg]) { tmpcv[0]=uppI_[iarg]; isOutOfInt = true; }
962 : }
963 : pcv=&(tmpcv[0]);
964 :
965 5008 : if(hill.multivariate) {
966 0 : double dp = difference(iarg, hill.center[0], pcv[0]);
967 0 : double dp2 = 0.5 * dp * dp * hill.sigma[0];
968 0 : if(dp2<DP2CUTOFF) {
969 0 : bias = hill.height*exp(-dp2);
970 0 : if(der && !isOutOfInt) {
971 0 : der[0] += -bias * dp * hill.sigma[0];
972 : }
973 : }
974 : } else {
975 10016 : double dp = difference(iarg, hill.center[0], pcv[0]) * hill.invsigma[0];
976 5008 : double dp2 = 0.5 * dp * dp;
977 5008 : if(dp2<DP2CUTOFF) {
978 4992 : bias = hill.height*exp(-dp2);
979 4992 : if(der && !isOutOfInt) {
980 5560 : der[0] += -bias * dp * hill.invsigma[0];
981 : }
982 : }
983 : }
984 :
985 5008 : return bias;
986 : }
987 :
988 258 : void PBMetaD::calculate()
989 : {
990 : // this is because presently there is no way to properly pass information
991 : // on adaptive hills (diff) after exchanges:
992 258 : if(adaptive_==FlexibleBin::diffusion && getExchangeStep()) error("ADAPTIVE=DIFF is not compatible with replica exchange");
993 :
994 258 : vector<double> cv(1);
995 : double der[1];
996 258 : vector<double> bias(getNumberOfArguments());
997 258 : vector<double> deriv(getNumberOfArguments());
998 :
999 258 : double ncv = (double) getNumberOfArguments();
1000 : double bmin = 1.0e+19;
1001 1290 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
1002 516 : cv[0] = getArgument(i);
1003 516 : der[0] = 0.0;
1004 516 : bias[i] = getBiasAndDerivatives(i, cv, der);
1005 516 : deriv[i] = der[0];
1006 516 : if(bias[i] < bmin) bmin = bias[i];
1007 : }
1008 : double ene = 0.;
1009 1290 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
1010 1032 : ene += exp((-bias[i]+bmin)/kbt_);
1011 : }
1012 :
1013 : // set Forces - set them to zero if SELECTOR is active
1014 258 : if(do_select_) current_value_ = static_cast<unsigned>(plumed.passMap[selector_]);
1015 :
1016 258 : if(!do_select_ || (do_select_ && select_value_==current_value_)) {
1017 1290 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
1018 1548 : const double f = - exp((-bias[i]+bmin)/kbt_) / (ene) * deriv[i];
1019 516 : setOutputForce(i, f);
1020 : }
1021 : }
1022 :
1023 258 : if(do_select_ && select_value_!=current_value_) {
1024 0 : for(unsigned i=0; i<getNumberOfArguments(); ++i) setOutputForce(i, 0.0);
1025 : }
1026 :
1027 : // set bias
1028 258 : ene = -kbt_ * (std::log(ene) - std::log(ncv)) + bmin;
1029 : setBias(ene);
1030 258 : }
1031 :
1032 258 : void PBMetaD::update()
1033 : {
1034 : bool multivariate;
1035 : // adding hills criteria
1036 : bool nowAddAHill;
1037 258 : if(getStep()%stride_==0 && !isFirstStep) nowAddAHill=true;
1038 : else {
1039 : nowAddAHill=false;
1040 30 : isFirstStep=false;
1041 : }
1042 :
1043 : // if you use adaptive, call the FlexibleBin
1044 258 : if(adaptive_!=FlexibleBin::none) {
1045 0 : for(unsigned i=0; i<getNumberOfArguments(); i++) flexbin[i].update(nowAddAHill,i);
1046 : multivariate=true;
1047 : } else {
1048 : multivariate=false;
1049 : }
1050 :
1051 258 : if(nowAddAHill && (!do_select_ || (do_select_ && select_value_==current_value_))) {
1052 : // get all biases and heights
1053 228 : vector<double> cv(getNumberOfArguments());
1054 228 : vector<double> bias(getNumberOfArguments());
1055 228 : vector<double> thissigma(getNumberOfArguments());
1056 228 : vector<double> height(getNumberOfArguments());
1057 228 : vector<double> cv_tmp(1);
1058 228 : vector<double> sigma_tmp(1);
1059 : double norm = 0.0;
1060 : double bmin = 1.0e+19;
1061 1140 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
1062 456 : if(adaptive_!=FlexibleBin::none) thissigma[i]=flexbin[i].getInverseMatrix(i)[0];
1063 912 : else thissigma[i]=sigma0_[i];
1064 912 : cv[i] = getArgument(i);
1065 456 : cv_tmp[0] = getArgument(i);
1066 456 : bias[i] = getBiasAndDerivatives(i, cv_tmp);
1067 456 : if(bias[i] < bmin) bmin = bias[i];
1068 : }
1069 : // calculate heights and norm
1070 1140 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
1071 912 : double h = exp((-bias[i]+bmin)/kbt_);
1072 456 : norm += h;
1073 456 : height[i] = h;
1074 : }
1075 : // normalize and apply welltemp correction
1076 1140 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
1077 912 : height[i] *= height0_ / norm;
1078 1352 : if(welltemp_) height[i] *= exp(-bias[i]/(kbt_*(biasf_-1.0)));
1079 : }
1080 :
1081 : // MPI Multiple walkers: share hills and add them all
1082 228 : if(walkers_mpi) {
1083 : // Allocate arrays to store all walkers hills
1084 440 : std::vector<double> all_cv(mpi_nw_*cv.size(), 0.0);
1085 220 : std::vector<double> all_sigma(mpi_nw_*getNumberOfArguments(), 0.0);
1086 440 : std::vector<double> all_height(mpi_nw_*height.size(), 0.0);
1087 220 : if(comm.Get_rank()==0) {
1088 : // fill in value
1089 550 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
1090 220 : unsigned j = mpi_id_ * getNumberOfArguments() + i;
1091 660 : all_cv[j] = cv[i];
1092 220 : all_sigma[j] = thissigma[i];
1093 220 : all_height[j] = height[i];
1094 : }
1095 : // Communicate (only root)
1096 220 : multi_sim_comm.Sum(&all_cv[0], all_cv.size());
1097 220 : multi_sim_comm.Sum(&all_sigma[0], all_sigma.size());
1098 220 : multi_sim_comm.Sum(&all_height[0], all_height.size());
1099 : }
1100 : // Share info with group members
1101 440 : comm.Sum(&all_cv[0], all_cv.size());
1102 440 : comm.Sum(&all_sigma[0], all_sigma.size());
1103 440 : comm.Sum(&all_height[0], all_height.size());
1104 : // now add hills one by one
1105 1100 : for(unsigned j=0; j<mpi_nw_; ++j) {
1106 2200 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
1107 2640 : cv_tmp[0] = all_cv[j*cv.size()+i];
1108 1760 : double height_tmp = all_height[j*cv.size()+i];
1109 880 : sigma_tmp[0] = all_sigma[j*cv.size()+i];
1110 1760 : Gaussian newhill = Gaussian(cv_tmp, sigma_tmp, height_tmp, multivariate);
1111 880 : addGaussian(i, newhill);
1112 880 : writeGaussian(i, newhill, hillsOfiles_[i]);
1113 : }
1114 : }
1115 : // just add your own hills
1116 : } else {
1117 40 : for(unsigned i=0; i<getNumberOfArguments(); ++i) {
1118 32 : cv_tmp[0] = cv[i];
1119 16 : if(adaptive_!=FlexibleBin::none) sigma_tmp[0]=thissigma[i];
1120 16 : else sigma_tmp[0] = sigma0_[i];
1121 48 : Gaussian newhill = Gaussian(cv_tmp, sigma_tmp, height[i], multivariate);
1122 16 : addGaussian(i, newhill);
1123 16 : writeGaussian(i, newhill, hillsOfiles_[i]);
1124 : }
1125 : }
1126 : }
1127 :
1128 : // write grid files
1129 258 : if(wgridstride_>0 && (getStep()%wgridstride_==0 || getCPT())) {
1130 5 : int r = 0;
1131 5 : if(walkers_mpi) {
1132 0 : if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank();
1133 0 : comm.Bcast(r,0);
1134 : }
1135 5 : if(r==0) {
1136 40 : for(unsigned i=0; i<gridfiles_.size(); ++i) {
1137 10 : gridfiles_[i]->rewind();
1138 20 : BiasGrids_[i]->writeToFile(*gridfiles_[i]);
1139 10 : gridfiles_[i]->flush();
1140 : }
1141 : }
1142 : }
1143 :
1144 : // if multiple walkers and time to read Gaussians
1145 258 : if(mw_n_>1 && getStep()%mw_rstride_==0) {
1146 0 : for(int j=0; j<mw_n_; ++j) {
1147 0 : for(unsigned i=0; i<hillsfname.size(); ++i) {
1148 0 : unsigned k=j*hillsfname.size()+i;
1149 : // don't read your own Gaussians
1150 0 : if(j==mw_id_) continue;
1151 : // if the file is not open yet
1152 0 : if(!(ifiles[k]->isOpen())) {
1153 : // check if it exists now and open it!
1154 0 : if(ifiles[k]->FileExist(ifilesnames[k])) {
1155 0 : ifiles[k]->open(ifilesnames[k]);
1156 0 : ifiles[k]->reset(false);
1157 : }
1158 : // otherwise read the new Gaussians
1159 : } else {
1160 0 : log.printf(" Reading hills from %s:",ifilesnames[k].c_str());
1161 0 : readGaussians(i,ifiles[k]);
1162 0 : ifiles[k]->reset(false);
1163 : }
1164 : }
1165 : }
1166 : }
1167 :
1168 258 : }
1169 :
1170 : /// takes a pointer to the file and a template string with values v and gives back the next center, sigma and height
1171 0 : bool PBMetaD::scanOneHill(unsigned iarg, IFile *ifile, vector<Value> &tmpvalues, vector<double> ¢er, vector<double> &sigma, double &height, bool &multivariate)
1172 : {
1173 : double dummy;
1174 0 : multivariate=false;
1175 0 : if(ifile->scanField("time",dummy)) {
1176 0 : ifile->scanField( &tmpvalues[0] );
1177 0 : if( tmpvalues[0].isPeriodic() && ! getPntrToArgument(iarg)->isPeriodic() ) {
1178 0 : error("in hills file periodicity for variable " + tmpvalues[0].getName() + " does not match periodicity in input");
1179 0 : } else if( tmpvalues[0].isPeriodic() ) {
1180 0 : std::string imin, imax; tmpvalues[0].getDomain( imin, imax );
1181 0 : std::string rmin, rmax; getPntrToArgument(iarg)->getDomain( rmin, rmax );
1182 0 : if( imin!=rmin || imax!=rmax ) {
1183 0 : error("in hills file periodicity for variable " + tmpvalues[0].getName() + " does not match periodicity in input");
1184 : }
1185 : }
1186 0 : center[0]=tmpvalues[0].get();
1187 : std::string sss;
1188 0 : ifile->scanField("multivariate",sss);
1189 0 : if(sss=="true") multivariate=true;
1190 0 : else if(sss=="false") multivariate=false;
1191 0 : else plumed_merror("cannot parse multivariate = "+ sss);
1192 :
1193 0 : if(multivariate) {
1194 0 : ifile->scanField("sigma_"+getPntrToArgument(iarg)->getName()+"_"+
1195 : getPntrToArgument(iarg)->getName(),sigma[0]);
1196 0 : sigma[0] = 1./(sigma[0]*sigma[0]);
1197 : } else {
1198 0 : ifile->scanField("sigma_"+getPntrToArgument(iarg)->getName(),sigma[0]);
1199 : }
1200 0 : ifile->scanField("height",height);
1201 0 : ifile->scanField("biasf",dummy);
1202 0 : if(ifile->FieldExist("clock")) ifile->scanField("clock",dummy);
1203 0 : if(ifile->FieldExist("lower_int")) ifile->scanField("lower_int",dummy);
1204 0 : if(ifile->FieldExist("upper_int")) ifile->scanField("upper_int",dummy);
1205 0 : ifile->scanField();
1206 : return true;
1207 : } else {
1208 : return false;
1209 : }
1210 :
1211 : }
1212 :
1213 258 : bool PBMetaD::checkNeedsGradients()const
1214 : {
1215 258 : if(adaptive_==FlexibleBin::geometry) {
1216 0 : if(getStep()%stride_==0 && !isFirstStep) return true;
1217 : else return false;
1218 : } else return false;
1219 : }
1220 :
1221 : }
1222 4839 : }
1223 :
|