LCOV - code coverage report
Current view: top level - ves - BasisFunctions.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 270 290 93.1 %
Date: 2019-08-13 10:15:31 Functions: 22 25 88.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2016-2018 The VES code team
       3             :    (see the PEOPLE-VES file at the root of this folder for a list of names)
       4             : 
       5             :    See http://www.ves-code.org for more information.
       6             : 
       7             :    This file is part of VES code module.
       8             : 
       9             :    The VES code module 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             :    The VES code module 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 the VES code module.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : 
      23             : #include "BasisFunctions.h"
      24             : #include "TargetDistribution.h"
      25             : #include "VesBias.h"
      26             : #include "VesTools.h"
      27             : #include "GridIntegrationWeights.h"
      28             : 
      29             : #include "tools/Grid.h"
      30             : #include "tools/Tools.h"
      31             : 
      32             : 
      33             : namespace PLMD {
      34             : namespace ves {
      35             : 
      36         216 : void BasisFunctions::registerKeywords(Keywords& keys) {
      37         216 :   Action::registerKeywords(keys);
      38         864 :   keys.add("compulsory","ORDER","The order of the basis function expansion.");
      39         864 :   keys.add("compulsory","MINIMUM","The minimum of the interval on which the basis functions are defined.");
      40         864 :   keys.add("compulsory","MAXIMUM","The maximum of the interval on which the basis functions are defined.");
      41         864 :   keys.add("hidden","NGRID_POINTS","The number of grid points used for numerical integrals");
      42         648 :   keys.addFlag("DEBUG_INFO",false,"Print out more detailed information about the basis set. Useful for debugging.");
      43         648 :   keys.addFlag("NUMERICAL_INTEGRALS",false,"Calculate basis function integral for the uniform distribution numerically. Useful for debugging.");
      44         216 : }
      45             : 
      46             : 
      47         203 : BasisFunctions::BasisFunctions(const ActionOptions&ao):
      48             :   Action(ao),
      49             :   print_debug_info_(false),
      50             :   has_been_set(false),
      51             :   description_("Undefined"),
      52             :   type_("Undefined"),
      53             :   norder_(0),
      54             :   nbasis_(1),
      55             :   bf_label_prefix_("f"),
      56             :   bf_labels_(nbasis_,"f0"),
      57             :   periodic_(false),
      58             :   orthogonal_(false),
      59             :   interval_bounded_(true),
      60             :   interval_intrinsic_min_str_("1.0"),
      61             :   interval_intrinsic_max_str_("-1.0"),
      62             :   interval_intrinsic_min_(1.0),
      63             :   interval_intrinsic_max_(-1.0),
      64             :   interval_intrinsic_range_(0.0),
      65             :   interval_intrinsic_mean_(0.0),
      66             :   interval_min_str_(""),
      67             :   interval_max_str_(""),
      68             :   interval_min_(0.0),
      69             :   interval_max_(0.0),
      70             :   interval_range_(0.0),
      71             :   interval_mean_(0.0),
      72             :   argT_derivf_(1.0),
      73             :   numerical_uniform_integrals_(false),
      74             :   nbins_(1001),
      75             :   uniform_integrals_(nbasis_,0.0),
      76             :   vesbias_pntr_(NULL),
      77         609 :   action_pntr_(NULL)
      78             : {
      79         203 :   bf_keywords_.push_back(getName());
      80         406 :   if(keywords.exists("ORDER")) {
      81         573 :     parse("ORDER",norder_); addKeywordToList("ORDER",norder_);
      82             :   }
      83         203 :   nbasis_=norder_+1;
      84             :   //
      85             :   std::string str_imin; std::string str_imax;
      86         607 :   if(keywords.exists("MINIMUM") && keywords.exists("MAXIMUM")) {
      87         804 :     parse("MINIMUM",str_imin); addKeywordToList("MINIMUM",str_imin);
      88         804 :     parse("MAXIMUM",str_imax); addKeywordToList("MAXIMUM",str_imax);
      89             :   }
      90             :   else {
      91             :     str_imin = "-1.0";
      92             :     str_imax = "1.0";
      93             :   }
      94             :   interval_min_str_ = str_imin;
      95             :   interval_max_str_ = str_imax;
      96         203 :   if(!Tools::convert(str_imin,interval_min_)) {
      97           0 :     plumed_merror(getName()+": cannot convert the value given in MINIMUM to a double");
      98             :   }
      99         203 :   if(!Tools::convert(str_imax,interval_max_)) {
     100           0 :     plumed_merror(getName()+": cannot convert the value given in MAXIMUM to a double");
     101             :   }
     102         203 :   if(interval_min_>interval_max_) {plumed_merror(getName()+": MINIMUM and MAXIMUM are not correctly defined");}
     103             :   //
     104         406 :   parseFlag("DEBUG_INFO",print_debug_info_);
     105         406 :   if(keywords.exists("NUMERICAL_INTEGRALS")) {
     106         346 :     parseFlag("NUMERICAL_INTEGRALS",numerical_uniform_integrals_);
     107             :   }
     108         406 :   if(keywords.exists("NGRID_POINTS")) {
     109         402 :     parse("NGRID_POINTS",nbins_);
     110             :   }
     111             :   // log.printf(" %s \n",getKeywordString().c_str());
     112             : 
     113         203 : }
     114             : 
     115             : 
     116          32 : void BasisFunctions::setIntrinsicInterval(const double interval_intrinsic_min_in, const double interval_intrinsic_max_in) {
     117          32 :   interval_intrinsic_min_ = interval_intrinsic_min_in;
     118          32 :   interval_intrinsic_max_ = interval_intrinsic_max_in;
     119          32 :   VesTools::convertDbl2Str(interval_intrinsic_min_,interval_intrinsic_min_str_);
     120          32 :   VesTools::convertDbl2Str(interval_intrinsic_max_,interval_intrinsic_max_str_);
     121          32 :   plumed_massert(interval_intrinsic_min_<interval_intrinsic_max_,"setIntrinsicInterval: intrinsic intervals are not defined correctly");
     122          32 : }
     123             : 
     124             : 
     125         171 : void BasisFunctions::setIntrinsicInterval(const std::string& interval_intrinsic_min_str_in, const std::string& interval_intrinsic_max_str_in) {
     126         171 :   interval_intrinsic_min_str_ = interval_intrinsic_min_str_in;
     127         171 :   interval_intrinsic_max_str_ = interval_intrinsic_max_str_in;
     128         171 :   if(!Tools::convert(interval_intrinsic_min_str_,interval_intrinsic_min_)) {
     129           0 :     plumed_merror("setIntrinsicInterval: cannot convert string value given for the minimum of the intrinsic interval to a double");
     130             :   }
     131         171 :   if(!Tools::convert(interval_intrinsic_max_str_,interval_intrinsic_max_)) {
     132           0 :     plumed_merror("setIntrinsicInterval: cannot convert string value given for the maximum of the intrinsic interval to a double");
     133             :   }
     134         171 :   plumed_massert(interval_intrinsic_min_<interval_intrinsic_max_,"setIntrinsicInterval: intrinsic intervals are not defined correctly");
     135         171 : }
     136             : 
     137             : 
     138           0 : void BasisFunctions::setInterval(const double interval_min_in, const double interval_max_in) {
     139           0 :   interval_min_ = interval_min_in;
     140           0 :   interval_max_ = interval_max_in;
     141           0 :   VesTools::convertDbl2Str(interval_min_,interval_min_str_);
     142           0 :   VesTools::convertDbl2Str(interval_max_,interval_max_str_);
     143           0 :   plumed_massert(interval_min_<interval_max_,"setInterval: intervals are not defined correctly");
     144           0 : }
     145             : 
     146             : 
     147           2 : void BasisFunctions::setInterval(const std::string& interval_min_str_in, const std::string& interval_max_str_in) {
     148           2 :   interval_min_str_ = interval_min_str_in;
     149           2 :   interval_max_str_ = interval_max_str_in;
     150           2 :   if(!Tools::convert(interval_min_str_,interval_min_)) {
     151           0 :     plumed_merror("setInterval: cannot convert string value given for the minimum of the interval to a double");
     152             :   }
     153           2 :   if(!Tools::convert(interval_max_str_,interval_max_)) {
     154           0 :     plumed_merror("setInterval: cannot convert string value given for the maximum of the interval to a double");
     155             :   }
     156           2 :   plumed_massert(interval_min_<interval_max_,"setInterval: intervals are not defined correctly");
     157           2 : }
     158             : 
     159             : 
     160         203 : void BasisFunctions::setupInterval() {
     161             :   // if(!intervalBounded()){plumed_merror("setupInterval() only works for bounded interval");}
     162         203 :   interval_intrinsic_range_ = interval_intrinsic_max_-interval_intrinsic_min_;
     163         203 :   interval_intrinsic_mean_  = 0.5*(interval_intrinsic_max_+interval_intrinsic_min_);
     164         203 :   interval_range_ = interval_max_-interval_min_;
     165         203 :   interval_mean_  = 0.5*(interval_max_+interval_min_);
     166         203 :   argT_derivf_ = interval_intrinsic_range_/interval_range_;
     167         203 : }
     168             : 
     169             : 
     170          81 : void BasisFunctions::setupLabels() {
     171         950 :   for(unsigned int i=0; i < nbasis_; i++) {
     172         869 :     std::string is; Tools::convert(i,is);
     173        3476 :     bf_labels_[i]=bf_label_prefix_+is+"(s)";
     174             :   }
     175          81 : }
     176             : 
     177             : 
     178          32 : void BasisFunctions::setupUniformIntegrals() {
     179          32 :   numerical_uniform_integrals_=true;
     180          32 :   numericalUniformIntegrals();
     181          32 : }
     182             : 
     183             : 
     184         203 : void BasisFunctions::setupBF() {
     185         203 :   if(interval_intrinsic_min_>interval_intrinsic_max_) {plumed_merror("setupBF: default intervals are not correctly set");}
     186         203 :   setupInterval();
     187         203 :   setupLabels();
     188         203 :   if(bf_labels_.size()==1) {plumed_merror("setupBF: the labels of the basis functions are not correct.");}
     189         203 :   if(!numerical_uniform_integrals_) {setupUniformIntegrals();}
     190           6 :   else {numericalUniformIntegrals();}
     191         203 :   if(uniform_integrals_.size()==1) {plumed_merror("setupBF: the integrals of the basis functions is not correct.");}
     192         406 :   if(type_=="Undefined") {plumed_merror("setupBF: the type of the basis function is not defined.");}
     193         406 :   if(description_=="Undefined") {plumed_merror("setupBF: the description of the basis function is not defined.");}
     194         203 :   has_been_set=true;
     195         203 :   printInfo();
     196         203 : }
     197             : 
     198             : 
     199         203 : void BasisFunctions::printInfo() const {
     200         203 :   if(!has_been_set) {plumed_merror("the basis set has not be setup correctly");}
     201         203 :   log.printf("  One-dimensional basis set\n");
     202         203 :   log.printf("   Description: %s\n",description_.c_str());
     203         203 :   log.printf("   Type: %s\n",type_.c_str());
     204         203 :   if(periodic_) {log.printf("   The basis functions are periodic\n");}
     205         203 :   if(orthogonal_) {
     206         354 :     if(getInnerProductWeightStr()=="1") {
     207         173 :       log.printf("   The basis functions are orthogonal\n");
     208             :     }
     209             :     else {
     210          12 :       log.printf("   The basis functions are orthogonal with respect to the weight %s\n",getInnerProductWeightStr().c_str());
     211             :     }
     212             :   }
     213             :   else {
     214          26 :     log.printf("   The basis functions are not orthogonal\n");
     215             :   }
     216         203 :   log.printf("   Order of basis set: %u\n",norder_);
     217         203 :   log.printf("   Number of basis functions: %u\n",nbasis_);
     218             :   // log.printf("   Interval of basis set: %f to %f\n",interval_min_,interval_max_);
     219         203 :   log.printf("   Interval of basis set: %s to %s\n",interval_min_str_.c_str(),interval_max_str_.c_str());
     220         203 :   log.printf("   Description of basis functions:\n");
     221        2412 :   for(unsigned int i=0; i < nbasis_; i++) {log.printf("    %2u       %10s\n",i,bf_labels_[i].c_str());}
     222             :   //
     223         203 :   if(print_debug_info_) {
     224          44 :     log.printf("  Debug information:\n");
     225             :     // log.printf("   Default interval of basis set: [%f,%f]\n",interval_intrinsic_min_,interval_intrinsic_max_);
     226          44 :     log.printf("   Intrinsic interval of basis set: [%s,%s]\n",interval_intrinsic_min_str_.c_str(),interval_intrinsic_max_str_.c_str());
     227          44 :     log.printf("   Intrinsic interval of basis set: range=%f,  mean=%f\n",interval_intrinsic_range_,interval_intrinsic_mean_);
     228             :     // log.printf("   Defined interval of basis set: [%f,%f]\n",interval_min_,interval_max_);
     229          44 :     log.printf("   Defined interval of basis set: [%s,%s]\n",interval_min_str_.c_str(),interval_max_str_.c_str());
     230          44 :     log.printf("   Defined interval of basis set: range=%f,  mean=%f\n",interval_range_,interval_mean_);
     231          44 :     log.printf("   Derivative factor due to interval translation: %f\n",argT_derivf_);
     232          44 :     log.printf("   Integral of basis functions over the interval:\n");
     233          44 :     if(numerical_uniform_integrals_) {log.printf("   Note: calculated numerically\n");}
     234        1288 :     for(unsigned int i=0; i < nbasis_; i++) {log.printf("    %2u       %16.10f\n",i,uniform_integrals_[i]);}
     235          44 :     log.printf("   --------------------------\n");
     236             :   }
     237         203 : }
     238             : 
     239             : 
     240           0 : void BasisFunctions::linkVesBias(VesBias* vesbias_pntr_in) {
     241           0 :   vesbias_pntr_ = vesbias_pntr_in;
     242           0 :   action_pntr_ = static_cast<Action*>(vesbias_pntr_in);
     243           0 : }
     244             : 
     245             : 
     246           0 : void BasisFunctions::linkAction(Action* action_pntr_in) {
     247           0 :   action_pntr_ = action_pntr_in;
     248           0 : }
     249             : 
     250             : 
     251          38 : void BasisFunctions::numericalUniformIntegrals() {
     252          76 :   std::vector<std::string> grid_min(1); grid_min[0]=intervalMinStr();
     253         114 :   std::vector<std::string> grid_max(1); grid_max[0]=intervalMaxStr();
     254          76 :   std::vector<unsigned int> grid_bins(1); grid_bins[0]=nbins_;
     255         114 :   std::vector<Value*> arguments(1); arguments[0]= new Value(NULL,"arg",false);
     256          50 :   if(arePeriodic()) {arguments[0]->setDomain(intervalMinStr(),intervalMaxStr());}
     257          34 :   else {arguments[0]->setNotPeriodic();}
     258          76 :   Grid* uniform_grid = new Grid("uniform",arguments,grid_min,grid_max,grid_bins,false,false);
     259             :   //
     260          38 :   double inverse_normalization = 1.0/(intervalMax()-intervalMin());
     261       38110 :   for(Grid::index_t l=0; l<uniform_grid->getSize(); l++) {
     262       38072 :     uniform_grid->setValue(l,inverse_normalization);
     263             :   }
     264          76 :   uniform_integrals_ = numericalTargetDistributionIntegralsFromGrid(uniform_grid);
     265          38 :   delete arguments[0]; arguments.clear();
     266          76 :   delete uniform_grid;
     267          38 : }
     268             : 
     269             : 
     270         188 : std::vector<double> BasisFunctions::numericalTargetDistributionIntegralsFromGrid(const Grid* grid_pntr) const {
     271         188 :   plumed_massert(grid_pntr!=NULL,"the grid is not defined");
     272         188 :   plumed_massert(grid_pntr->getDimension()==1,"the target distribution grid should be one dimensional");
     273             :   //
     274         188 :   std::vector<double> targetdist_integrals(nbasis_,0.0);
     275         564 :   std::vector<double> integration_weights = GridIntegrationWeights::getIntegrationWeights(grid_pntr);
     276             : 
     277       83369 :   for(Grid::index_t k=0; k < grid_pntr->getSize(); k++) {
     278      249543 :     double arg = grid_pntr->getPoint(k)[0];
     279       83181 :     std::vector<double> bf_values(nbasis_);
     280       83181 :     std::vector<double> bf_derivs(nbasis_);
     281       83181 :     bool inside=true;
     282       83181 :     double argT=0.0;
     283       83181 :     getAllValues(arg,argT,inside,bf_values,bf_derivs);
     284     1145995 :     for(unsigned int i=0; i < nbasis_; i++) {
     285     3437985 :       targetdist_integrals[i] += (integration_weights[k] * grid_pntr->getValue(k)) * bf_values[i];
     286             :     }
     287             :   }
     288             :   // assume that the first function is the constant
     289         188 :   bool inside=true;
     290         188 :   double argT=0.0;
     291         188 :   targetdist_integrals[0] = getValue(0.0,0,argT,inside);
     292         188 :   return targetdist_integrals;
     293             : }
     294             : 
     295             : 
     296         233 : std::vector<double> BasisFunctions::getTargetDistributionIntegrals(const TargetDistribution* targetdist_pntr) const {
     297         233 :   if(targetdist_pntr==NULL) {
     298             :     return getUniformIntegrals();
     299             :   }
     300             :   else {
     301             :     Grid* targetdist_grid = targetdist_pntr->getTargetDistGridPntr();
     302         150 :     return numericalTargetDistributionIntegralsFromGrid(targetdist_grid);
     303             :   }
     304             : }
     305             : 
     306             : 
     307         166 : std::string BasisFunctions::getKeywordString() const {
     308         166 :   std::string str_keywords=bf_keywords_[0];
     309        2420 :   for(unsigned int i=1; i<bf_keywords_.size(); i++) {str_keywords+=" "+bf_keywords_[i];}
     310         166 :   return str_keywords;
     311             : }
     312             : 
     313             : 
     314         188 : double BasisFunctions::getValue(const double arg, const unsigned int n, double& argT, bool& inside_range) const {
     315         188 :   plumed_massert(n<numberOfBasisFunctions(),"getValue: n is outside range of the defined order of the basis set");
     316         188 :   inside_range=true;
     317         188 :   std::vector<double> tmp_values(numberOfBasisFunctions());
     318         188 :   std::vector<double> tmp_derivs(numberOfBasisFunctions());
     319         188 :   getAllValues(arg, argT, inside_range, tmp_values, tmp_derivs);
     320         564 :   return tmp_values[n];
     321             : }
     322             : 
     323             : 
     324        5716 : void BasisFunctions::getAllValuesNumericalDerivs(const double arg, double& argT, bool& inside_range, std::vector<double>& values, std::vector<double>& derivs) const {
     325             :   // use forward difference, unless very close to the boundary
     326             :   double delta = sqrt(epsilon);
     327       11432 :   if((arg+delta)>intervalMax()) {
     328             :     delta *= -1.0;
     329             :   }
     330        5716 :   inside_range=true;
     331        5716 :   std::vector<double> values_delta(numberOfBasisFunctions());
     332        5716 :   std::vector<double> derivs_dummy(numberOfBasisFunctions());
     333        5716 :   getAllValues(arg+delta, argT, inside_range, values_delta, derivs_dummy);
     334        5716 :   getAllValues(arg, argT, inside_range, values, derivs_dummy);
     335      200678 :   for(unsigned int i=0; i<numberOfBasisFunctions(); i++) {
     336      292443 :     derivs[i] = (values_delta[i]-values[i])/delta;
     337             :   }
     338        5716 : }
     339             : 
     340             : 
     341          83 : void BasisFunctions::getMultipleValue(const std::vector<double>& args, std::vector<double>& argsT, std::vector<std::vector<double> >& values, std::vector<std::vector<double> >& derivs, const bool numerical_deriv) const {
     342          83 :   argsT.resize(args.size());
     343             :   values.clear();
     344             :   derivs.clear();
     345       53096 :   for(unsigned int i=0; i<args.size(); i++) {
     346       26465 :     std::vector<double> tmp_values(getNumberOfBasisFunctions());
     347       26465 :     std::vector<double> tmp_derivs(getNumberOfBasisFunctions());
     348       26465 :     bool inside_interval=true;
     349       26465 :     if(!numerical_deriv) {
     350       41498 :       getAllValues(args[i],argsT[i],inside_interval,tmp_values,tmp_derivs);
     351             :     } else {
     352        5716 :       getAllValuesNumericalDerivs(args[i],argsT[i],inside_interval,tmp_values,tmp_derivs);
     353             :     }
     354       26465 :     values.push_back(tmp_values);
     355       26465 :     derivs.push_back(tmp_derivs);
     356             :   }
     357          83 : }
     358             : 
     359             : 
     360          83 : void BasisFunctions::writeBasisFunctionsToFile(OFile& ofile_values, OFile& ofile_derivs, const std::string& min_in, const std::string& max_in, unsigned int nbins_in, const bool ignore_periodicity, const std::string& output_fmt, const bool numerical_deriv) const {
     361          83 :   std::vector<std::string> min(1); min[0]=min_in;
     362         166 :   std::vector<std::string> max(1); max[0]=max_in;
     363         166 :   std::vector<unsigned int> nbins(1); nbins[0]=nbins_in;
     364          83 :   std::vector<Value*> value_pntr(1);
     365         249 :   value_pntr[0]= new Value(NULL,"arg",false);
     366         137 :   if(arePeriodic() && !ignore_periodicity) {value_pntr[0]->setDomain(intervalMinStr(),intervalMaxStr());}
     367          65 :   else {value_pntr[0]->setNotPeriodic();}
     368         249 :   Grid args_grid = Grid("grid",value_pntr,min,max,nbins,false,false);
     369             : 
     370          83 :   std::vector<double> args(args_grid.getSize(),0.0);
     371       53096 :   for(unsigned int i=0; i<args.size(); i++) {
     372       79395 :     args[i] = args_grid.getPoint(i)[0];
     373             :   }
     374             :   std::vector<double> argsT;
     375          83 :   std::vector<std::vector<double> > values;
     376          83 :   std::vector<std::vector<double> > derivs;
     377             : 
     378         581 :   ofile_values.addConstantField("bf_keywords").printField("bf_keywords","{"+getKeywordString()+"}");
     379         581 :   ofile_derivs.addConstantField("bf_keywords").printField("bf_keywords","{"+getKeywordString()+"}");
     380             : 
     381         332 :   ofile_values.addConstantField("min").printField("min",intervalMinStr());
     382         332 :   ofile_values.addConstantField("max").printField("max",intervalMaxStr());
     383             : 
     384         332 :   ofile_derivs.addConstantField("min").printField("min",intervalMinStr());
     385         332 :   ofile_derivs.addConstantField("max").printField("max",intervalMaxStr());
     386             : 
     387         415 :   ofile_values.addConstantField("nbins").printField("nbins",static_cast<int>(args_grid.getNbin()[0]));
     388         415 :   ofile_derivs.addConstantField("nbins").printField("nbins",static_cast<int>(args_grid.getNbin()[0]));
     389             : 
     390          83 :   if(arePeriodic()) {
     391          84 :     ofile_values.addConstantField("periodic").printField("periodic","true");
     392          84 :     ofile_derivs.addConstantField("periodic").printField("periodic","true");
     393             :   }
     394             :   else {
     395         248 :     ofile_values.addConstantField("periodic").printField("periodic","false");
     396         248 :     ofile_derivs.addConstantField("periodic").printField("periodic","false");
     397             :   }
     398             : 
     399          83 :   getMultipleValue(args,argsT,values,derivs,numerical_deriv);
     400          83 :   ofile_values.fmtField(output_fmt);
     401          83 :   ofile_derivs.fmtField(output_fmt);
     402       53013 :   for(unsigned int i=0; i<args.size(); i++) {
     403       52930 :     ofile_values.printField("arg",args[i]);
     404       52930 :     ofile_derivs.printField("arg",args[i]);
     405      901292 :     for(unsigned int k=0; k<getNumberOfBasisFunctions(); k++) {
     406     1696724 :       ofile_values.printField(getBasisFunctionLabel(k),values[i][k]);
     407     1696724 :       ofile_derivs.printField("d_"+getBasisFunctionLabel(k),derivs[i][k]);
     408             :     }
     409       26465 :     ofile_values.printField();
     410       26465 :     ofile_derivs.printField();
     411             :   }
     412          83 :   ofile_values.fmtField();
     413          83 :   ofile_derivs.fmtField();
     414             : 
     415         166 :   delete value_pntr[0]; value_pntr.clear();
     416             : 
     417          83 : }
     418             : 
     419             : 
     420          83 : std::vector<std::vector<double> > BasisFunctions::getAllInnerProducts() const {
     421             :   // setup temp grid
     422         166 :   std::vector<std::string> grid_min(1); grid_min[0]=intervalMinStr();
     423         249 :   std::vector<std::string> grid_max(1); grid_max[0]=intervalMaxStr();
     424         166 :   std::vector<unsigned int> grid_bins(1); grid_bins[0]=nbins_;
     425         249 :   std::vector<Value*> arguments(1); arguments[0]= new Value(NULL,"arg",false);
     426         146 :   if(arePeriodic()) {arguments[0]->setDomain(intervalMinStr(),intervalMaxStr());}
     427          62 :   else {arguments[0]->setNotPeriodic();}
     428         166 :   Grid* grid = new Grid("uniform",arguments,grid_min,grid_max,grid_bins,false,false);
     429       83228 :   for(Grid::index_t l=0; l<grid->getSize(); l++) {
     430       83145 :     grid->setValue(l,1.0);
     431             :   }
     432             :   //
     433          83 :   std::vector<std::vector<double> > inner_products = getAllInnerProducts(grid);
     434          83 :   delete grid;
     435          83 :   return inner_products;
     436             :   //
     437             : }
     438             : 
     439             : 
     440          83 : std::vector<std::vector<double> > BasisFunctions::getAllInnerProducts(const Grid* grid_pntr) const {
     441             : 
     442         249 :   std::vector<std::vector<double> > inner_products(numberOfBasisFunctions(), std::vector<double>(numberOfBasisFunctions()));
     443        2828 :   for(unsigned int i=0; i<numberOfBasisFunctions(); i++) {
     444       28323 :     for(unsigned int j=i; j<numberOfBasisFunctions(); j++) {
     445       26992 :       inner_products[i][j] = inner_products[j][i] = getInnerProduct(i,j,grid_pntr);
     446             :     }
     447             :   }
     448          83 :   return inner_products;
     449             : }
     450             : 
     451             : 
     452       13496 : double BasisFunctions::getInnerProduct(const unsigned int n, const unsigned int m, const Grid* grid_pntr) const {
     453       13496 :   plumed_massert(grid_pntr->getDimension()==1,"the grid must be one-dimensional");
     454       40488 :   std::vector<double> integration_weights = GridIntegrationWeights::getIntegrationWeights(grid_pntr);
     455             :   double sum = 0.0;
     456    13534023 :   for(Grid::index_t k=0; k < grid_pntr->getSize(); k++) {
     457    40561581 :     double arg = grid_pntr->getPoint(k)[0];
     458             :     double argT;
     459    13520527 :     bool inside_range=true;
     460    13520527 :     std::vector<double> values(numberOfBasisFunctions());
     461    13520527 :     std::vector<double> derivs(numberOfBasisFunctions());
     462    13520527 :     getAllValues(arg, argT, inside_range, values, derivs);
     463    13520527 :     plumed_massert(inside_range,"the basis functions values must be inside the range of the defined interval!");
     464             :     //
     465    40561581 :     sum += integration_weights[k]*values[n]*values[m];
     466             :     // disable weight for the moment
     467             :     // sum += integration_weights[k]*values[n]*values[m]*getInnerProductWeight(arg);
     468             :     //
     469             :   }
     470       13496 :   return sum;
     471             : }
     472             : 
     473             : 
     474          83 : void BasisFunctions::writeInnerProductsToFiles(OFile& ofile, const std::string& output_fmt) const {
     475             : 
     476          83 :   std::string int_fmt = "%8d";
     477          83 :   ofile.fmtField(output_fmt);
     478             : 
     479          83 :   std::string weight = getInnerProductWeightStr();
     480             : 
     481         166 :   std::vector<std::vector<double> > inner_products = getAllInnerProducts();
     482          83 :   char* s1 = new char[20];
     483             : 
     484             :   // diagonal part
     485          83 :   ofile.printf("#! Diagonal Part\n");
     486         249 :   ofile.addConstantField("weight").printField("weight",weight);
     487        2828 :   for(unsigned int i=0; i<numberOfBasisFunctions(); i++) {
     488        3993 :     sprintf(s1,int_fmt.c_str(),i); ofile.printField("i",s1);
     489        3993 :     sprintf(s1,int_fmt.c_str(),i); ofile.printField("j",s1);
     490        3993 :     ofile.printField("inner_product",inner_products[i][i]);
     491        1331 :     ofile.printField();
     492             :   }
     493             : 
     494          83 :   ofile.clearFields();
     495             :   // off-diagonal part
     496          83 :   ofile.printf("#! Off-Diagonal Part\n");
     497         249 :   ofile.addConstantField("weight").printField("weight",weight);
     498        1497 :   for(unsigned int i=0; i<numberOfBasisFunctions(); i++) {
     499       26992 :     for(unsigned int j=i+1; j<numberOfBasisFunctions(); j++) {
     500       36495 :       sprintf(s1,int_fmt.c_str(),i); ofile.printField("i",s1);
     501       36495 :       sprintf(s1,int_fmt.c_str(),j); ofile.printField("j",s1);
     502       36495 :       ofile.printField("inner_product",inner_products[i][j]);
     503       12165 :       ofile.printField();
     504             :     }
     505             :   }
     506          83 : }
     507             : 
     508             : 
     509             : 
     510             : }
     511             : }

Generated by: LCOV version 1.14