LCOV - code coverage report
Current view: top level - tools - BiasRepresentation.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 274 304 90.1 %
Date: 2026-11-05 10:19:04 Functions: 24 31 77.4 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-2023 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 "BiasRepresentation.h"
      23             : #include "core/Value.h"
      24             : #include "Communicator.h"
      25             : #include <iostream>
      26             : #include "KernelFunctions.h"
      27             : #include "File.h"
      28             : #include "Grid.h"
      29             : #include "Tools.h"
      30             : #include <algorithm>
      31             : #include <cmath>
      32             : #include <limits>
      33             : 
      34             : namespace PLMD {
      35             : 
      36             : namespace {
      37             : /// factor converting the heights written in a hills file into the bias:
      38             : /// with well-tempered metadynamics (biasf>1) the heights are scaled by biasf/(biasf-1),
      39             : /// otherwise they are the bias itself
      40         606 : double biasFactorToBias(double biasf) {
      41         606 :   return biasf>1.0 ? (biasf-1.)/biasf : 1.0;
      42             : }
      43             : }
      44             : 
      45             : /// the constructor here
      46           7 : BiasRepresentation::BiasRepresentation(const std::vector<Value*> & tmpvalues, Communicator &cc ):hasgrid(false),rescaledToBias(false),mycomm(cc) {
      47           7 :   lowI_=0.0;
      48           7 :   uppI_=0.0;
      49           7 :   doInt_=false;
      50           7 :   ndim=tmpvalues.size();
      51          21 :   for(int i=0; i<ndim; i++) {
      52          14 :     values.push_back(tmpvalues[i]);
      53          14 :     names.push_back(values[i]->getName());
      54             :   }
      55           7 :   resetSupport();
      56           7 : }
      57             : 
      58             : /// overload the constructor: add the sigma  at constructor time
      59           1 : BiasRepresentation::BiasRepresentation(const std::vector<Value*> & tmpvalues, Communicator &cc, const std::vector<double> & sigma ):
      60           1 :   hasgrid(false), rescaledToBias(false), histosigma(sigma),mycomm(cc) {
      61           1 :   lowI_=0.0;
      62           1 :   uppI_=0.0;
      63           1 :   doInt_=false;
      64           1 :   ndim=tmpvalues.size();
      65           3 :   for(int i=0; i<ndim; i++) {
      66           2 :     values.push_back(tmpvalues[i]);
      67           2 :     names.push_back(values[i]->getName());
      68             :   }
      69           1 :   resetSupport();
      70           1 : }
      71             : 
      72             : /// overload the constructor: add the grid at constructor time
      73          14 : BiasRepresentation::BiasRepresentation(const std::vector<Value*> & tmpvalues, Communicator &cc, const std::vector<std::string> & gmin, const std::vector<std::string> & gmax,
      74          14 :                                        const std::vector<unsigned> & nbin, bool doInt, double lowI, double uppI):
      75          14 :   hasgrid(false), rescaledToBias(false), mycomm(cc) {
      76          14 :   ndim=tmpvalues.size();
      77          38 :   for(int i=0; i<ndim; i++) {
      78          24 :     values.push_back(tmpvalues[i]);
      79          24 :     names.push_back(values[i]->getName());
      80             :   }
      81          14 :   resetSupport();
      82          14 :   doInt_=doInt;
      83          14 :   lowI_=lowI;
      84          14 :   uppI_=uppI;
      85             :   // initialize the grid
      86          14 :   addGrid(gmin,gmax,nbin);
      87          14 : }
      88             : 
      89             : /// overload the constructor with some external sigmas: needed for histogram
      90           1 : BiasRepresentation::BiasRepresentation(const std::vector<Value*> & tmpvalues, Communicator &cc, const std::vector<std::string> & gmin, const std::vector<std::string> & gmax,
      91           1 :                                        const std::vector<unsigned> & nbin, const std::vector<double> & sigma):
      92           1 :   hasgrid(false), rescaledToBias(false),histosigma(sigma),mycomm(cc) {
      93           1 :   lowI_=0.0;
      94           1 :   uppI_=0.0;
      95           1 :   doInt_=false;
      96           1 :   ndim=tmpvalues.size();
      97           3 :   for(int  i=0; i<ndim; i++) {
      98           2 :     values.push_back(tmpvalues[i]);
      99           2 :     names.push_back(values[i]->getName());
     100             :   }
     101           1 :   resetSupport();
     102             :   // initialize the grid
     103           1 :   addGrid(gmin,gmax,nbin);
     104           1 : }
     105             : 
     106          15 : void BiasRepresentation::addGrid(const std::vector<std::string> & gmin, const std::vector<std::string> & gmax, const std::vector<unsigned> & nbin ) {
     107          15 :   plumed_massert(nkernels==0,"you can set the grid before loading the hills");
     108          15 :   plumed_massert(hasgrid==false,"to build the grid you should not having the grid in this bias representation");
     109             :   std::string ss;
     110             :   ss="file.free";
     111          15 :   std::vector<Value*> vv;
     112          41 :   for(unsigned i=0; i<values.size(); i++) {
     113          26 :     vv.push_back(values[i]);
     114             :   }
     115          30 :   BiasGrid_=Tools::make_unique<Grid>(ss,vv,gmin,gmax,nbin,false,true);
     116          15 :   hasgrid=true;
     117             :   // geometry of the grid, used in addSeparableGaussian
     118          30 :   gridnbin=BiasGrid_->getNbin();
     119          30 :   gridpbc=BiasGrid_->getIsPeriodic();
     120          30 :   griddx=BiasGrid_->getDx();
     121          15 :   gridmin=BiasGrid_->getPoint(std::vector<unsigned>(ndim,0));
     122          15 :   gridstride.assign(ndim,1);
     123          26 :   for(int d=1; d<ndim; d++) {
     124          11 :     gridstride[d]=gridstride[d-1]*gridnbin[d-1];
     125             :   }
     126          15 :   sepIndex.resize(ndim);
     127          15 :   sepT.resize(ndim);
     128          15 :   sepT2.resize(ndim);
     129          15 :   sepExp.resize(ndim);
     130          30 : }
     131             : 
     132        6143 : bool BiasRepresentation::hasSigmaInInput() {
     133        6143 :   if(histosigma.size()==0) {
     134             :     return false;
     135             :   } else {
     136        1092 :     return true;
     137             :   }
     138             : }
     139             : 
     140           2 : void BiasRepresentation::setRescaledToBias(bool rescaled) {
     141           2 :   plumed_massert(nkernels==0,"you can set the rescaling function only before loading hills");
     142           2 :   rescaledToBias=rescaled;
     143           2 : }
     144             : 
     145           0 : const bool & BiasRepresentation::isRescaledToBias() {
     146           0 :   return rescaledToBias;
     147             : }
     148             : 
     149           0 : unsigned BiasRepresentation::getNumberOfDimensions() {
     150           0 :   return values.size();
     151             : }
     152             : 
     153           0 : std::vector<std::string> BiasRepresentation::getNames() {
     154           0 :   return names;
     155             : }
     156             : 
     157           0 : const std::string & BiasRepresentation::getName(unsigned i) {
     158           0 :   return names[i];
     159             : }
     160             : 
     161           0 : const std::vector<Value*>& BiasRepresentation::getPtrToValues() {
     162           0 :   return values;
     163             : }
     164             : 
     165           0 : Value*  BiasRepresentation::getPtrToValue(unsigned i) {
     166           0 :   return values[i];
     167             : }
     168             : 
     169        1092 : std::unique_ptr<KernelFunctions> BiasRepresentation::readFromPoint(IFile *ifile) {
     170        1092 :   std::vector<double> cc( names.size() );
     171        3276 :   for(unsigned i=0; i<names.size(); ++i) {
     172        2184 :     ifile->scanField(names[i],cc[i]);
     173             :   }
     174        1092 :   double h=1.0;
     175        2184 :   return Tools::make_unique<KernelFunctions>(cc,histosigma,"stretched-gaussian","DIAGONAL",h);
     176             : }
     177             : 
     178        6023 : void BiasRepresentation::pushKernel( IFile *ifile, double time ) {
     179             :   double bf;
     180        6023 :   auto kk=readKernel(ifile,bf);
     181        6023 :   addKernel(std::move(kk),bf,time);
     182        6023 : }
     183             : 
     184        6143 : std::unique_ptr<KernelFunctions> BiasRepresentation::readKernel( IFile *ifile, double & bf ) {
     185        6143 :   std::unique_ptr<KernelFunctions> kk;
     186             :   // here below the reading of the kernel is completely hidden
     187        6143 :   if(histosigma.size()==0) {
     188        5051 :     ifile->allowIgnoredFields();
     189       10102 :     kk=KernelFunctions::read(ifile,true,names);
     190             :   } else {
     191             :     // when doing histogram assume gaussian with a given diagonal sigma
     192             :     // and neglect all the rest
     193        2184 :     kk=readFromPoint(ifile);
     194             :   }
     195             :   // the bias factor is not something about the kernels but
     196             :   // must be stored to keep the  bias/free energy duality
     197       12286 :   if(ifile->FieldExist("biasf")) {
     198             :     std::string dummy;
     199        6083 :     ifile->scanField("biasf",dummy);
     200        6083 :     Tools::convert(dummy,bf);
     201             :   } else {
     202          60 :     bf=1.0;
     203             :   }
     204             :   // the domain does not pertain to the kernel but to the values here defined
     205             :   std::string mins,maxs,minv,maxv,mini,maxi;
     206             :   mins="min_";
     207             :   maxs="max_";
     208       18208 :   for(int i=0 ; i<ndim; i++) {
     209       12065 :     if(values[i]->isPeriodic()) {
     210       22536 :       ifile->scanField(mins+names[i],minv);
     211       22536 :       ifile->scanField(maxs+names[i],maxv);
     212             :       // verify that the domain is correct
     213       11268 :       values[i]->getDomain(mini,maxi);
     214       11268 :       plumed_massert(mini==minv,"the input periodicity in hills and in value definition does not match"  );
     215       11268 :       plumed_massert(maxi==maxv,"the input periodicity in hills and in value definition does not match"  );
     216             :     }
     217             :   }
     218        6143 :   return kk;
     219           0 : }
     220             : 
     221        6143 : void BiasRepresentation::addKernel( std::unique_ptr<KernelFunctions> kk, double bf, double time ) {
     222        6143 :   nkernels++;
     223        6143 :   lasttime=std::max(lasttime,time);
     224        6143 :   if(!hasgrid) {
     225             :     // without a grid only the support of the kernels is needed (see getMinMaxBin)
     226        2368 :     std::vector<double> ss;
     227        2368 :     if(histosigma.size()!=0) {
     228         546 :       ss=histosigma;
     229             :     } else {
     230        3644 :       ss=kk->getContinuousSupport();
     231             :     }
     232             :     const std::vector<double> cc=kk->getCenter();
     233             :     const int ndiv=10; // adjustable parameter: division per support
     234        7104 :     for(int j=0; j<ndim; j++) {
     235        5064 :       supmin[j]=std::min(supmin[j],cc[j]-ss[j]);
     236        5006 :       supmax[j]=std::max(supmax[j],cc[j]+ss[j]);
     237        4776 :       minbinsize[j]=std::min(minbinsize[j],ss[j]/double(ndiv));
     238             :     }
     239             :     return;
     240             :   }
     241             :   // with MPI each process adds a subset of the kernels to its own grid,
     242             :   // the grids are summed in getGridPtr
     243        3775 :   if(mycomm.Get_size()>1 && (nkernels-1)%mycomm.Get_size()!=mycomm.Get_rank()) {
     244             :     return;
     245             :   }
     246        3775 :   const double f=(rescaledToBias ? biasFactorToBias(bf) : 1.0);
     247        3775 :   if(!timeaverage || time<avt0) {
     248        3745 :     addToGrid(*BiasGrid_,*kk,f);
     249          30 :   } else if(!avhasend || time<=avt1) {
     250             :     // time average: the hills after t0 are accumulated with weights 1 and t,
     251             :     // and combined in getGridPtr with the weight (t1-t)/(t1-t0)
     252          21 :     addToGrid(*avS1_,*kk,f);
     253          21 :     addToGrid(*avS2_,*kk,f*time);
     254             :   }
     255             : }
     256             : 
     257        3787 : void BiasRepresentation::addToGrid( Grid & g, const KernelFunctions & kk, double f ) {
     258             :   double h,a,b,r2cut;
     259        3787 :   std::vector<double> w;
     260        3787 :   if(!doInt_ && kk.getSeparableGaussian(h,a,b,r2cut,w)) {
     261        1057 :     addSeparableGaussian(g,kk,f*h,a,b,r2cut,w);
     262             :   } else {
     263        2730 :     addGenericKernel(g,kk,f);
     264             :   }
     265        3787 : }
     266             : 
     267        2730 : void BiasRepresentation::addGenericKernel( Grid & g, const KernelFunctions & kk, double f ) {
     268        2730 :   std::vector<unsigned> nneighb;
     269        2730 :   if(doInt_&&(kk.getCenter()[0]+kk.getContinuousSupport()[0] > uppI_ || kk.getCenter()[0]-kk.getContinuousSupport()[0] < lowI_ )) {
     270           0 :     nneighb=g.getNbin();
     271             :   } else {
     272        5460 :     nneighb=kk.getSupport(g.getDx());
     273             :   }
     274        2730 :   std::vector<Grid::index_t> neighbors=g.getNeighbors(kk.getCenter(),nneighb);
     275        2730 :   std::vector<double> der(ndim);
     276        2730 :   std::vector<double> xx(ndim);
     277      973234 :   for(unsigned i=0; i<neighbors.size(); ++i) {
     278      970504 :     Grid::index_t ineigh=neighbors[i];
     279      970504 :     g.getPoint(ineigh,xx);
     280     2911512 :     for(int j=0; j<ndim; ++j) {
     281     1941008 :       values[j]->set(xx[j]);
     282             :     }
     283             :     double bias;
     284      970504 :     if(doInt_) {
     285           0 :       bias=kk.evaluate(values,der,true,doInt_,lowI_,uppI_);
     286             :     } else {
     287      970504 :       bias=kk.evaluate(values,der,true);
     288             :     }
     289      970504 :     bias*=f;
     290     2911512 :     for(int j=0; j<ndim; ++j) {
     291     1941008 :       der[j]*=f;
     292             :     }
     293      970504 :     g.addValueAndDerivatives(ineigh,bias,der);
     294             :   }
     295        5460 : }
     296             : 
     297        1057 : void BiasRepresentation::addSeparableGaussian( Grid & g, const KernelFunctions & kk, double h, double a, double b, double r2cut, const std::vector<double> & w ) {
     298             :   // The kernel is evaluated on the same grid points as in addGenericKernel, but the
     299             :   // Gaussian factors are computed once per dimension and then multiplied, instead of
     300             :   // computing an exponential at each point of the grid.
     301             :   const std::vector<double> c=kk.getCenter();
     302        1057 :   const std::vector<unsigned> nneigh=kk.getSupport(griddx);
     303        2938 :   for(int d=0; d<ndim; d++) {
     304        1881 :     auto & idx=sepIndex[d];
     305             :     auto & t=sepT[d];
     306             :     auto & q=sepT2[d];
     307             :     auto & e=sepExp[d];
     308        1881 :     idx.clear();
     309        1881 :     t.clear();
     310        1881 :     q.clear();
     311        1881 :     e.clear();
     312        1881 :     const int nb=gridnbin[d];
     313        1881 :     const int ic=static_cast<int>(std::floor((c[d]-gridmin[d])/griddx[d]));
     314        1881 :     int span=2*nneigh[d]+1;
     315             :     // along a periodic direction visit each point of the grid only once
     316        1881 :     if(gridpbc[d] && span>nb) {
     317             :       span=nb;
     318             :     }
     319       23984 :     for(int k=0; k<span; k++) {
     320       22103 :       int i=ic-static_cast<int>(nneigh[d])+k;
     321       22103 :       if(!gridpbc[d] && (i<0 || i>=nb)) {
     322          70 :         continue;
     323             :       }
     324       22033 :       if(gridpbc[d]) {
     325       15476 :         i=((i%nb)+nb)%nb;
     326             :       }
     327       22033 :       const double x=gridmin[d]+static_cast<double>(i)*griddx[d];
     328       22033 :       const double tt=-values[d]->difference(x,c[d])/w[d];
     329       22033 :       idx.push_back(i);
     330       22033 :       t.push_back(tt);
     331       22033 :       q.push_back(tt*tt);
     332       22033 :       e.push_back(std::exp(-0.5*tt*tt));
     333             :     }
     334        1881 :     if(idx.empty()) {
     335             :       return;
     336             :     }
     337             :   }
     338             :   // prefix (over the dimensions from the last to the second) of r2, of the product of the exponentials and of the index
     339        1057 :   std::vector<unsigned> pos(ndim,0);
     340        1057 :   std::vector<double> pr2(ndim+1,0.0), pe(ndim+1,1.0);
     341        1057 :   std::vector<Grid::index_t> pidx(ndim+1,0);
     342        8300 :   auto setLevel=[&](int l) {
     343        8300 :     pr2[l]=pr2[l+1]+sepT2[l][pos[l]];
     344        8300 :     pe[l]=pe[l+1]*sepExp[l][pos[l]];
     345        8300 :     pidx[l]=pidx[l+1]+static_cast<Grid::index_t>(sepIndex[l][pos[l]])*gridstride[l];
     346        9357 :   };
     347        1881 :   for(int l=ndim-1; l>=1; --l) {
     348         824 :     setLevel(l);
     349             :   }
     350        1057 :   std::vector<double> der(ndim), dd(ndim);
     351             :   const auto & idx0=sepIndex[0];
     352             :   const auto & t0=sepT[0];
     353             :   const auto & q0=sepT2[0];
     354             :   const auto & e0=sepExp[0];
     355        1057 :   const double ha=h*a;
     356        1057 :   const double hb=h*b;
     357             :   while(true) {
     358        8533 :     const double r2u=pr2[1];
     359        8533 :     const double eu=pe[1];
     360        8533 :     const Grid::index_t iu=pidx[1];
     361       16833 :     for(int l=1; l<ndim; ++l) {
     362        8300 :       der[l]=sepT[l][pos[l]]/w[l];
     363             :     }
     364      112150 :     for(unsigned k=0; k<idx0.size(); ++k) {
     365      103617 :       if(r2u+q0[k]>=r2cut) {
     366       47641 :         continue;
     367             :       }
     368       55976 :       const double ee=eu*e0[k];
     369       55976 :       const double kderiv=-ha*ee;
     370       55976 :       dd[0]=t0[k]/w[0]*kderiv;
     371      107532 :       for(int l=1; l<ndim; ++l) {
     372       51556 :         dd[l]=der[l]*kderiv;
     373             :       }
     374       55976 :       g.addValueAndDerivatives(iu+idx0[k],ha*ee+hb,dd.data(),ndim);
     375             :     }
     376             :     // next combination of the indices of the other dimensions
     377             :     int l=1;
     378        9357 :     while(l<ndim) {
     379        8300 :       pos[l]++;
     380        8300 :       if(pos[l]<sepIndex[l].size()) {
     381             :         break;
     382             :       }
     383         824 :       pos[l]=0;
     384         824 :       l++;
     385             :     }
     386        8533 :     if(l>=ndim) {
     387             :       break;
     388             :     }
     389       14952 :     for(int m=l; m>=1; --m) {
     390        7476 :       setLevel(m);
     391             :     }
     392             :   }
     393        1057 : }
     394             : 
     395        6198 : int BiasRepresentation::getNumberOfKernels() {
     396        6198 :   return nkernels;
     397             : }
     398             : 
     399          23 : Grid* BiasRepresentation::getGridPtr() {
     400          23 :   plumed_massert(hasgrid,"if you want the grid pointer then you should have defined a grid before");
     401          23 :   if(mycomm.Get_size()==1 && !timeaverage) {
     402          21 :     return BiasGrid_.get();
     403             :   }
     404             :   // sum the grids of all the processes and combine the grids of the time average
     405           2 :   const auto n=BiasGrid_->getSize();
     406           6 :   auto getData=[&](const Grid & g, std::vector<double> & val, std::vector<double> & der) {
     407           6 :     val.resize(n);
     408           6 :     der.resize(n*ndim);
     409         366 :     for(Grid::index_t i=0; i<n; i++) {
     410         360 :       val[i]=g.getValueAndDerivatives(i,&der[i*ndim],ndim);
     411             :     }
     412           6 :     if(mycomm.Get_size()>1) {
     413           0 :       mycomm.Sum(val);
     414           0 :       mycomm.Sum(der);
     415             :     }
     416           8 :   };
     417           2 :   std::vector<double> val,der;
     418           2 :   getData(*BiasGrid_,val,der);
     419           2 :   if(timeaverage) {
     420           2 :     std::vector<double> val1,der1,val2,der2;
     421           2 :     getData(*avS1_,val1,der1);
     422           2 :     getData(*avS2_,val2,der2);
     423           2 :     const double t1=getTimeAverageEnd();
     424             :     // weight (t1-t)/(t1-t0) for the hills between t0 and t1
     425           2 :     const double c1=(t1>avt0 ? t1/(t1-avt0) : 1.0);
     426           2 :     const double c2=(t1>avt0 ? -1.0/(t1-avt0) : 0.0);
     427         122 :     for(Grid::index_t i=0; i<n; i++) {
     428         120 :       val[i]+=c1*val1[i]+c2*val2[i];
     429             :     }
     430         122 :     for(Grid::index_t i=0; i<n*ndim; i++) {
     431         120 :       der[i]+=c1*der1[i]+c2*der2[i];
     432             :     }
     433             :   }
     434           2 :   reducedGrid_=Tools::make_unique<Grid>(*BiasGrid_);
     435           2 :   std::vector<double> dd(ndim);
     436         122 :   for(Grid::index_t i=0; i<n; i++) {
     437         240 :     for(int j=0; j<ndim; j++) {
     438         120 :       dd[j]=der[i*ndim+j];
     439             :     }
     440         120 :     reducedGrid_->setValueAndDerivatives(i,val[i],dd);
     441             :   }
     442             :   return reducedGrid_.get();
     443             : }
     444             : 
     445           1 : void BiasRepresentation::setTimeAverage(double t0, bool hasend, double t1) {
     446           1 :   plumed_massert(hasgrid,"the time average requires a grid");
     447           1 :   plumed_massert(nkernels==0,"the time average should be set before adding the kernels");
     448           1 :   timeaverage=true;
     449           1 :   avt0=t0;
     450           1 :   avhasend=hasend;
     451           1 :   avt1=t1;
     452           1 :   plumed_massert(!hasend || t1>t0,"the end of the time average should be after its beginning");
     453           1 :   avS1_=Tools::make_unique<Grid>(*BiasGrid_);
     454           1 :   avS2_=Tools::make_unique<Grid>(*BiasGrid_);
     455           1 : }
     456             : 
     457           2 : double BiasRepresentation::getTimeAverageEnd() const {
     458             :   // without an explicit end (or before reaching it) the average ends at the last hill
     459           2 :   if(!avhasend) {
     460           0 :     return lasttime;
     461             :   }
     462           3 :   return std::min(avt1,lasttime);
     463             : }
     464             : 
     465           3 : double BiasRepresentation::getLastTime() const {
     466           3 :   return lasttime;
     467             : }
     468             : 
     469           8 : void BiasRepresentation::getMinMaxBin(std::vector<double> &vmin, std::vector<double> &vmax, std::vector<unsigned> &vbin) {
     470           8 :   vmin=supmin;
     471           8 :   vmax=supmax;
     472           8 :   vbin.assign(ndim,0);
     473          24 :   for(int j=0; j<ndim; j++) {
     474             :     // reset to periodicity
     475          16 :     if(values[j]->isPeriodic()) {
     476             :       double minv,maxv;
     477           8 :       values[j]->getDomain(minv,maxv);
     478           8 :       if(minv>vmin[j]) {
     479           0 :         vmin[j]=minv;
     480             :       }
     481           8 :       if(maxv<vmax[j]) {
     482           0 :         vmax[j]=maxv;
     483             :       }
     484             :     }
     485          16 :     vbin[j]=static_cast<unsigned>(std::ceil((vmax[j]-vmin[j])/minbinsize[j]) );
     486             :   }
     487           8 : }
     488             : 
     489           0 : void BiasRepresentation::clear() {
     490           0 :   nkernels=0;
     491           0 :   lasttime=-std::numeric_limits<double>::max();
     492           0 :   resetSupport();
     493             :   // clear the grid
     494           0 :   if(hasgrid) {
     495           0 :     BiasGrid_->clear();
     496             :   }
     497           0 :   if(timeaverage) {
     498           0 :     avS1_->clear();
     499           0 :     avS2_->clear();
     500             :   }
     501           0 : }
     502             : 
     503          23 : void BiasRepresentation::resetSupport() {
     504          23 :   supmin.assign(ndim,10.e20);
     505          23 :   supmax.assign(ndim,-10.e20);
     506          23 :   minbinsize.assign(ndim,10.e20);
     507          23 : }
     508             : 
     509             : 
     510             : }

Generated by: LCOV version 1.16