LCOV - code coverage report
Current view: top level - ves - Optimizer.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 671 777 86.4 %
Date: 2019-08-13 10:39:37 Functions: 28 34 82.4 %

          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 "Optimizer.h"
      24             : #include "CoeffsVector.h"
      25             : #include "CoeffsMatrix.h"
      26             : #include "VesBias.h"
      27             : #include "VesTools.h"
      28             : 
      29             : #include "tools/Exception.h"
      30             : #include "core/PlumedMain.h"
      31             : #include "core/ActionSet.h"
      32             : #include "tools/Communicator.h"
      33             : #include "tools/File.h"
      34             : #include "tools/FileBase.h"
      35             : 
      36             : namespace PLMD {
      37             : namespace ves {
      38             : 
      39          70 : Optimizer::Optimizer(const ActionOptions&ao):
      40             :   Action(ao),
      41             :   ActionPilot(ao),
      42             :   ActionWithValue(ao),
      43             :   description_("Undefined"),
      44             :   type_("Undefined"),
      45             :   stepsizes_(0),
      46             :   current_stepsizes(0),
      47             :   fixed_stepsize_(true),
      48             :   iter_counter(0),
      49             :   use_hessian_(false),
      50             :   diagonal_hessian_(true),
      51             :   monitor_instantaneous_gradient_(false),
      52             :   use_mwalkers_mpi_(false),
      53             :   mwalkers_mpi_single_files_(true),
      54             :   dynamic_targetdists_(0),
      55             :   ustride_targetdist_(0),
      56             :   ustride_reweightfactor_(0),
      57             :   coeffssetid_prefix_(""),
      58             :   coeffs_wstride_(100),
      59             :   coeffsOFiles_(0),
      60             :   coeffs_output_fmt_(""),
      61             :   gradient_wstride_(100),
      62             :   gradientOFiles_(0),
      63             :   gradient_output_fmt_(""),
      64             :   hessian_wstride_(100),
      65             :   hessianOFiles_(0),
      66             :   hessian_output_fmt_(""),
      67             :   targetdist_averages_wstride_(0),
      68             :   targetdist_averagesOFiles_(0),
      69             :   targetdist_averages_output_fmt_(""),
      70             :   nbiases_(0),
      71             :   bias_pntrs_(0),
      72             :   ncoeffssets_(0),
      73             :   coeffs_pntrs_(0),
      74             :   aux_coeffs_pntrs_(0),
      75             :   gradient_pntrs_(0),
      76             :   aver_gradient_pntrs_(0),
      77             :   hessian_pntrs_(0),
      78             :   coeffs_mask_pntrs_(0),
      79             :   targetdist_averages_pntrs_(0),
      80             :   identical_coeffs_shape_(true),
      81             :   bias_output_active_(false),
      82             :   bias_output_stride_(0),
      83             :   fes_output_active_(false),
      84             :   fes_output_stride_(0),
      85             :   fesproj_output_active_(false),
      86             :   fesproj_output_stride_(0),
      87             :   targetdist_output_active_(false),
      88             :   targetdist_output_stride_(0),
      89             :   targetdist_proj_output_active_(false),
      90             :   targetdist_proj_output_stride_(0),
      91          70 :   isFirstStep(true)
      92             : {
      93          70 :   std::vector<std::string> bias_labels(0);
      94          70 :   parseVector("BIAS",bias_labels);
      95          70 :   plumed_massert(bias_labels.size()>0,"problem with BIAS keyword");
      96          70 :   nbiases_ = bias_labels.size();
      97             :   //
      98         140 :   std::string error_msg = "";
      99          70 :   bias_pntrs_ = VesTools::getPointersFromLabels<VesBias*>(bias_labels,plumed.getActionSet(),error_msg);
     100          70 :   if(error_msg.size()>0) {plumed_merror("Error in keyword BIAS of "+getName()+": "+error_msg);}
     101             : 
     102         146 :   for(unsigned int i=0; i<bias_pntrs_.size(); i++) {
     103          76 :     bias_pntrs_[i]->linkOptimizer(this);
     104             :     //
     105          76 :     std::vector<CoeffsVector*> pntrs_coeffs = bias_pntrs_[i]->getCoeffsPntrs();
     106         152 :     std::vector<CoeffsVector*> pntrs_gradient = bias_pntrs_[i]->getGradientPntrs();
     107         152 :     std::vector<CoeffsVector*> pntrs_targetdist_averages = bias_pntrs_[i]->getTargetDistAveragesPntrs();
     108          76 :     plumed_massert(pntrs_coeffs.size()==pntrs_gradient.size(),"something wrong in the coefficients and gradient passed from VES bias");
     109          76 :     plumed_massert(pntrs_coeffs.size()==pntrs_targetdist_averages.size(),"something wrong in the coefficients and target distribution averages passed from VES bias");
     110         152 :     for(unsigned int k=0; k<pntrs_coeffs.size(); k++) {
     111          76 :       plumed_massert(pntrs_coeffs[k] != NULL,"some coefficient is not linked correctly");
     112          76 :       plumed_massert(pntrs_gradient[k] != NULL,"some gradient is not linked correctly");
     113          76 :       plumed_massert(pntrs_targetdist_averages[k] != NULL,"some target distribution average is not linked correctly");
     114          76 :       pntrs_coeffs[k]->turnOnIterationCounter();
     115          76 :       coeffs_pntrs_.push_back(pntrs_coeffs[k]);
     116          76 :       pntrs_gradient[k]->turnOnIterationCounter();
     117          76 :       gradient_pntrs_.push_back(pntrs_gradient[k]);
     118          76 :       pntrs_targetdist_averages[k]->turnOnIterationCounter();
     119          76 :       targetdist_averages_pntrs_.push_back(pntrs_targetdist_averages[k]);
     120             :       //
     121          76 :       CoeffsVector* aux_coeffs_tmp = new CoeffsVector(*pntrs_coeffs[k]);
     122          76 :       std::string aux_label = pntrs_coeffs[k]->getLabel();
     123          76 :       if(aux_label.find("coeffs")!=std::string::npos) {
     124          76 :         aux_label.replace(aux_label.find("coeffs"), std::string("coeffs").length(), "aux_coeffs");
     125             :       }
     126             :       else {
     127           0 :         aux_label += "_aux";
     128             :       }
     129          76 :       aux_coeffs_tmp->setLabels(aux_label);
     130          76 :       aux_coeffs_pntrs_.push_back(aux_coeffs_tmp);
     131          76 :       AuxCoeffs(i).setValues( Coeffs(i) );
     132          76 :     }
     133          76 :   }
     134          70 :   ncoeffssets_ = coeffs_pntrs_.size();
     135          70 :   plumed_massert(aux_coeffs_pntrs_.size()==ncoeffssets_,"problems in linking aux coefficients");
     136          70 :   plumed_massert(gradient_pntrs_.size()==ncoeffssets_,"problems in linking gradients");
     137          70 :   setAllCoeffsSetIterationCounters();
     138             : 
     139             : 
     140             :   //
     141          70 :   identical_coeffs_shape_ = true;
     142          76 :   for(unsigned int i=1; i<ncoeffssets_; i++) {
     143           6 :     if(!coeffs_pntrs_[0]->sameShape(*coeffs_pntrs_[i])) {
     144           0 :       identical_coeffs_shape_ = false;
     145           0 :       break;
     146             :     }
     147             :   }
     148             :   //
     149          70 :   if(keywords.exists("STEPSIZE")) {
     150          69 :     plumed_assert(!keywords.exists("INITIAL_STEPSIZE"));
     151          69 :     fixed_stepsize_=true;
     152          69 :     parseMultipleValues("STEPSIZE",stepsizes_);
     153          69 :     setCurrentStepSizes(stepsizes_);
     154             :   }
     155          70 :   if(keywords.exists("INITIAL_STEPSIZE")) {
     156           0 :     plumed_assert(!keywords.exists("STEPSIZE"));
     157           0 :     fixed_stepsize_=false;
     158           0 :     parseMultipleValues("INITIAL_STEPSIZE",stepsizes_);
     159           0 :     setCurrentStepSizes(stepsizes_);
     160             :   }
     161             :   //
     162          70 :   if(ncoeffssets_==1) {
     163          67 :     log.printf("  optimizing VES bias %s with label %s: \n",bias_pntrs_[0]->getName().c_str(),bias_pntrs_[0]->getLabel().c_str());
     164          67 :     log.printf("   KbT: %f\n",bias_pntrs_[0]->getKbT());
     165          67 :     log.printf("  number of coefficients: %zu\n",coeffs_pntrs_[0]->numberOfCoeffs());
     166          67 :     if(stepsizes_.size()>0) {
     167          66 :       if(fixed_stepsize_) {log.printf("  using a constant step size of %f\n",stepsizes_[0]);}
     168           0 :       else {log.printf("  using an initial step size of %f\n",stepsizes_[0]);}
     169             :     }
     170             :   }
     171             :   else {
     172           3 :     log.printf("  optimizing %u coefficent sets from following %u VES biases:\n",ncoeffssets_,nbiases_);
     173          12 :     for(unsigned int i=0; i<nbiases_; i++) {
     174           9 :       log.printf("   %s of type %s (KbT: %f) \n",bias_pntrs_[i]->getLabel().c_str(),bias_pntrs_[i]->getName().c_str(),bias_pntrs_[i]->getKbT());
     175             :     }
     176           3 :     size_t tot_ncoeffs = 0;
     177          12 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
     178           9 :       log.printf("  coefficient set %u: \n",i);
     179           9 :       log.printf("   used in bias %s (type %s)\n",coeffs_pntrs_[i]->getPntrToAction()->getLabel().c_str(),coeffs_pntrs_[i]->getPntrToAction()->getName().c_str());
     180           9 :       log.printf("   number of coefficients: %zu\n",coeffs_pntrs_[i]->numberOfCoeffs());
     181           9 :       if(stepsizes_.size()>0) {
     182           9 :         if(fixed_stepsize_) {log.printf("   using a constant step size of %f\n",stepsizes_[i]);}
     183           0 :         else {log.printf("   using an initial step size of %f\n",stepsizes_[i]);}
     184             :       }
     185           9 :       tot_ncoeffs += coeffs_pntrs_[i]->numberOfCoeffs();
     186             :     }
     187           3 :     log.printf("  total number of coefficients: %zu\n",tot_ncoeffs);
     188           3 :     if(identical_coeffs_shape_) {
     189           3 :       log.printf("  the indices shape is identical for all coefficient sets\n");
     190             :     }
     191             :     else {
     192           0 :       log.printf("  the indices shape differs between coefficient sets\n");
     193             :     }
     194             :   }
     195             : 
     196             :   //
     197          70 :   if(keywords.exists("FULL_HESSIAN")) {
     198           0 :     bool full_hessian=false;
     199           0 :     parseFlag("FULL_HESSIAN",full_hessian);
     200           0 :     diagonal_hessian_ = !full_hessian;
     201             :   }
     202             :   //
     203          70 :   bool mw_single_files = false;
     204          70 :   if(keywords.exists("MULTIPLE_WALKERS")) {
     205          70 :     parseFlag("MULTIPLE_WALKERS",use_mwalkers_mpi_);
     206          70 :     if(use_mwalkers_mpi_) {
     207          12 :       mw_single_files=true;
     208             :     }
     209             :   }
     210             : 
     211          70 :   int numwalkers=1;
     212          70 :   int walker_rank=0;
     213          70 :   if(comm.Get_rank()==0) {
     214          61 :     numwalkers = multi_sim_comm.Get_size();
     215          61 :     walker_rank = multi_sim_comm.Get_rank();
     216             :   }
     217          70 :   comm.Bcast(numwalkers,0);
     218          70 :   comm.Bcast(walker_rank,0);
     219          70 :   if(use_mwalkers_mpi_ && numwalkers==1) {
     220           0 :     plumed_merror("using the MULTIPLE_WALKERS keyword does not make sense if running the MD code with a single replica");
     221             :   }
     222          70 :   if(use_mwalkers_mpi_) {
     223          12 :     log.printf("  optimization performed using multiple walkers connected via MPI:\n");
     224          12 :     log.printf("   number of walkers: %d\n",numwalkers);
     225          12 :     log.printf("   walker number: %d\n",walker_rank);
     226          12 :     log.printf("   please see and cite ");
     227          12 :     log << plumed.cite("Raiteri, Laio, Gervasio, Micheletti, and Parrinello, J. Phys. Chem. B 110, 3533 (2006)");
     228          12 :     log.printf("\n");
     229             :   }
     230             : 
     231          70 :   dynamic_targetdists_.resize(nbiases_,false);
     232          70 :   if(keywords.exists("TARGETDIST_STRIDE")) {
     233          69 :     bool need_stride = false;
     234         144 :     for(unsigned int i=0; i<nbiases_; i++) {
     235          75 :       dynamic_targetdists_[i] = bias_pntrs_[i]->dynamicTargetDistribution();
     236          75 :       if(dynamic_targetdists_[i]) {need_stride = true;}
     237             :     }
     238          69 :     parse("TARGETDIST_STRIDE",ustride_targetdist_);
     239          69 :     if(need_stride && ustride_targetdist_==0) {
     240           0 :       plumed_merror("one of the biases has a dynamic target distribution so you need to give stride for updating it by using the TARGETDIST_STRIDE keyword");
     241             :     }
     242          69 :     if(!need_stride && ustride_targetdist_!=0) {
     243           0 :       plumed_merror("using the TARGETDIST_STRIDE keyword doesn't make sense as there is no dynamic target distribution to update");
     244             :     }
     245          69 :     if(ustride_targetdist_>0) {
     246          32 :       if(nbiases_==1) {
     247          32 :         log.printf("  the target distribution will be updated very %u coefficent iterations\n",ustride_targetdist_);
     248             :       }
     249             :       else {
     250           0 :         log.printf("  the target distribution will be updated very %u coefficent iterations for the following biases\n   ",ustride_targetdist_);
     251           0 :         for(unsigned int i=0; i<nbiases_; i++) {
     252           0 :           log.printf("%s ",bias_pntrs_[i]->getLabel().c_str());
     253             :         }
     254           0 :         log.printf("\n");
     255             :       }
     256          32 :       log.printf("  See and cite ");
     257          32 :       log << plumed.cite("Valsson and Parrinello, J. Chem. Theory Comput. 11, 1996-2002 (2015)");
     258          32 :       log.printf("\n");
     259             :     }
     260             :   }
     261             : 
     262          70 :   if(keywords.exists("REWEIGHT_FACTOR_STRIDE")) {
     263           0 :     bool reweightfactor_calculated = false;
     264           0 :     for(unsigned int i=0; i<nbiases_; i++) {
     265           0 :       reweightfactor_calculated = bias_pntrs_[i]->isReweightFactorCalculated();
     266             :     }
     267           0 :     parse("REWEIGHT_FACTOR_STRIDE",ustride_reweightfactor_);
     268           0 :     if(ustride_reweightfactor_==0 && reweightfactor_calculated) {
     269           0 :       plumed_merror("the calculation of the reweight factor is enabled, You need to use the REWEIGHT_FACTOR_STRIDE keyword to specfiy how often it should be updated.");
     270             :     }
     271           0 :     if(ustride_reweightfactor_>0) {
     272           0 :       if(!reweightfactor_calculated) {
     273           0 :         plumed_merror("In order to use the REWEIGHT_FACTOR_STRIDE keyword you need to enable the calculation of the reweight factor in the VES bias by using the CALC_REWEIGHT_FACTOR flag.");
     274             :       }
     275           0 :       log.printf("  the reweight factor c(t) will be updated very %u coefficent iterations\n",ustride_reweightfactor_);
     276             :     }
     277             :   }
     278             : 
     279          70 :   if(keywords.exists("MONITOR_INSTANTANEOUS_GRADIENT")) {
     280          70 :     parseFlag("MONITOR_INSTANTANEOUS_GRADIENT",monitor_instantaneous_gradient_);
     281             :   }
     282             : 
     283          70 :   if(keywords.exists("MONITOR_AVERAGE_GRADIENT")) {
     284          70 :     bool monitor_aver_gradient = false;
     285          70 :     parseFlag("MONITOR_AVERAGE_GRADIENT",monitor_aver_gradient);
     286          70 :     if(monitor_aver_gradient) {
     287           2 :       unsigned int averaging_exp_decay=0;
     288           2 :       parse("MONITOR_AVERAGES_GRADIENT_EXP_DECAY",averaging_exp_decay);
     289           2 :       aver_gradient_pntrs_.clear();
     290           4 :       for(unsigned int i=0; i<ncoeffssets_; i++) {
     291           2 :         CoeffsVector* aver_gradient_tmp = new CoeffsVector(*gradient_pntrs_[i]);
     292           2 :         aver_gradient_tmp->clear();
     293           2 :         std::string aver_grad_label = aver_gradient_tmp->getLabel();
     294           2 :         if(aver_grad_label.find("gradient")!=std::string::npos) {
     295           2 :           aver_grad_label.replace(aver_grad_label.find("gradient"), std::string("gradient").length(), "aver_gradient");
     296             :         }
     297             :         else {
     298           0 :           aver_grad_label += "_aver";
     299             :         }
     300           2 :         aver_gradient_tmp->setLabels(aver_grad_label);
     301           2 :         if(averaging_exp_decay>0) {
     302           1 :           aver_gradient_tmp->setupExponentiallyDecayingAveraging(averaging_exp_decay);
     303             :         }
     304           2 :         aver_gradient_pntrs_.push_back(aver_gradient_tmp);
     305           2 :       }
     306             :     }
     307             :   }
     308             : 
     309             : 
     310          70 :   if(ncoeffssets_>1) {
     311           3 :     coeffssetid_prefix_="c-";
     312           3 :     if(keywords.exists("COEFFS_SET_ID_PREFIX")) {
     313           3 :       parse("COEFFS_SET_ID_PREFIX",coeffssetid_prefix_);
     314             :     }
     315             :   }
     316             :   else {
     317          67 :     coeffssetid_prefix_="";
     318          67 :     if(keywords.exists("COEFFS_SET_ID_PREFIX")) {
     319          67 :       parse("COEFFS_SET_ID_PREFIX",coeffssetid_prefix_);
     320             :     }
     321          67 :     if(coeffssetid_prefix_.size()>0) {
     322           0 :       plumed_merror("COEFFS_SET_ID_PREFIX should only be given if optimizing multiple coefficent sets");
     323             :     }
     324             :   }
     325             : 
     326          70 :   if(keywords.exists("INITIAL_COEFFS")) {
     327          70 :     std::vector<std::string> initial_coeffs_fnames;
     328          70 :     parseFilenames("INITIAL_COEFFS",initial_coeffs_fnames);
     329          70 :     if(initial_coeffs_fnames.size()>0) {
     330           1 :       readCoeffsFromFiles(initial_coeffs_fnames,false);
     331           1 :       comm.Barrier();
     332           1 :       if(comm.Get_rank()==0 && use_mwalkers_mpi_) {
     333           0 :         multi_sim_comm.Barrier();
     334             :       }
     335           1 :       setAllCoeffsSetIterationCounters();
     336          70 :     }
     337             :   }
     338             :   //
     339             : 
     340         140 :   std::vector<std::string> coeffs_fnames;
     341          70 :   if(keywords.exists("COEFFS_FILE")) {
     342          70 :     parseFilenames("COEFFS_FILE",coeffs_fnames,"coeffs.data");
     343          70 :     bool start_opt_afresh=false;
     344          70 :     if(keywords.exists("START_OPTIMIZATION_AFRESH")) {
     345          69 :       parseFlag("START_OPTIMIZATION_AFRESH",start_opt_afresh);
     346          69 :       if(start_opt_afresh && !getRestart()) {
     347           0 :         plumed_merror("the START_OPTIMIZATION_AFRESH keyword should only be used when a restart has been triggered by the RESTART keyword or the MD code");
     348             :       }
     349             :     }
     350          70 :     if(getRestart()) {
     351          28 :       for(unsigned int i=0; i<coeffs_fnames.size(); i++) {
     352          15 :         IFile ifile;
     353          15 :         ifile.link(*this);
     354          15 :         if(use_mwalkers_mpi_) {ifile.enforceSuffix("");}
     355          15 :         bool file_exist = ifile.FileExist(coeffs_fnames[i]);
     356          15 :         if(!file_exist) {
     357           0 :           std::string fname = FileBase::appendSuffix(coeffs_fnames[i],ifile.getSuffix());
     358           0 :           plumed_merror("Cannot find coefficient file " + fname + " when trying to restart an optimzation. If you don't want to restart the optimzation please remove the RESTART keyword or use the RESTART=NO within the "+getName()+" action to locally disable the restart.");
     359             :         }
     360          15 :       }
     361          13 :       readCoeffsFromFiles(coeffs_fnames,true);
     362          13 :       comm.Barrier();
     363          13 :       if(comm.Get_rank()==0 && use_mwalkers_mpi_) {
     364           4 :         multi_sim_comm.Barrier();
     365             :       }
     366          13 :       unsigned int iter_opt_tmp = coeffs_pntrs_[0]->getIterationCounter();
     367          15 :       for(unsigned int i=1; i<ncoeffssets_; i++) {
     368           2 :         plumed_massert(coeffs_pntrs_[i]->getIterationCounter()==iter_opt_tmp,"the iteraton counter should be the same for all files when restarting from previous coefficient files\n");
     369             :       }
     370          13 :       if(start_opt_afresh) {
     371           1 :         setIterationCounter(0);
     372           1 :         log.printf("  Optimization started afresh at iteration %u\n",getIterationCounter());
     373           2 :         for(unsigned int i=0; i<ncoeffssets_; i++) {
     374           1 :           AuxCoeffs(i).setValues( Coeffs(i) );
     375             :         }
     376             :       }
     377             :       else {
     378          12 :         setIterationCounter(coeffs_pntrs_[0]->getIterationCounter());
     379          12 :         log.printf("  Optimization restarted at iteration %u\n",getIterationCounter());
     380             :       }
     381          13 :       setAllCoeffsSetIterationCounters();
     382             :     }
     383             : 
     384          70 :     std::string coeffs_wstride_tmpstr="";
     385          70 :     parse("COEFFS_OUTPUT",coeffs_wstride_tmpstr);
     386          70 :     if(coeffs_wstride_tmpstr!="OFF" && coeffs_wstride_tmpstr.size()>0) {
     387          70 :       Tools::convert(coeffs_wstride_tmpstr,coeffs_wstride_);
     388             :     }
     389          70 :     if(coeffs_wstride_tmpstr=="OFF") {
     390           0 :       coeffs_fnames.clear();
     391             :     }
     392          70 :     setupOFiles(coeffs_fnames,coeffsOFiles_,mw_single_files);
     393          70 :     parse("COEFFS_FMT",coeffs_output_fmt_);
     394          70 :     if(coeffs_output_fmt_.size()>0) {
     395         144 :       for(unsigned int i=0; i<ncoeffssets_; i++) {
     396          75 :         coeffs_pntrs_[i]->setOutputFmt(coeffs_output_fmt_);
     397             :       }
     398             :     }
     399          70 :     if(!getRestart()) {
     400         118 :       for(unsigned int i=0; i<coeffsOFiles_.size(); i++) {
     401          61 :         coeffs_pntrs_[i]->writeToFile(*coeffsOFiles_[i],aux_coeffs_pntrs_[i],false);
     402             :       }
     403             :     }
     404          70 :     if(coeffs_fnames.size()>0) {
     405          70 :       if(ncoeffssets_==1) {
     406          67 :         log.printf("  Coefficients will be written out to file %s every %u iterations\n",coeffsOFiles_[0]->getPath().c_str(),coeffs_wstride_);
     407             :       }
     408             :       else {
     409           3 :         log.printf("  Coefficients will be written out to the following files every %u iterations:\n",coeffs_wstride_);
     410          12 :         for(unsigned int i=0; i<coeffs_fnames.size(); i++) {
     411           9 :           log.printf("   coefficient set %u: %s\n",i,coeffsOFiles_[i]->getPath().c_str());
     412             :         }
     413             :       }
     414             :     }
     415             :     else {
     416           0 :       log.printf("  Output of coefficients to file has been disabled\n");
     417          70 :     }
     418             :   }
     419             : 
     420         140 :   std::vector<std::string> gradient_fnames;
     421          70 :   if(keywords.exists("GRADIENT_FILE")) {
     422          70 :     parseFilenames("GRADIENT_FILE",gradient_fnames);
     423          70 :     parse("GRADIENT_OUTPUT",gradient_wstride_);
     424             : 
     425          70 :     if(coeffs_fnames.size()>0) {
     426         140 :       for(unsigned int i=0; i<gradient_fnames.size(); i++) {
     427          70 :         plumed_massert(gradient_fnames[i]!=coeffs_fnames[i],"COEFFS_FILE and GRADIENT_FILE cannot be the same");
     428             :       }
     429             :     }
     430          70 :     setupOFiles(gradient_fnames,gradientOFiles_,mw_single_files);
     431          70 :     parse("GRADIENT_FMT",gradient_output_fmt_);
     432          70 :     if(gradient_output_fmt_.size()>0) {
     433         134 :       for(unsigned int i=0; i<ncoeffssets_; i++) {
     434          70 :         gradient_pntrs_[i]->setOutputFmt(gradient_output_fmt_);
     435             :       }
     436             :     }
     437             : 
     438          70 :     if(gradient_fnames.size()>0) {
     439          64 :       if(ncoeffssets_==1) {
     440          61 :         log.printf("  Gradient will be written out to file %s every %u iterations\n",gradientOFiles_[0]->getPath().c_str(),gradient_wstride_);
     441             :       }
     442             :       else {
     443           3 :         log.printf("  Gradient will be written out to the following files every %u iterations:\n",gradient_wstride_);
     444          12 :         for(unsigned int i=0; i<gradient_fnames.size(); i++) {
     445           9 :           log.printf("   coefficient set %u: %s\n",i,gradientOFiles_[i]->getPath().c_str());
     446             :         }
     447             :       }
     448             :     }
     449             :   }
     450             : 
     451         140 :   std::vector<std::string> hessian_fnames;
     452          70 :   if(keywords.exists("HESSIAN_FILE")) {
     453          70 :     parseFilenames("HESSIAN_FILE",hessian_fnames);
     454          70 :     parse("HESSIAN_OUTPUT",hessian_wstride_);
     455             : 
     456          70 :     if(coeffs_fnames.size()>0) {
     457         135 :       for(unsigned int i=0; i<hessian_fnames.size(); i++) {
     458          65 :         plumed_massert(hessian_fnames[i]!=coeffs_fnames[i],"COEFFS_FILE and HESSIAN_FILE cannot be the same");
     459             :       }
     460             :     }
     461          70 :     if(gradient_fnames.size()>0) {
     462         129 :       for(unsigned int i=0; i<hessian_fnames.size(); i++) {
     463          65 :         plumed_massert(hessian_fnames[i]!=gradient_fnames[i],"GRADIENT_FILE and HESSIAN_FILE cannot be the same");
     464             :       }
     465             :     }
     466          70 :     setupOFiles(hessian_fnames,hessianOFiles_,mw_single_files);
     467          70 :     parse("HESSIAN_FMT",hessian_output_fmt_);
     468             : 
     469          70 :     if(hessian_fnames.size()>0) {
     470          61 :       if(ncoeffssets_==1) {
     471          59 :         log.printf("  Hessian will be written out to file %s every %u iterations\n",hessianOFiles_[0]->getPath().c_str(),hessian_wstride_);
     472             :       }
     473             :       else {
     474           2 :         log.printf("  Hessian will be written out to the following files every %u iterations:\n",hessian_wstride_);
     475           8 :         for(unsigned int i=0; i<hessian_fnames.size(); i++) {
     476           6 :           log.printf("   coefficient set %u: %s\n",i,hessianOFiles_[i]->getPath().c_str());
     477             :         }
     478             :       }
     479             :     }
     480             :   }
     481             : 
     482             : 
     483             :   //
     484          70 :   if(keywords.exists("MASK_FILE")) {
     485          69 :     std::vector<std::string> mask_fnames_in;
     486          69 :     parseVector("MASK_FILE",mask_fnames_in);
     487          69 :     if(mask_fnames_in.size()==1 && ncoeffssets_>1) {
     488           0 :       if(identical_coeffs_shape_) {mask_fnames_in.resize(ncoeffssets_,mask_fnames_in[0]);}
     489           0 :       else {plumed_merror("the coefficients indices shape differs between biases so you need to give a separate file for each coefficient set\n");}
     490             :     }
     491          69 :     if(mask_fnames_in.size()>0 && mask_fnames_in.size()!=ncoeffssets_) {
     492           0 :       plumed_merror("Error in MASK_FILE keyword: either give one value for all biases or a separate value for each coefficient set");
     493             :     }
     494             : 
     495          69 :     coeffs_mask_pntrs_.resize(ncoeffssets_);
     496         144 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
     497          75 :       coeffs_mask_pntrs_[i] = new CoeffsVector(*coeffs_pntrs_[i]);
     498          75 :       coeffs_mask_pntrs_[i]->setLabels("mask");
     499          75 :       coeffs_mask_pntrs_[i]->setValues(1.0);
     500          75 :       coeffs_mask_pntrs_[i]->setOutputFmt("%f");
     501             :     }
     502             : 
     503          69 :     if(mask_fnames_in.size()>0) {
     504           1 :       if(ncoeffssets_==1) {
     505           1 :         size_t nread = coeffs_mask_pntrs_[0]->readFromFile(mask_fnames_in[0],true,true);
     506           1 :         log.printf("  read %zu values from mask file %s\n",nread,mask_fnames_in[0].c_str());
     507           1 :         size_t ndeactived = coeffs_mask_pntrs_[0]->countValues(0.0);
     508           1 :         log.printf("  deactived optimization of %zu coefficients\n",ndeactived);
     509             :       }
     510             :       else {
     511           0 :         for(unsigned int i=0; i<ncoeffssets_; i++) {
     512           0 :           size_t nread = coeffs_mask_pntrs_[i]->readFromFile(mask_fnames_in[i],true,true);
     513           0 :           log.printf("  mask for coefficent set %u:\n",i);
     514           0 :           log.printf("   read %zu values from file %s\n",nread,mask_fnames_in[i].c_str());
     515           0 :           size_t ndeactived = coeffs_mask_pntrs_[0]->countValues(0.0);
     516           0 :           log.printf("   deactived optimization of %zu coefficients\n",ndeactived);
     517             :         }
     518             :       }
     519             :     }
     520             : 
     521         138 :     std::vector<std::string> mask_fnames_out;
     522          69 :     parseFilenames("OUTPUT_MASK_FILE",mask_fnames_out);
     523             : 
     524          70 :     for(unsigned int i=0; i<mask_fnames_out.size(); i++) {
     525           1 :       if(mask_fnames_in.size()>0) {
     526           1 :         plumed_massert(mask_fnames_out[i]!=mask_fnames_in[i],"MASK_FILE and OUTPUT_MASK_FILE cannot be the same");
     527             :       }
     528           1 :       OFile maskOFile;
     529           1 :       maskOFile.link(*this);
     530           1 :       maskOFile.enforceBackup();
     531           1 :       if(use_mwalkers_mpi_ && mwalkers_mpi_single_files_) {
     532           0 :         unsigned int r=0;
     533           0 :         if(comm.Get_rank()==0) {r=multi_sim_comm.Get_rank();}
     534           0 :         comm.Bcast(r,0);
     535           0 :         if(r>0) {mask_fnames_out[i]="/dev/null";}
     536           0 :         maskOFile.enforceSuffix("");
     537             :       }
     538           1 :       maskOFile.open(mask_fnames_out[i]);
     539           1 :       coeffs_mask_pntrs_[i]->writeToFile(maskOFile,true);
     540           1 :       maskOFile.close();
     541          70 :     }
     542             :   }
     543             : 
     544          70 :   if(getRestart() && ustride_targetdist_>0) {
     545          16 :     for(unsigned int i=0; i<nbiases_; i++) {
     546           8 :       if(dynamic_targetdists_[i]) {
     547           8 :         bias_pntrs_[i]->restartTargetDistributions();
     548             :       }
     549             :     }
     550             :   }
     551             : 
     552             : 
     553         140 :   std::vector<std::string> targetdist_averages_fnames;
     554          70 :   if(keywords.exists("TARGETDIST_AVERAGES_FILE")) {
     555          70 :     parseFilenames("TARGETDIST_AVERAGES_FILE",targetdist_averages_fnames,"targetdist-averages.data");
     556          70 :     parse("TARGETDIST_AVERAGES_OUTPUT",targetdist_averages_wstride_);
     557             : 
     558          70 :     if(coeffs_fnames.size()>0) {
     559         146 :       for(unsigned int i=0; i<targetdist_averages_fnames.size(); i++) {
     560          76 :         plumed_massert(targetdist_averages_fnames[i]!=coeffs_fnames[i],"COEFFS_FILE and TARGETDIST_AVERAGES_FILE cannot be the same");
     561             :       }
     562             :     }
     563          70 :     if(gradient_fnames.size()>0) {
     564         134 :       for(unsigned int i=0; i<targetdist_averages_fnames.size(); i++) {
     565          70 :         plumed_massert(targetdist_averages_fnames[i]!=gradient_fnames[i],"GRADIENT_FILE and TARGETDIST_AVERAGES_FILE cannot be the same");
     566             :       }
     567             :     }
     568          70 :     if(hessian_fnames.size()>0) {
     569         126 :       for(unsigned int i=0; i<targetdist_averages_fnames.size(); i++) {
     570          65 :         plumed_massert(targetdist_averages_fnames[i]!=hessian_fnames[i],"HESSIAN_FILE and TARGETDIST_AVERAGES_FILE cannot be the same");
     571             :       }
     572             :     }
     573          70 :     setupOFiles(targetdist_averages_fnames,targetdist_averagesOFiles_,mw_single_files);
     574          70 :     parse("TARGETDIST_AVERAGES_FMT",targetdist_averages_output_fmt_);
     575          70 :     if(targetdist_averages_output_fmt_.size()>0) {
     576         146 :       for(unsigned int i=0; i<ncoeffssets_; i++) {
     577          76 :         targetdist_averages_pntrs_[i]->setOutputFmt(targetdist_averages_output_fmt_);
     578             :       }
     579             :     }
     580             : 
     581         146 :     for(unsigned int i=0; i<targetdist_averagesOFiles_.size(); i++) {
     582          76 :       targetdist_averages_pntrs_[i]->writeToFile(*targetdist_averagesOFiles_[i]);
     583             :     }
     584             : 
     585          70 :     if(targetdist_averages_wstride_==0) {
     586          82 :       for(unsigned int i=0; i<targetdist_averagesOFiles_.size(); i++) {
     587          44 :         targetdist_averagesOFiles_[i]->close();
     588          44 :         delete targetdist_averagesOFiles_[i];
     589             :       }
     590          38 :       targetdist_averagesOFiles_.clear();
     591             :     }
     592             : 
     593          70 :     if(targetdist_averages_fnames.size()>0 && targetdist_averages_wstride_ > 0) {
     594          32 :       if(ncoeffssets_==1) {
     595          32 :         log.printf("  Target distribution averages will be written out to file %s every %u iterations\n",targetdist_averagesOFiles_[0]->getPath().c_str(),targetdist_averages_wstride_);
     596             :       }
     597             :       else {
     598           0 :         log.printf("  Target distribution averages will be written out to the following files every %u iterations:\n",targetdist_averages_wstride_);
     599           0 :         for(unsigned int i=0; i<targetdist_averages_fnames.size(); i++) {
     600           0 :           log.printf("   coefficient set %u: %s\n",i,targetdist_averagesOFiles_[i]->getPath().c_str());
     601             :         }
     602             :       }
     603             :     }
     604             :   }
     605             : 
     606             : 
     607          70 :   if(keywords.exists("BIAS_OUTPUT")) {
     608          70 :     parse("BIAS_OUTPUT",bias_output_stride_);
     609          70 :     if(bias_output_stride_>0) {
     610          69 :       bias_output_active_=true;
     611         144 :       for(unsigned int i=0; i<nbiases_; i++) {
     612          75 :         bias_pntrs_[i]->enableBiasFileOutput();
     613          75 :         bias_pntrs_[i]->setupBiasFileOutput();
     614          75 :         bias_pntrs_[i]->writeBiasToFile();
     615             :       }
     616             :     }
     617             :     else {
     618           1 :       bias_output_active_=false;
     619           1 :       bias_output_stride_=1000;
     620             :     }
     621             :   }
     622             : 
     623          70 :   if(keywords.exists("FES_OUTPUT")) {
     624          70 :     parse("FES_OUTPUT",fes_output_stride_);
     625          70 :     if(fes_output_stride_>0) {
     626          69 :       fes_output_active_=true;
     627         144 :       for(unsigned int i=0; i<nbiases_; i++) {
     628          75 :         bias_pntrs_[i]->enableFesFileOutput();
     629          75 :         bias_pntrs_[i]->setupFesFileOutput();
     630          75 :         bias_pntrs_[i]->writeFesToFile();
     631             :       }
     632             :     }
     633             :     else {
     634           1 :       fes_output_active_=false;
     635           1 :       fes_output_stride_=1000;
     636             :     }
     637             :   }
     638             : 
     639          70 :   if(keywords.exists("FES_PROJ_OUTPUT")) {
     640          70 :     parse("FES_PROJ_OUTPUT",fesproj_output_stride_);
     641          70 :     if(fesproj_output_stride_>0) {
     642          15 :       fesproj_output_active_=true;
     643          30 :       for(unsigned int i=0; i<nbiases_; i++) {
     644          15 :         bias_pntrs_[i]->enableFesProjFileOutput();
     645          15 :         bias_pntrs_[i]->setupFesProjFileOutput();
     646          15 :         bias_pntrs_[i]->writeFesProjToFile();
     647             :       }
     648             :     }
     649             :     else {
     650          55 :       fesproj_output_active_=false;
     651          55 :       fesproj_output_stride_=1000;
     652             :     }
     653             :   }
     654             : 
     655         146 :   for(unsigned int i=0; i<nbiases_; i++) {
     656          76 :     if(!dynamic_targetdists_[i] && bias_pntrs_[i]->isStaticTargetDistFileOutputActive()) {
     657           4 :       bias_pntrs_[i]->setupTargetDistFileOutput();
     658           4 :       bias_pntrs_[i]->writeTargetDistToFile();
     659           4 :       bias_pntrs_[i]->setupTargetDistProjFileOutput();
     660           4 :       bias_pntrs_[i]->writeTargetDistProjToFile();
     661             :     }
     662             :   }
     663             : 
     664          70 :   if(keywords.exists("TARGETDIST_OUTPUT")) {
     665          69 :     parse("TARGETDIST_OUTPUT",targetdist_output_stride_);
     666          69 :     if(targetdist_output_stride_>0) {
     667          31 :       if(ustride_targetdist_==0) {
     668           0 :         plumed_merror("it doesn't make sense to use the TARGETDIST_OUTPUT keyword if you don't have a target distribution that needs to be updated");
     669             :       }
     670          31 :       if(targetdist_output_stride_%ustride_targetdist_!=0) {
     671           0 :         plumed_merror("the value given in TARGETDIST_OUTPUT doesn't make sense, it should be multiple of TARGETDIST_STRIDE");
     672             :       }
     673             : 
     674          31 :       targetdist_output_active_=true;
     675          62 :       for(unsigned int i=0; i<nbiases_; i++) {
     676          31 :         if(dynamic_targetdists_[i]) {
     677          31 :           bias_pntrs_[i]->enableDynamicTargetDistFileOutput();
     678          31 :           bias_pntrs_[i]->setupTargetDistFileOutput();
     679          31 :           bias_pntrs_[i]->writeTargetDistToFile();
     680             :         }
     681             :       }
     682             :     }
     683             :     else {
     684          38 :       targetdist_output_active_=false;
     685          38 :       targetdist_output_stride_=1000;
     686             :     }
     687             :   }
     688             : 
     689          70 :   if(keywords.exists("TARGETDIST_PROJ_OUTPUT")) {
     690          69 :     parse("TARGETDIST_PROJ_OUTPUT",targetdist_proj_output_stride_);
     691          69 :     if(targetdist_proj_output_stride_>0) {
     692           2 :       if(ustride_targetdist_==0) {
     693           0 :         plumed_merror("it doesn't make sense to use the TARGETDIST_PROJ_OUTPUT keyword if you don't have a target distribution that needs to be updated");
     694             :       }
     695           2 :       if(targetdist_proj_output_stride_%ustride_targetdist_!=0) {
     696           0 :         plumed_merror("the value given in TARGETDIST_PROJ_OUTPUT doesn't make sense, it should be multiple of TARGETDIST_STRIDE");
     697             :       }
     698             : 
     699           2 :       targetdist_proj_output_active_=true;
     700           4 :       for(unsigned int i=0; i<nbiases_; i++) {
     701           2 :         if(dynamic_targetdists_[i]) {
     702           2 :           bias_pntrs_[i]->enableDynamicTargetDistFileOutput();
     703           2 :           bias_pntrs_[i]->setupTargetDistProjFileOutput();
     704           2 :           bias_pntrs_[i]->writeTargetDistProjToFile();
     705             :         }
     706             :       }
     707             :     }
     708             :     else {
     709          67 :       targetdist_proj_output_active_=false;
     710          67 :       targetdist_proj_output_stride_=1000;
     711             :     }
     712             :   }
     713             : 
     714          70 :   if(ncoeffssets_==1) {
     715          67 :     log.printf("  Output Components:\n");
     716          67 :     log.printf(" ");
     717          67 :     if(monitor_instantaneous_gradient_) {
     718           2 :       addComponent("gradrms"); componentIsNotPeriodic("gradrms");
     719           2 :       log.printf(" ");
     720           2 :       addComponent("gradmax"); componentIsNotPeriodic("gradmax");
     721             :     }
     722          67 :     if(aver_gradient_pntrs_.size()>0) {
     723           2 :       log.printf(" ");
     724           2 :       addComponent("avergradrms"); componentIsNotPeriodic("avergradrms");
     725           2 :       log.printf(" ");
     726           2 :       addComponent("avergradmax"); componentIsNotPeriodic("avergradmax");
     727             :     }
     728          67 :     if(!fixed_stepsize_) {
     729           0 :       log.printf(" ");
     730           0 :       addComponent("stepsize"); componentIsNotPeriodic("stepsize");
     731           0 :       getPntrToComponent("stepsize")->set( getCurrentStepSize(0) );
     732             :     }
     733             :   }
     734             :   else {
     735          12 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
     736           9 :       log.printf("  Output Components for coefficent set %u:\n",i);
     737           9 :       std::string is=""; Tools::convert(i,is); is = "_" + coeffssetid_prefix_ + is;
     738           9 :       log.printf(" ");
     739           9 :       if(monitor_instantaneous_gradient_) {
     740           0 :         addComponent("gradrms"+is); componentIsNotPeriodic("gradrms"+is);
     741           0 :         log.printf(" ");
     742           0 :         addComponent("gradmax"+is); componentIsNotPeriodic("gradmax"+is);
     743             :       }
     744           9 :       if(aver_gradient_pntrs_.size()>0) {
     745           0 :         log.printf(" ");
     746           0 :         addComponent("avergradrms"+is); componentIsNotPeriodic("avergradrms"+is);
     747           0 :         log.printf(" ");
     748           0 :         addComponent("avergradmax"+is); componentIsNotPeriodic("avergradmax"+is);
     749             :       }
     750           9 :       if(!fixed_stepsize_) {
     751           0 :         log.printf(" ");
     752           0 :         addComponent("stepsize"+is); componentIsNotPeriodic("stepsize"+is);
     753           0 :         getPntrToComponent("stepsize"+is)->set( getCurrentStepSize(i) );
     754             :       }
     755           9 :     }
     756          70 :   }
     757             : 
     758          70 : }
     759             : 
     760             : 
     761         140 : Optimizer::~Optimizer() {
     762             :   //
     763          70 :   if(!isTargetDistOutputActive()) {
     764          84 :     for(unsigned int i=0; i<nbiases_; i++) {
     765          45 :       if(dynamic_targetdists_[i]) {
     766           1 :         bias_pntrs_[i]->enableDynamicTargetDistFileOutput();
     767           1 :         bias_pntrs_[i]->setupTargetDistFileOutput();
     768           1 :         bias_pntrs_[i]->writeTargetDistToFile();
     769             :       }
     770             :     }
     771             :   }
     772          31 :   else if(isTargetDistOutputActive() && getIterationCounter()%getTargetDistOutputStride()!=0) {
     773           1 :     writeTargetDistOutputFiles();
     774             :   }
     775             :   //
     776         146 :   for(unsigned int i=0; i<aux_coeffs_pntrs_.size(); i++) {
     777          76 :     delete aux_coeffs_pntrs_[i];
     778             :   }
     779          70 :   aux_coeffs_pntrs_.clear();
     780             :   //
     781          72 :   for(unsigned int i=0; i<aver_gradient_pntrs_.size(); i++) {
     782           2 :     delete aver_gradient_pntrs_[i];
     783             :   }
     784          70 :   aver_gradient_pntrs_.clear();
     785             :   //
     786         145 :   for(unsigned int i=0; i<coeffs_mask_pntrs_.size(); i++) {
     787          75 :     delete coeffs_mask_pntrs_[i];
     788             :   }
     789          70 :   coeffs_mask_pntrs_.clear();
     790             :   //
     791         145 :   for(unsigned int i=0; i<coeffsOFiles_.size(); i++) {
     792          75 :     coeffsOFiles_[i]->close();
     793          75 :     delete coeffsOFiles_[i];
     794             :   }
     795          70 :   coeffsOFiles_.clear();
     796         140 :   for(unsigned int i=0; i<gradientOFiles_.size(); i++) {
     797          70 :     gradientOFiles_[i]->close();
     798          70 :     delete gradientOFiles_[i];
     799             :   }
     800          70 :   gradientOFiles_.clear();
     801         135 :   for(unsigned int i=0; i<hessianOFiles_.size(); i++) {
     802          65 :     hessianOFiles_[i]->close();
     803          65 :     delete hessianOFiles_[i];
     804             :   }
     805          70 :   hessianOFiles_.clear();
     806         102 :   for(unsigned int i=0; i<targetdist_averagesOFiles_.size(); i++) {
     807          32 :     targetdist_averagesOFiles_[i]->close();
     808          32 :     delete targetdist_averagesOFiles_[i];
     809             :   }
     810          70 :   targetdist_averagesOFiles_.clear();
     811          70 : }
     812             : 
     813             : 
     814          72 : void Optimizer::registerKeywords( Keywords& keys ) {
     815          72 :   Action::registerKeywords(keys);
     816          72 :   ActionPilot::registerKeywords(keys);
     817          72 :   ActionWithValue::registerKeywords(keys);
     818             :   //
     819          72 :   keys.remove("NUMERICAL_DERIVATIVES");
     820             :   // Default always active keywords
     821          72 :   keys.add("compulsory","BIAS","the label of the VES bias to be optimized");
     822          72 :   keys.add("compulsory","STRIDE","the frequency of updating the coefficients given in the number of MD steps.");
     823          72 :   keys.add("compulsory","COEFFS_FILE","coeffs.data","the name of output file for the coefficients");
     824          72 :   keys.add("compulsory","COEFFS_OUTPUT","100","how often the coefficients should be written to file. This parameter is given as the number of iterations.");
     825          72 :   keys.add("optional","COEFFS_FMT","specify format for coefficient file(s) (useful for decrease the number of digits in regtests)");
     826          72 :   keys.add("optional","COEFFS_SET_ID_PREFIX","suffix to add to the filename given in FILE to identfy the bias, should only be given if a single filename is given in FILE when optimizing multiple biases.");
     827             :   //
     828          72 :   keys.add("optional","INITIAL_COEFFS","the name(s) of file(s) with the initial coefficents");
     829             :   // Hidden keywords to output the gradient to a file.
     830          72 :   keys.add("hidden","GRADIENT_FILE","the name of output file for the gradient");
     831          72 :   keys.add("hidden","GRADIENT_OUTPUT","how often the gradient should be written to file. This parameter is given as the number of bias iterations. It is by default 100 if GRADIENT_FILE is specficed");
     832          72 :   keys.add("hidden","GRADIENT_FMT","specify format for gradient file(s) (useful for decrease the number of digits in regtests)");
     833             :   // Either use a fixed stepsize (useFixedStepSizeKeywords) or changing stepsize (useDynamicsStepSizeKeywords)
     834          72 :   keys.reserve("compulsory","STEPSIZE","the step size used for the optimization");
     835          72 :   keys.reserve("compulsory","INITIAL_STEPSIZE","the initial step size used for the optimization");
     836             :   // Keywords related to the Hessian, actived with the useHessianKeywords function
     837          72 :   keys.reserveFlag("FULL_HESSIAN",false,"if the full Hessian matrix should be used for the optimization, otherwise only the diagonal part of the Hessian is used");
     838          72 :   keys.reserve("hidden","HESSIAN_FILE","the name of output file for the Hessian");
     839          72 :   keys.reserve("hidden","HESSIAN_OUTPUT","how often the Hessian should be written to file. This parameter is given as the number of bias iterations. It is by default 100 if HESSIAN_FILE is specficed");
     840          72 :   keys.reserve("hidden","HESSIAN_FMT","specify format for hessian file(s) (useful for decrease the number of digits in regtests)");
     841             :   // Keywords related to the multiple walkers, actived with the useMultipleWalkersKeywords function
     842          72 :   keys.reserveFlag("MULTIPLE_WALKERS",false,"if optimization is to be performed using multiple walkers connected via MPI");
     843             :   // Keywords related to the mask file, actived with the useMaskKeywords function
     844          72 :   keys.reserve("optional","MASK_FILE","read in a mask file which allows one to employ different step sizes for different coefficents and/or deactive the optimization of certain coefficients (by putting values of 0.0). One can write out the resulting mask by using the OUTPUT_MASK_FILE keyword.");
     845          72 :   keys.reserve("optional","OUTPUT_MASK_FILE","Name of the file to write out the mask resulting from using the MASK_FILE keyword. Can also be used to generate a template mask file.");
     846             :   //
     847          72 :   keys.reserveFlag("START_OPTIMIZATION_AFRESH",false,"if the iterations should be started afresh when a restart has been triggered by the RESTART keyword or the MD code.");
     848             :   //
     849          72 :   keys.addFlag("MONITOR_INSTANTANEOUS_GRADIENT",false,"if quantities related to the instantaneous gradient should be outputted.");
     850             :   //
     851          72 :   keys.reserveFlag("MONITOR_AVERAGE_GRADIENT",false,"if the averaged gradient should be monitored and quantities related to it should be outputted.");
     852          72 :   keys.reserve("optional","MONITOR_AVERAGES_GRADIENT_EXP_DECAY","use an exponentially decaying averaging with a given time constant when monitoring the averaged gradient");
     853             :   //
     854          72 :   keys.reserve("optional","TARGETDIST_STRIDE","stride for updating a target distribution that is iteratively updated during the optimization. Note that the value is given in terms of coefficent iterations.");
     855          72 :   keys.reserve("optional","TARGETDIST_OUTPUT","how often the dynamic target distribution(s) should be written out to file. Note that the value is given in terms of coefficent iterations.");
     856          72 :   keys.reserve("optional","TARGETDIST_PROJ_OUTPUT","how often the projections of the dynamic target distribution(s) should be written out to file. Note that the value is given in terms of coefficent iterations.");
     857             :   //
     858          72 :   keys.add("optional","TARGETDIST_AVERAGES_FILE","the name of output file for the target distribution averages. By default it is targetdist-averages.data.");
     859          72 :   keys.add("optional","TARGETDIST_AVERAGES_OUTPUT","how often the target distribution averages should be written out to file. Note that the value is given in terms of coefficent iterations. If no value is given are the averages only written at the begining of the optimization");
     860          72 :   keys.add("hidden","TARGETDIST_AVERAGES_FMT","specify format for target distribution averages file(s) (useful for decrease the number of digits in regtests)");
     861             :   //
     862          72 :   keys.add("optional","BIAS_OUTPUT","how often the bias(es) should be written out to file. Note that the value is given in terms of coefficent iterations.");
     863          72 :   keys.add("optional","FES_OUTPUT","how often the FES(s) should be written out to file. Note that the value is given in terms of coefficent iterations.");
     864          72 :   keys.add("optional","FES_PROJ_OUTPUT","how often the projections of the FES(s) should be written out to file. Note that the value is given in terms of coefficent iterations.");
     865             :   //
     866          72 :   keys.reserve("optional","REWEIGHT_FACTOR_STRIDE","stride for updating the reweighting factor c(t). Note that the value is given in terms of coefficent iterations.");
     867             :   //
     868          72 :   keys.use("RESTART");
     869             :   //
     870          72 :   keys.use("UPDATE_FROM");
     871          72 :   keys.use("UPDATE_UNTIL");
     872             :   // Components that are always active
     873          72 :   keys.addOutputComponent("gradrms","MONITOR_INSTANTANEOUS_GRADIENT","the root mean square value of the coefficent gradient. For multiple biases this component is labeled using the number of the bias as gradrms-#.");
     874          72 :   keys.addOutputComponent("gradmax","MONITOR_INSTANTANEOUS_GRADIENT","the largest absolute value of the coefficent gradient. For multiple biases this component is labeled using the number of the bias as gradmax-#.");
     875          72 :   ActionWithValue::useCustomisableComponents(keys);
     876             :   // keys.addOutputComponent("gradmaxidx","default","the index of the maximum absolute value of the gradient");
     877             : 
     878          72 : }
     879             : 
     880             : 
     881          72 : void Optimizer::useHessianKeywords(Keywords& keys) {
     882             :   // keys.use("FULL_HESSIAN");
     883          72 :   keys.use("HESSIAN_FILE");
     884          72 :   keys.use("HESSIAN_OUTPUT");
     885          72 :   keys.use("HESSIAN_FMT");
     886          72 : }
     887             : 
     888             : 
     889          72 : void Optimizer::useMultipleWalkersKeywords(Keywords& keys) {
     890          72 :   keys.use("MULTIPLE_WALKERS");
     891          72 : }
     892             : 
     893             : 
     894          70 : void Optimizer::useFixedStepSizeKeywords(Keywords& keys) {
     895          70 :   keys.use("STEPSIZE");
     896          70 : }
     897             : 
     898             : 
     899           0 : void Optimizer::useDynamicStepSizeKeywords(Keywords& keys) {
     900           0 :   keys.use("INITIAL_STEPSIZE");
     901           0 :   keys.addOutputComponent("stepsize","default","the current value of step size used to update the coefficients. For multiple biases this component is labeled using the number of the bias as stepsize-#.");
     902           0 : }
     903             : 
     904             : 
     905          70 : void Optimizer::useMaskKeywords(Keywords& keys) {
     906          70 :   keys.use("MASK_FILE");
     907          70 :   keys.use("OUTPUT_MASK_FILE");
     908          70 : }
     909             : 
     910             : 
     911          70 : void Optimizer::useRestartKeywords(Keywords& keys) {
     912          70 :   keys.use("START_OPTIMIZATION_AFRESH");
     913          70 : }
     914             : 
     915             : 
     916          72 : void Optimizer::useMonitorAverageGradientKeywords(Keywords& keys) {
     917          72 :   keys.use("MONITOR_AVERAGE_GRADIENT");
     918          72 :   keys.use("MONITOR_AVERAGES_GRADIENT_EXP_DECAY");
     919          72 :   keys.addOutputComponent("avergradrms","MONITOR_AVERAGE_GRADIENT","the root mean square value of the averaged coefficent gradient. For multiple biases this component is labeled using the number of the bias as gradrms-#.");
     920          72 :   keys.addOutputComponent("avergradmax","MONITOR_AVERAGE_GRADIENT","the largest absolute value of the averaged coefficent gradient. For multiple biases this component is labeled using the number of the bias as gradmax-#.");
     921          72 : }
     922             : 
     923             : 
     924          70 : void Optimizer::useDynamicTargetDistributionKeywords(Keywords& keys) {
     925          70 :   keys.use("TARGETDIST_STRIDE");
     926          70 :   keys.use("TARGETDIST_OUTPUT");
     927          70 :   keys.use("TARGETDIST_PROJ_OUTPUT");
     928          70 : }
     929             : 
     930             : 
     931           0 : void Optimizer::useReweightFactorKeywords(Keywords& keys) {
     932           0 :   keys.use("REWEIGHT_FACTOR_STRIDE");
     933           0 : }
     934             : 
     935             : 
     936          70 : void Optimizer::turnOnHessian() {
     937          70 :   plumed_massert(hessian_pntrs_.size()==0,"turnOnHessian() should only be run during initialization");
     938          70 :   use_hessian_=true;
     939          70 :   hessian_pntrs_.clear();
     940         146 :   for(unsigned int i=0; i<nbiases_; i++) {
     941          76 :     std::vector<CoeffsMatrix*> pntrs_hessian = enableHessian(bias_pntrs_[i],diagonal_hessian_);
     942         152 :     for(unsigned int k=0; k<pntrs_hessian.size(); k++) {
     943          76 :       pntrs_hessian[k]->turnOnIterationCounter();
     944          76 :       pntrs_hessian[k]->setIterationCounterAndTime(getIterationCounter(),getTime());
     945          76 :       hessian_pntrs_.push_back(pntrs_hessian[k]);
     946             :     }
     947          76 :   }
     948          70 :   plumed_massert(hessian_pntrs_.size()==ncoeffssets_,"problems in linking Hessians");
     949          70 :   if(diagonal_hessian_) {
     950          70 :     log.printf("  Optimization performed using diagonal Hessian matrix\n");
     951             :   }
     952             :   else {
     953           0 :     log.printf("  Optimization performed using full Hessian matrix\n");
     954             :   }
     955             :   //
     956          70 :   if(hessian_output_fmt_.size()>0) {
     957         126 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
     958          65 :       hessian_pntrs_[i]->setOutputFmt(hessian_output_fmt_);
     959             :     }
     960             :   }
     961             : 
     962          70 : }
     963             : 
     964             : 
     965           0 : void Optimizer::turnOffHessian() {
     966           0 :   use_hessian_=false;
     967           0 :   for(unsigned int i=0; i<nbiases_; i++) {
     968           0 :     bias_pntrs_[i]->disableHessian();
     969             :   }
     970           0 :   hessian_pntrs_.clear();
     971           0 :   for(unsigned int i=0; i<hessianOFiles_.size(); i++) {
     972           0 :     hessianOFiles_[i]->close();
     973           0 :     delete hessianOFiles_[i];
     974             :   }
     975           0 :   hessianOFiles_.clear();
     976           0 : }
     977             : 
     978             : 
     979          76 : std::vector<CoeffsMatrix*> Optimizer::enableHessian(VesBias* bias_pntr_in, const bool diagonal_hessian) {
     980          76 :   plumed_massert(use_hessian_,"the Hessian should not be used");
     981          76 :   bias_pntr_in->enableHessian(diagonal_hessian);
     982          76 :   std::vector<CoeffsMatrix*> hessian_pntrs_out = bias_pntr_in->getHessianPntrs();
     983         152 :   for(unsigned int k=0; k<hessian_pntrs_out.size(); k++) {
     984          76 :     plumed_massert(hessian_pntrs_out[k] != NULL,"Hessian is needed but not linked correctly");
     985             :   }
     986          76 :   return hessian_pntrs_out;
     987             : }
     988             : 
     989             : 
     990             : // CoeffsMatrix* Optimizer::switchToDiagonalHessian(VesBias* bias_pntr_in) {
     991             : //   plumed_massert(use_hessian_,"it does not make sense to switch to diagonal Hessian if it Hessian is not used");
     992             : //   diagonal_hessian_=true;
     993             : //   bias_pntr_in->enableHessian(diagonal_hessian_);
     994             : //   CoeffsMatrix* hessian_pntr_out = bias_pntr_in->getHessianPntr();
     995             : //   plumed_massert(hessian_pntr_out != NULL,"Hessian is needed but not linked correctly");
     996             : //   //
     997             : //   log.printf("  %s (with label %s): switching to a diagonal Hessian for VES bias %s (with label %s) at time  %f\n",getName().c_str(),getLabel().c_str(),bias_pntr_in->getName().c_str(),bias_pntr_in->getLabel().c_str(),getTime());
     998             : //   return hessian_pntr_out;
     999             : // }
    1000             : 
    1001             : 
    1002             : // CoeffsMatrix* Optimizer::switchToFullHessian(VesBias* bias_pntr_in) {
    1003             : //   plumed_massert(use_hessian_,"it does not make sense to switch to diagonal Hessian if it Hessian is not used");
    1004             : //   diagonal_hessian_=false;
    1005             : //   bias_pntr_in->enableHessian(diagonal_hessian_);
    1006             : //   CoeffsMatrix* hessian_pntr_out = bias_pntr_in->getHessianPntr();
    1007             : //   plumed_massert(hessian_pntr_out != NULL,"Hessian is needed but not linked correctly");
    1008             : //   //
    1009             : //   log.printf("  %s (with label %s): switching to a diagonal Hessian for VES bias %s (with label %s) at time  %f\n",getName().c_str(),getLabel().c_str(),bias_pntr_in->getName().c_str(),bias_pntr_in->getLabel().c_str(),getTime());
    1010             : //   return hessian_pntr_out;
    1011             : // }
    1012             : 
    1013             : 
    1014         810 : void Optimizer::update() {
    1015         810 :   if(onStep() && !isFirstStep) {
    1016        1460 :     for(unsigned int i=0; i<nbiases_; i++) {
    1017         760 :       bias_pntrs_[i]->updateGradientAndHessian(use_mwalkers_mpi_);
    1018             :     }
    1019        1460 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
    1020         760 :       if(gradient_pntrs_[i]->isActive()) {coeffsUpdate(i);}
    1021             :       else {
    1022         270 :         std::string msg = "iteration " + getIterationCounterStr(+1) +
    1023         270 :                           " for " + bias_pntrs_[i]->getLabel() +
    1024         180 :                           " - the coefficients are not updated as CV values are outside the bias intervals";
    1025          90 :         warning(msg);
    1026             :       }
    1027             : 
    1028             :       // +1 as this is done before increaseIterationCounter() is used
    1029         760 :       unsigned int curr_iter = getIterationCounter()+1;
    1030         760 :       double curr_time = getTime();
    1031         760 :       coeffs_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1032         760 :       aux_coeffs_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1033         760 :       gradient_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1034         760 :       targetdist_averages_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1035         760 :       if(use_hessian_) {
    1036         760 :         hessian_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1037             :       }
    1038         760 :       if(aver_gradient_pntrs_.size()>0) {
    1039          20 :         aver_gradient_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1040          20 :         aver_gradient_pntrs_[i]->addToAverage(*gradient_pntrs_[i]);
    1041             :       }
    1042             :     }
    1043         700 :     increaseIterationCounter();
    1044         700 :     updateOutputComponents();
    1045        1460 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
    1046         760 :       writeOutputFiles(i);
    1047             :     }
    1048         700 :     if(ustride_targetdist_>0 && getIterationCounter()%ustride_targetdist_==0) {
    1049         640 :       for(unsigned int i=0; i<nbiases_; i++) {
    1050         320 :         if(dynamic_targetdists_[i]) {
    1051         320 :           bias_pntrs_[i]->updateTargetDistributions();
    1052             :         }
    1053             :       }
    1054             :     }
    1055         700 :     if(ustride_reweightfactor_>0 && getIterationCounter()%ustride_reweightfactor_==0) {
    1056           0 :       for(unsigned int i=0; i<nbiases_; i++) {
    1057           0 :         bias_pntrs_[i]->updateReweightFactor();
    1058             :       }
    1059             :     }
    1060             : 
    1061             : 
    1062             :     //
    1063         700 :     if(isBiasOutputActive() && getIterationCounter()%getBiasOutputStride()==0) {
    1064          69 :       writeBiasOutputFiles();
    1065             :     }
    1066         700 :     if(isFesOutputActive() && getIterationCounter()%getFesOutputStride()==0) {
    1067          69 :       writeFesOutputFiles();
    1068             :     }
    1069         700 :     if(isFesProjOutputActive() && getIterationCounter()%getFesProjOutputStride()==0) {
    1070          15 :       writeFesProjOutputFiles();
    1071             :     }
    1072         700 :     if(isTargetDistOutputActive() && getIterationCounter()%getTargetDistOutputStride()==0) {
    1073          30 :       writeTargetDistOutputFiles();
    1074             :     }
    1075         700 :     if(isTargetDistProjOutputActive() && getIterationCounter()%getTargetDistProjOutputStride()==0) {
    1076           2 :       writeTargetDistProjOutputFiles();
    1077             :     }
    1078             :   }
    1079             :   else {
    1080         110 :     isFirstStep=false;
    1081             :   }
    1082         810 : }
    1083             : 
    1084             : 
    1085         700 : void Optimizer::updateOutputComponents() {
    1086         700 :   if(ncoeffssets_==1) {
    1087         670 :     if(!fixed_stepsize_) {
    1088           0 :       getPntrToComponent("stepsize")->set( getCurrentStepSize(0) );
    1089             :     }
    1090         670 :     if(monitor_instantaneous_gradient_) {
    1091          20 :       getPntrToComponent("gradrms")->set( gradient_pntrs_[0]->getRMS() );
    1092          20 :       size_t gradient_maxabs_idx=0;
    1093          20 :       getPntrToComponent("gradmax")->set( gradient_pntrs_[0]->getMaxAbsValue(gradient_maxabs_idx) );
    1094             :     }
    1095         670 :     if(aver_gradient_pntrs_.size()>0) {
    1096          20 :       getPntrToComponent("avergradrms")->set( aver_gradient_pntrs_[0]->getRMS() );
    1097          20 :       size_t avergradient_maxabs_idx=0;
    1098          20 :       getPntrToComponent("avergradmax")->set( aver_gradient_pntrs_[0]->getMaxAbsValue(avergradient_maxabs_idx) );
    1099             :     }
    1100             :   }
    1101             :   else {
    1102         120 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
    1103          90 :       std::string is=""; Tools::convert(i,is); is = "_" + coeffssetid_prefix_ + is;
    1104          90 :       if(!fixed_stepsize_) {
    1105           0 :         getPntrToComponent("stepsize"+is)->set( getCurrentStepSize(i) );
    1106             :       }
    1107          90 :       if(monitor_instantaneous_gradient_) {
    1108           0 :         getPntrToComponent("gradrms"+is)->set( gradient_pntrs_[i]->getRMS() );
    1109           0 :         size_t gradient_maxabs_idx=0;
    1110           0 :         getPntrToComponent("gradmax"+is)->set( gradient_pntrs_[i]->getMaxAbsValue(gradient_maxabs_idx) );
    1111             :       }
    1112          90 :       if(aver_gradient_pntrs_.size()>0) {
    1113           0 :         getPntrToComponent("avergradrms"+is)->set( aver_gradient_pntrs_[0]->getRMS() );
    1114           0 :         size_t avergradient_maxabs_idx=0;
    1115           0 :         getPntrToComponent("avergradmax"+is)->set( aver_gradient_pntrs_[0]->getMaxAbsValue(avergradient_maxabs_idx) );
    1116             :       }
    1117          90 :     }
    1118             :   }
    1119         700 : }
    1120             : 
    1121             : 
    1122           1 : void Optimizer::turnOffCoeffsOutputFiles() {
    1123           2 :   for(unsigned int i=0; i<coeffsOFiles_.size(); i++) {
    1124           1 :     coeffsOFiles_[i]->close();
    1125           1 :     delete coeffsOFiles_[i];
    1126             :   }
    1127           1 :   coeffsOFiles_.clear();
    1128           1 : }
    1129             : 
    1130             : 
    1131         760 : void Optimizer::writeOutputFiles(const unsigned int coeffs_id) {
    1132         760 :   if(coeffsOFiles_.size()>0 && iter_counter%coeffs_wstride_==0) {
    1133         740 :     coeffs_pntrs_[coeffs_id]->writeToFile(*coeffsOFiles_[coeffs_id],aux_coeffs_pntrs_[coeffs_id],false);
    1134             :   }
    1135         760 :   if(gradientOFiles_.size()>0 && iter_counter%gradient_wstride_==0) {
    1136         700 :     if(aver_gradient_pntrs_.size()==0) {
    1137         680 :       gradient_pntrs_[coeffs_id]->writeToFile(*gradientOFiles_[coeffs_id],false);
    1138             :     }
    1139             :     else {
    1140          20 :       gradient_pntrs_[coeffs_id]->writeToFile(*gradientOFiles_[coeffs_id],aver_gradient_pntrs_[coeffs_id],false);
    1141             :     }
    1142             :   }
    1143         760 :   if(hessianOFiles_.size()>0 && iter_counter%hessian_wstride_==0) {
    1144         650 :     hessian_pntrs_[coeffs_id]->writeToFile(*hessianOFiles_[coeffs_id]);
    1145             :   }
    1146         760 :   if(targetdist_averagesOFiles_.size()>0 && iter_counter%targetdist_averages_wstride_==0) {
    1147         320 :     targetdist_averages_pntrs_[coeffs_id]->writeToFile(*targetdist_averagesOFiles_[coeffs_id]);
    1148             :   }
    1149         760 : }
    1150             : 
    1151             : 
    1152         349 : void Optimizer::setupOFiles(std::vector<std::string>& fnames, std::vector<OFile*>& OFiles, const bool multi_sim_single_files) {
    1153         349 :   plumed_assert(ncoeffssets_>0);
    1154         349 :   OFiles.resize(fnames.size(),NULL);
    1155         642 :   for(unsigned int i=0; i<fnames.size(); i++) {
    1156         293 :     OFiles[i] = new OFile();
    1157         293 :     OFiles[i]->link(*this);
    1158         293 :     if(multi_sim_single_files) {
    1159          48 :       unsigned int r=0;
    1160          48 :       if(comm.Get_rank()==0) {r=multi_sim_comm.Get_rank();}
    1161          48 :       comm.Bcast(r,0);
    1162          48 :       if(r>0) {fnames[i]="/dev/null";}
    1163          48 :       OFiles[i]->enforceSuffix("");
    1164             :     }
    1165         293 :     OFiles[i]->open(fnames[i]);
    1166         293 :     OFiles[i]->setHeavyFlush();
    1167             :   }
    1168         349 : }
    1169             : 
    1170             : 
    1171          14 : void Optimizer::readCoeffsFromFiles(const std::vector<std::string>& fnames, const bool read_aux_coeffs) {
    1172          14 :   plumed_assert(ncoeffssets_>0);
    1173          14 :   plumed_assert(fnames.size()==ncoeffssets_);
    1174          14 :   if(ncoeffssets_==1) {
    1175          13 :     log.printf("  Read in coefficents from file ");
    1176             :   }
    1177             :   else {
    1178           1 :     log.printf("  Read in coefficents from files:\n");
    1179             :   }
    1180          30 :   for(unsigned int i=0; i<ncoeffssets_; i++) {
    1181          16 :     IFile ifile;
    1182          16 :     ifile.link(*this);
    1183          16 :     if(use_mwalkers_mpi_ && mwalkers_mpi_single_files_) {
    1184           4 :       ifile.enforceSuffix("");
    1185             :     }
    1186          16 :     ifile.open(fnames[i]);
    1187          16 :     if(!ifile.FieldExist(coeffs_pntrs_[i]->getDataLabel())) {
    1188           0 :       std::string error_msg = "Problem with reading coefficents from file " + ifile.getPath() + ": no field with name " + coeffs_pntrs_[i]->getDataLabel() + "\n";
    1189           0 :       plumed_merror(error_msg);
    1190             :     }
    1191          16 :     size_t ncoeffs_read = coeffs_pntrs_[i]->readFromFile(ifile,false,false);
    1192          16 :     if(ncoeffssets_==1) {
    1193          13 :       log.printf("%s (read %zu of %zu values)\n", ifile.getPath().c_str(),ncoeffs_read,coeffs_pntrs_[i]->numberOfCoeffs());
    1194             :     }
    1195             :     else {
    1196           3 :       log.printf("   coefficent set %u: %s (read %zu of %zu values)\n",i,ifile.getPath().c_str(),ncoeffs_read,coeffs_pntrs_[i]->numberOfCoeffs());
    1197             :     }
    1198          16 :     ifile.close();
    1199          16 :     if(read_aux_coeffs) {
    1200          15 :       ifile.open(fnames[i]);
    1201          15 :       if(!ifile.FieldExist(aux_coeffs_pntrs_[i]->getDataLabel())) {
    1202           0 :         std::string error_msg = "Problem with reading coefficents from file " + ifile.getPath() + ": no field with name " + aux_coeffs_pntrs_[i]->getDataLabel() + "\n";
    1203           0 :         plumed_merror(error_msg);
    1204             :       }
    1205          15 :       aux_coeffs_pntrs_[i]->readFromFile(ifile,false,false);
    1206          15 :       ifile.close();
    1207             :     }
    1208             :     else {
    1209           1 :       AuxCoeffs(i).setValues( Coeffs(i) );
    1210             :     }
    1211          16 :   }
    1212          14 : }
    1213             : 
    1214             : 
    1215          76 : void Optimizer::addCoeffsSetIDsToFilenames(std::vector<std::string>& fnames, std::string& coeffssetid_prefix) {
    1216         152 :   if(ncoeffssets_==1) {return;}
    1217             :   //
    1218           9 :   if(fnames.size()==1) {
    1219           0 :     fnames.resize(ncoeffssets_,fnames[0]);
    1220             :   }
    1221           9 :   plumed_assert(fnames.size()==ncoeffssets_);
    1222             :   //
    1223          36 :   for(unsigned int i=0; i<ncoeffssets_; i++) {
    1224          27 :     std::string is=""; Tools::convert(i,is);
    1225          27 :     fnames[i] = FileBase::appendSuffix(fnames[i],"."+coeffssetid_prefix_+is);
    1226          27 :   }
    1227             : }
    1228             : 
    1229             : 
    1230          84 : void Optimizer::setAllCoeffsSetIterationCounters() {
    1231         176 :   for(unsigned int i=0; i<ncoeffssets_; i++) {
    1232          92 :     coeffs_pntrs_[i]->setIterationCounterAndTime(getIterationCounter(),getTime());
    1233          92 :     aux_coeffs_pntrs_[i]->setIterationCounterAndTime(getIterationCounter(),getTime());
    1234          92 :     gradient_pntrs_[i]->setIterationCounterAndTime(getIterationCounter(),getTime());
    1235          92 :     targetdist_averages_pntrs_[i]->setIterationCounterAndTime(getIterationCounter(),getTime());
    1236          92 :     if(use_hessian_) {
    1237           0 :       hessian_pntrs_[i]->setIterationCounterAndTime(getIterationCounter(),getTime());
    1238             :     }
    1239             :   }
    1240          84 : }
    1241             : 
    1242             : 
    1243          90 : std::string Optimizer::getIterationCounterStr(const int offset) const {
    1244          90 :   std::string s;
    1245          90 :   Tools::convert(getIterationCounter()+offset,s);
    1246          90 :   return s;
    1247             : }
    1248             : 
    1249             : 
    1250          69 : void Optimizer::writeBiasOutputFiles() const {
    1251         144 :   for(unsigned int i=0; i<nbiases_; i++) {
    1252          75 :     bias_pntrs_[i]->writeBiasToFile();
    1253             :   }
    1254          69 : }
    1255             : 
    1256             : 
    1257          69 : void Optimizer::writeFesOutputFiles() const {
    1258         144 :   for(unsigned int i=0; i<nbiases_; i++) {
    1259          75 :     bias_pntrs_[i]->writeFesToFile();
    1260             :   }
    1261          69 : }
    1262             : 
    1263             : 
    1264          15 : void Optimizer::writeFesProjOutputFiles() const {
    1265          30 :   for(unsigned int i=0; i<nbiases_; i++) {
    1266          15 :     bias_pntrs_[i]->writeFesProjToFile();
    1267             :   }
    1268          15 : }
    1269             : 
    1270             : 
    1271          31 : void Optimizer::writeTargetDistOutputFiles() const {
    1272          62 :   for(unsigned int i=0; i<nbiases_; i++) {
    1273          31 :     if(dynamic_targetdists_[i]) {
    1274          31 :       bias_pntrs_[i]->writeTargetDistToFile();
    1275             :     }
    1276             :   }
    1277          31 : }
    1278             : 
    1279             : 
    1280           2 : void Optimizer::writeTargetDistProjOutputFiles() const {
    1281           4 :   for(unsigned int i=0; i<nbiases_; i++) {
    1282           2 :     if(dynamic_targetdists_[i]) {
    1283           2 :       bias_pntrs_[i]->writeTargetDistProjToFile();
    1284             :     }
    1285             :   }
    1286           2 : }
    1287             : 
    1288             : 
    1289             : 
    1290             : }
    1291        4821 : }

Generated by: LCOV version 1.13