diff --git a/src/gridtools/ActionWithInputGrid.cpp b/src/gridtools/ActionWithInputGrid.cpp index 3ec6ab5d8533084684228ac3aa2f4665f346d53f..f0dfe559e4b8ad68c44656e4d4d179ffd4a19b16 100644 --- a/src/gridtools/ActionWithInputGrid.cpp +++ b/src/gridtools/ActionWithInputGrid.cpp @@ -54,7 +54,11 @@ mygrid(NULL) if( !mygrid ) error("input action does not calculate a grid"); parseFlag("UNORMALISED",unormalised); - if( unormalised ) log.printf(" working with unormalised grid \n"); + if( unormalised ){ + log.printf(" working with unormalised grid \n"); + mygrid->switchOffNormalisation(); + } + if( keywords.exists("USE_ALL_DATA") ){ parseFlag("USE_ALL_DATA",single_run); if( !single_run ) log.printf(" outputting grid every %u steps \n", getStride() ); diff --git a/src/gridtools/GridVessel.cpp b/src/gridtools/GridVessel.cpp index a6f110e79419ae23c42aeb705b2d6dee5b1f4056..9b424a516da1e82347ad48a2f26315afa565c67f 100644 --- a/src/gridtools/GridVessel.cpp +++ b/src/gridtools/GridVessel.cpp @@ -46,7 +46,6 @@ cube_units(1.0) dimension=coordnames.size(); std::vector<std::string> spbc( dimension ); parseVector("PBC",spbc); str_min.resize( dimension); str_max.resize( dimension ); - nbin.resize( dimension ); parseVector("NBINS",nbin); parseFlag("NOMEMORY",nomemory); tmp_indices.resize( str_min.size() ); @@ -60,30 +59,43 @@ cube_units(1.0) for(unsigned j=0;j<coordnames.size();++j){ arg_names[n] = "d" + compnames[i] + "_" + coordnames[j]; n++; } } - npoints=1; dx.resize( dimension ); pbc.resize( dimension ); - min.resize( dimension ); stride.resize( dimension ); max.resize( dimension ); + pbc.resize( dimension ); for(unsigned i=0;i<dimension;++i){ - if( spbc[i]=="F" ){ pbc[i]=false; nbin[i]+=1; } + if( spbc[i]=="F" ) pbc[i]=false; else if( spbc[i]=="T" ) pbc[i]=true; else plumed_error(); - stride[i]=npoints; - npoints*=nbin[i]; } } -void GridVessel::setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax ){ - bounds_set=true; plumed_dbg_assert( smin.size()==dimension && smax.size()==dimension ); +void GridVessel::setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax, + const std::vector<unsigned>& binsin, const std::vector<double>& spacing ){ + plumed_dbg_assert( smin.size()==dimension && smax.size()==dimension ); + plumed_assert( spacing.size()==dimension || binsin.size()==dimension ); + + npoints=1; bounds_set=true; + stride.resize( dimension ); max.resize( dimension ); + dx.resize( dimension ); nbin.resize( dimension ); min.resize( dimension ); for(unsigned i=0;i<dimension;++i){ str_min[i]=smin[i]; str_max[i]=smax[i]; Tools::convert( str_min[i], min[i] ); Tools::convert( str_max[i], max[i] ); - if( !pbc[i] ){ nbin[i]-=1; } + if( spacing.size()==dimension && binsin.size()==dimension ){ + unsigned spc = std::floor(( max[i] - min[i] ) / spacing[i]) + 1; + if( spc>binsin[i] ) nbin[i]=spc; + else nbin[i]=binsin[i]; + } else if( binsin.size()==dimension ) nbin[i]=binsin[i]; + else if( spacing.size()==dimension ) nbin[i] = std::floor(( max[i] - min[i] ) / spacing[i]) + 1; + else plumed_error(); dx[i] = ( max[i] - min[i] ) / static_cast<double>( nbin[i] ); if( !pbc[i] ){ max[i] +=dx[i]; nbin[i]+=1; } + stride[i]=npoints; + npoints*=nbin[i]; } } -std::string GridVessel::getGridDescription() const { +std::string GridVessel::description(){ + if( !bounds_set ) return ""; + std::string des="grid of "; std::string num; for(unsigned i=0;i<dimension-1;++i){ Tools::convert( nbin[i], num ); diff --git a/src/gridtools/GridVessel.h b/src/gridtools/GridVessel.h index c0df8d1734cd8be95c2c4ef137b6c9b04fe804b3..9dfdd8952a17fe0cf1e447fb70687669dc698cea 100644 --- a/src/gridtools/GridVessel.h +++ b/src/gridtools/GridVessel.h @@ -81,9 +81,9 @@ public: /// Constructor explicit GridVessel( const vesselbase::VesselOptions& ); /// Set the minimum and maximum of the grid - virtual void setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax ); + virtual void setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax, const std::vector<unsigned>& nbins, const std::vector<double>& spacing ); /// Get a description of the grid to output to the log - std::string getGridDescription() const ; + std::string description(); /// Convert an index into indices void convertIndexToIndices( const unsigned& index, const std::vector<unsigned>& nnbin, std::vector<unsigned>& indices ) const ; /// Get the indices fof a point @@ -139,6 +139,7 @@ public: double getCubeUnits() const ; /// This gives the normalisation of histograms virtual double getNorm() const ; + virtual void switchOffNormalisation(){} }; inline diff --git a/src/gridtools/HistogramOnGrid.cpp b/src/gridtools/HistogramOnGrid.cpp index 050810e1f4a2eabe0effe9cc4a803aea1bade3a2..6ca321c07133fa1be643a8d953e61322d99afe3a 100644 --- a/src/gridtools/HistogramOnGrid.cpp +++ b/src/gridtools/HistogramOnGrid.cpp @@ -29,18 +29,25 @@ void HistogramOnGrid::registerKeywords( Keywords& keys ){ GridVessel::registerKeywords( keys ); keys.add("compulsory","KERNEL","the type of kernel to use"); keys.add("compulsory","BANDWIDTH","the bandwidths"); + keys.addFlag("STORE_NORMED",false,"are we to store the data normalised"); } HistogramOnGrid::HistogramOnGrid( const vesselbase::VesselOptions& da ): GridVessel(da), norm(0), +store_normed(false), bandwidths(dimension) { - parse("KERNEL",kerneltype); parseVector("BANDWIDTH",bandwidths); + parseFlag("STORE_NORMED",store_normed); parse("KERNEL",kerneltype); parseVector("BANDWIDTH",bandwidths); } -void HistogramOnGrid::setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax ){ - GridVessel::setBounds( smin, smax ); +void HistogramOnGrid::switchOffNormalisation(){ + store_normed=false; +} + +void HistogramOnGrid::setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax, + const std::vector<unsigned>& nbins, const std::vector<double>& spacing ){ + GridVessel::setBounds( smin, smax, nbins, spacing ); std::vector<double> point(dimension,0); KernelFunctions kernel( point, bandwidths, kerneltype, false, 1.0, true ); nneigh=kernel.getSupport( dx ); @@ -80,8 +87,13 @@ void HistogramOnGrid::finish( const std::vector<double>& buffer ){ } void HistogramOnGrid::clear(){ - if( !nomemory ) return ; - norm = 0.; GridVessel::clear(); + if( !nomemory && !store_normed ) return ; + if( nomemory ){ + norm = 0.; GridVessel::clear(); return; + } + if( store_normed ){ + for(unsigned i=0;i<data.size();++i) data[i] /= norm; + } } } diff --git a/src/gridtools/HistogramOnGrid.h b/src/gridtools/HistogramOnGrid.h index 0bdae980e082f0154202ec0ce02bbaf249cdcf95..cea0b9c02ccb96b3d51307c788f8c50d8856fe63 100644 --- a/src/gridtools/HistogramOnGrid.h +++ b/src/gridtools/HistogramOnGrid.h @@ -30,20 +30,22 @@ namespace gridtools { class HistogramOnGrid : public GridVessel { private: double norm; + bool store_normed; std::string kerneltype; std::vector<double> bandwidths; std::vector<unsigned> nneigh; public: static void registerKeywords( Keywords& keys ); explicit HistogramOnGrid( const vesselbase::VesselOptions& da ); - void setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax ); - std::string description(){ return ""; } + void setBounds( const std::vector<std::string>& smin, const std::vector<std::string>& smax, + const std::vector<unsigned>& nbins, const std::vector<double>& spacing ); bool calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const ; void finish( const std::vector<double>& ); bool applyForce( std::vector<double>& forces ){ return false; } void addToNorm( const double& anorm ); void setNorm( const double& snorm ); double getNorm() const ; + void switchOffNormalisation(); void clear(); }; diff --git a/src/multicolvar/MultiColvarDensity.cpp b/src/multicolvar/MultiColvarDensity.cpp index 230e32746ec76656d6b7255d66657c3c695b6ab0..697bc822b0db55a31c0f2ba1ebd175a6d050075f 100644 --- a/src/multicolvar/MultiColvarDensity.cpp +++ b/src/multicolvar/MultiColvarDensity.cpp @@ -63,6 +63,8 @@ class MultiColvarDensity : bool fractional; unsigned rstride; MultiColvarBase* mycolv; + std::vector<unsigned> nbins; + std::vector<double> gspacing; vesselbase::StoreDataVessel* stash; gridtools::HistogramOnGrid* mygrid; Vector origin; @@ -91,7 +93,8 @@ void MultiColvarDensity::registerKeywords( Keywords& keys ){ keys.add("compulsory","STRIDE","1","the frequency with which the data should be collected and added to the grid"); keys.add("atoms","ORIGIN","we will use the position of this atom as the origin"); keys.add("compulsory","DIR","the direction in which to calculate the density profile"); - keys.add("compulsory","NBINS","the number of bins to use to represent the density profile"); + keys.add("optional","NBINS","the number of bins to use to represent the density profile"); + keys.add("optional","SPACING","the approximate grid spacing (to be used as an alternative or together with NBINS)"); keys.add("compulsory","BANDWIDTH","the bandwidths for kernel density esimtation"); keys.add("compulsory","KERNEL","gaussian","the kernel function you are using. More details on the kernels available " "in plumed plumed can be found in \\ref kernelfunctions."); @@ -148,8 +151,10 @@ MultiColvarDensity::MultiColvarDensity(const ActionOptions&ao): error( direction + " is not valid gradient direction"); } log.printf(" for colvars calculated by action %s \n",mycolv->getLabel().c_str() ); + parseVector("NBINS",nbins); parseVector("SPACING",gspacing); + if( nbins.size()!=directions.size() && gspacing.size()!=directions.size() ) error("NBINS or SPACING must be set"); - std::string vstring = getKeyword("NBINS") + " " + getKeyword("KERNEL") + " " + getKeyword("BANDWIDTH"); + std::string vstring = getKeyword("KERNEL") + " " + getKeyword("BANDWIDTH"); vstring += " PBC=T"; for(unsigned i=1;i<directions.size();++i) vstring+=",T"; vstring +=" COMPONENTS=" + getPntrToArgument()->getLabel() + ".dens"; vstring +=" COORDINATES="; @@ -169,7 +174,6 @@ MultiColvarDensity::MultiColvarDensity(const ActionOptions&ao): Keywords keys; gridtools::HistogramOnGrid::registerKeywords( keys ); vesselbase::VesselOptions dar( da, keys ); mygrid = new gridtools::HistogramOnGrid(dar); addVessel( mygrid ); - resizeFunctions(); // Enusre units for cube files are set correctly if( !fractional ){ @@ -204,7 +208,7 @@ void MultiColvarDensity::update(){ if( plumed.getRestart() ){ error("restarting of MultiColvarDensity is not yet implemented"); } else { - mygrid->setBounds( gmin, gmax ); + mygrid->setBounds( gmin, gmax, nbins, gspacing ); resizeFunctions(); } firststep=false; // We only have the first step once } else {