LCOV - code coverage report
Current view: top level - ves - Optimizer.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 655 737 88.9 %
Date: 2019-08-13 10:15:31 Functions: 29 34 85.3 %

          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          80 : 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         160 :   isFirstStep(true)
      92             : {
      93          80 :   std::vector<std::string> bias_labels(0);
      94         160 :   parseVector("BIAS",bias_labels);
      95          80 :   plumed_massert(bias_labels.size()>0,"problem with BIAS keyword");
      96          80 :   nbiases_ = bias_labels.size();
      97             :   //
      98          80 :   std::string error_msg = "";
      99         240 :   bias_pntrs_ = VesTools::getPointersFromLabels<VesBias*>(bias_labels,plumed.getActionSet(),error_msg);
     100          80 :   if(error_msg.size()>0) {plumed_merror("Error in keyword BIAS of "+getName()+": "+error_msg);}
     101             : 
     102         252 :   for(unsigned int i=0; i<bias_pntrs_.size(); i++) {
     103          86 :     bias_pntrs_[i]->linkOptimizer(this);
     104             :     //
     105          86 :     std::vector<CoeffsVector*> pntrs_coeffs = bias_pntrs_[i]->getCoeffsPntrs();
     106          86 :     std::vector<CoeffsVector*> pntrs_gradient = bias_pntrs_[i]->getGradientPntrs();
     107          86 :     std::vector<CoeffsVector*> pntrs_targetdist_averages = bias_pntrs_[i]->getTargetDistAveragesPntrs();
     108          86 :     plumed_massert(pntrs_coeffs.size()==pntrs_gradient.size(),"something wrong in the coefficients and gradient passed from VES bias");
     109          86 :     plumed_massert(pntrs_coeffs.size()==pntrs_targetdist_averages.size(),"something wrong in the coefficients and target distribution averages passed from VES bias");
     110         258 :     for(unsigned int k=0; k<pntrs_coeffs.size(); k++) {
     111          86 :       plumed_massert(pntrs_coeffs[k] != NULL,"some coefficient is not linked correctly");
     112          86 :       plumed_massert(pntrs_gradient[k] != NULL,"some gradient is not linked correctly");
     113          86 :       plumed_massert(pntrs_targetdist_averages[k] != NULL,"some target distribution average is not linked correctly");
     114             :       pntrs_coeffs[k]->turnOnIterationCounter();
     115          86 :       coeffs_pntrs_.push_back(pntrs_coeffs[k]);
     116          86 :       pntrs_gradient[k]->turnOnIterationCounter();
     117          86 :       gradient_pntrs_.push_back(pntrs_gradient[k]);
     118          86 :       pntrs_targetdist_averages[k]->turnOnIterationCounter();
     119          86 :       targetdist_averages_pntrs_.push_back(pntrs_targetdist_averages[k]);
     120             :       //
     121          86 :       CoeffsVector* aux_coeffs_tmp = new CoeffsVector(*pntrs_coeffs[k]);
     122          86 :       std::string aux_label = pntrs_coeffs[k]->getLabel();
     123          86 :       if(aux_label.find("coeffs")!=std::string::npos) {
     124         258 :         aux_label.replace(aux_label.find("coeffs"), std::string("coeffs").length(), "aux_coeffs");
     125             :       }
     126             :       else {
     127             :         aux_label += "_aux";
     128             :       }
     129          86 :       aux_coeffs_tmp->setLabels(aux_label);
     130          86 :       aux_coeffs_pntrs_.push_back(aux_coeffs_tmp);
     131          86 :       AuxCoeffs(i).setValues( Coeffs(i) );
     132             :     }
     133             :   }
     134          80 :   ncoeffssets_ = coeffs_pntrs_.size();
     135          80 :   plumed_massert(aux_coeffs_pntrs_.size()==ncoeffssets_,"problems in linking aux coefficients");
     136          80 :   plumed_massert(gradient_pntrs_.size()==ncoeffssets_,"problems in linking gradients");
     137          80 :   setAllCoeffsSetIterationCounters();
     138             : 
     139             : 
     140             :   //
     141          80 :   identical_coeffs_shape_ = true;
     142          86 :   for(unsigned int i=1; i<ncoeffssets_; i++) {
     143          12 :     if(!coeffs_pntrs_[0]->sameShape(*coeffs_pntrs_[i])) {
     144           0 :       identical_coeffs_shape_ = false;
     145           0 :       break;
     146             :     }
     147             :   }
     148             :   //
     149         160 :   if(keywords.exists("STEPSIZE")) {
     150         152 :     plumed_assert(!keywords.exists("INITIAL_STEPSIZE"));
     151          76 :     fixed_stepsize_=true;
     152         152 :     parseMultipleValues("STEPSIZE",stepsizes_);
     153          76 :     setCurrentStepSizes(stepsizes_);
     154             :   }
     155         160 :   if(keywords.exists("INITIAL_STEPSIZE")) {
     156           6 :     plumed_assert(!keywords.exists("STEPSIZE"));
     157           3 :     fixed_stepsize_=false;
     158           6 :     parseMultipleValues("INITIAL_STEPSIZE",stepsizes_);
     159           3 :     setCurrentStepSizes(stepsizes_);
     160             :   }
     161             :   //
     162          80 :   if(ncoeffssets_==1) {
     163         154 :     log.printf("  optimizing VES bias %s with label %s: \n",bias_pntrs_[0]->getName().c_str(),bias_pntrs_[0]->getLabel().c_str());
     164         154 :     log.printf("   KbT: %f\n",bias_pntrs_[0]->getKbT());
     165         154 :     log.printf("  number of coefficients: %zu\n",coeffs_pntrs_[0]->numberOfCoeffs());
     166          77 :     if(stepsizes_.size()>0) {
     167          76 :       if(fixed_stepsize_) {log.printf("  using a constant step size of %f\n",stepsizes_[0]);}
     168           3 :       else {log.printf("  using an initial step size of %f\n",stepsizes_[0]);}
     169             :     }
     170             :   }
     171             :   else {
     172           3 :     log.printf("  optimizing %u coefficient sets from following %u VES biases:\n",ncoeffssets_,nbiases_);
     173           9 :     for(unsigned int i=0; i<nbiases_; i++) {
     174          36 :       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             :     size_t tot_ncoeffs = 0;
     177           9 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
     178           9 :       log.printf("  coefficient set %u: \n",i);
     179          27 :       log.printf("   used in bias %s (type %s)\n",coeffs_pntrs_[i]->getPntrToAction()->getLabel().c_str(),coeffs_pntrs_[i]->getPntrToAction()->getName().c_str());
     180          18 :       log.printf("   number of coefficients: %zu\n",coeffs_pntrs_[i]->numberOfCoeffs());
     181           9 :       if(stepsizes_.size()>0) {
     182          18 :         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          18 :       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         160 :   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             :   bool mw_single_files = false;
     204         160 :   if(keywords.exists("MULTIPLE_WALKERS")) {
     205         160 :     parseFlag("MULTIPLE_WALKERS",use_mwalkers_mpi_);
     206          80 :     if(use_mwalkers_mpi_) {
     207             :       mw_single_files=true;
     208             :     }
     209             :   }
     210             : 
     211          80 :   int numwalkers=1;
     212          80 :   int walker_rank=0;
     213          80 :   if(comm.Get_rank()==0) {
     214          71 :     numwalkers = multi_sim_comm.Get_size();
     215          71 :     walker_rank = multi_sim_comm.Get_rank();
     216             :   }
     217          80 :   comm.Bcast(numwalkers,0);
     218          80 :   comm.Bcast(walker_rank,0);
     219          80 :   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          80 :   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          36 :     log << plumed.cite("Raiteri, Laio, Gervasio, Micheletti, and Parrinello, J. Phys. Chem. B 110, 3533 (2006)");
     228          12 :     log.printf("\n");
     229             :   }
     230             : 
     231          80 :   dynamic_targetdists_.resize(nbiases_,false);
     232         160 :   if(keywords.exists("TARGETDIST_STRIDE")) {
     233             :     bool need_stride = false;
     234          83 :     for(unsigned int i=0; i<nbiases_; i++) {
     235         166 :       dynamic_targetdists_[i] = bias_pntrs_[i]->dynamicTargetDistribution();
     236          83 :       if(dynamic_targetdists_[i]) {need_stride = true;}
     237             :     }
     238         154 :     parse("TARGETDIST_STRIDE",ustride_targetdist_);
     239          77 :     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          77 :     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          77 :     if(ustride_targetdist_>0) {
     246          37 :       if(nbiases_==1) {
     247          37 :         log.printf("  the target distribution will be updated very %u coefficient iterations\n",ustride_targetdist_);
     248             :       }
     249             :       else {
     250           0 :         log.printf("  the target distribution will be updated very %u coefficient 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          37 :       log.printf("  See and cite ");
     257         111 :       log << plumed.cite("Valsson and Parrinello, J. Chem. Theory Comput. 11, 1996-2002 (2015)");
     258          37 :       log.printf("\n");
     259             :     }
     260             :   }
     261             : 
     262         160 :   if(keywords.exists("REWEIGHT_FACTOR_STRIDE")) {
     263             :     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 coefficient iterations\n",ustride_reweightfactor_);
     276             :     }
     277             :   }
     278             : 
     279         160 :   if(keywords.exists("MONITOR_INSTANTANEOUS_GRADIENT")) {
     280         160 :     parseFlag("MONITOR_INSTANTANEOUS_GRADIENT",monitor_instantaneous_gradient_);
     281             :   }
     282             : 
     283         160 :   if(keywords.exists("MONITOR_AVERAGE_GRADIENT")) {
     284          75 :     bool monitor_aver_gradient = false;
     285         150 :     parseFlag("MONITOR_AVERAGE_GRADIENT",monitor_aver_gradient);
     286          75 :     if(monitor_aver_gradient) {
     287           2 :       unsigned int averaging_exp_decay=0;
     288           4 :       parse("MONITOR_AVERAGES_GRADIENT_EXP_DECAY",averaging_exp_decay);
     289             :       aver_gradient_pntrs_.clear();
     290           4 :       for(unsigned int i=0; i<ncoeffssets_; i++) {
     291           4 :         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           6 :           aver_grad_label.replace(aver_grad_label.find("gradient"), std::string("gradient").length(), "aver_gradient");
     296             :         }
     297             :         else {
     298             :           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             :       }
     306             :     }
     307             :   }
     308             : 
     309             : 
     310          80 :   if(ncoeffssets_>1) {
     311             :     coeffssetid_prefix_="c-";
     312           6 :     if(keywords.exists("COEFFS_SET_ID_PREFIX")) {
     313           6 :       parse("COEFFS_SET_ID_PREFIX",coeffssetid_prefix_);
     314             :     }
     315             :   }
     316             :   else {
     317             :     coeffssetid_prefix_="";
     318         154 :     if(keywords.exists("COEFFS_SET_ID_PREFIX")) {
     319         154 :       parse("COEFFS_SET_ID_PREFIX",coeffssetid_prefix_);
     320             :     }
     321          77 :     if(coeffssetid_prefix_.size()>0) {
     322           0 :       plumed_merror("COEFFS_SET_ID_PREFIX should only be given if optimizing multiple coefficient sets");
     323             :     }
     324             :   }
     325             : 
     326         160 :   if(keywords.exists("INITIAL_COEFFS")) {
     327             :     std::vector<std::string> initial_coeffs_fnames;
     328         160 :     parseFilenames("INITIAL_COEFFS",initial_coeffs_fnames);
     329          80 :     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          80 :     }
     337             :   }
     338             :   //
     339             : 
     340          80 :   std::vector<std::string> coeffs_fnames;
     341         160 :   if(keywords.exists("COEFFS_FILE")) {
     342         240 :     parseFilenames("COEFFS_FILE",coeffs_fnames,"coeffs.data");
     343          80 :     bool start_opt_afresh=false;
     344         160 :     if(keywords.exists("START_OPTIMIZATION_AFRESH")) {
     345         154 :       parseFlag("START_OPTIMIZATION_AFRESH",start_opt_afresh);
     346          78 :       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         160 :     if(getRestart()) {
     351          43 :       for(unsigned int i=0; i<coeffs_fnames.size(); i++) {
     352          15 :         IFile ifile;
     353          15 :         ifile.link(*this);
     354          19 :         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           6 :         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             :         setIterationCounter(0);
     372           1 :         log.printf("  Optimization started afresh at iteration %u\n",getIterationCounter());
     373           1 :         for(unsigned int i=0; i<ncoeffssets_; i++) {
     374           1 :           AuxCoeffs(i).setValues( Coeffs(i) );
     375             :         }
     376             :       }
     377             :       else {
     378             :         setIterationCounter(coeffs_pntrs_[0]->getIterationCounter());
     379          12 :         log.printf("  Optimization restarted at iteration %u\n",getIterationCounter());
     380             :       }
     381          13 :       setAllCoeffsSetIterationCounters();
     382             :     }
     383             : 
     384          80 :     std::string coeffs_wstride_tmpstr="";
     385         160 :     parse("COEFFS_OUTPUT",coeffs_wstride_tmpstr);
     386         160 :     if(coeffs_wstride_tmpstr!="OFF" && coeffs_wstride_tmpstr.size()>0) {
     387          80 :       Tools::convert(coeffs_wstride_tmpstr,coeffs_wstride_);
     388             :     }
     389          80 :     if(coeffs_wstride_tmpstr=="OFF") {
     390           0 :       coeffs_fnames.clear();
     391             :     }
     392          80 :     setupOFiles(coeffs_fnames,coeffsOFiles_,mw_single_files);
     393         160 :     parse("COEFFS_FMT",coeffs_output_fmt_);
     394          80 :     if(coeffs_output_fmt_.size()>0) {
     395          85 :       for(unsigned int i=0; i<ncoeffssets_; i++) {
     396         170 :         coeffs_pntrs_[i]->setOutputFmt(coeffs_output_fmt_);
     397             :       }
     398             :     }
     399         160 :     if(!getRestart()) {
     400         209 :       for(unsigned int i=0; i<coeffsOFiles_.size(); i++) {
     401         213 :         coeffs_pntrs_[i]->writeToFile(*coeffsOFiles_[i],aux_coeffs_pntrs_[i],false);
     402             :       }
     403             :     }
     404          80 :     if(coeffs_fnames.size()>0) {
     405          80 :       if(ncoeffssets_==1) {
     406         308 :         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          21 :         for(unsigned int i=0; i<coeffs_fnames.size(); i++) {
     411          27 :           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             :     }
     418             :   }
     419             : 
     420          80 :   std::vector<std::string> gradient_fnames;
     421         160 :   if(keywords.exists("GRADIENT_FILE")) {
     422         160 :     parseFilenames("GRADIENT_FILE",gradient_fnames);
     423         160 :     parse("GRADIENT_OUTPUT",gradient_wstride_);
     424             : 
     425          80 :     if(coeffs_fnames.size()>0) {
     426         228 :       for(unsigned int i=0; i<gradient_fnames.size(); i++) {
     427          74 :         plumed_massert(gradient_fnames[i]!=coeffs_fnames[i],"COEFFS_FILE and GRADIENT_FILE cannot be the same");
     428             :       }
     429             :     }
     430          80 :     setupOFiles(gradient_fnames,gradientOFiles_,mw_single_files);
     431         160 :     parse("GRADIENT_FMT",gradient_output_fmt_);
     432          80 :     if(gradient_output_fmt_.size()>0) {
     433          74 :       for(unsigned int i=0; i<ncoeffssets_; i++) {
     434         148 :         gradient_pntrs_[i]->setOutputFmt(gradient_output_fmt_);
     435             :       }
     436             :     }
     437             : 
     438          80 :     if(gradient_fnames.size()>0) {
     439          68 :       if(ncoeffssets_==1) {
     440         260 :         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          21 :         for(unsigned int i=0; i<gradient_fnames.size(); i++) {
     445          27 :           log.printf("   coefficient set %u: %s\n",i,gradientOFiles_[i]->getPath().c_str());
     446             :         }
     447             :       }
     448             :     }
     449             :   }
     450             : 
     451          80 :   std::vector<std::string> hessian_fnames;
     452         160 :   if(keywords.exists("HESSIAN_FILE")) {
     453         150 :     parseFilenames("HESSIAN_FILE",hessian_fnames);
     454         150 :     parse("HESSIAN_OUTPUT",hessian_wstride_);
     455             : 
     456          75 :     if(coeffs_fnames.size()>0) {
     457         207 :       for(unsigned int i=0; i<hessian_fnames.size(); i++) {
     458          66 :         plumed_massert(hessian_fnames[i]!=coeffs_fnames[i],"COEFFS_FILE and HESSIAN_FILE cannot be the same");
     459             :       }
     460             :     }
     461          75 :     if(gradient_fnames.size()>0) {
     462         197 :       for(unsigned int i=0; i<hessian_fnames.size(); i++) {
     463          66 :         plumed_massert(hessian_fnames[i]!=gradient_fnames[i],"GRADIENT_FILE and HESSIAN_FILE cannot be the same");
     464             :       }
     465             :     }
     466          75 :     setupOFiles(hessian_fnames,hessianOFiles_,mw_single_files);
     467         150 :     parse("HESSIAN_FMT",hessian_output_fmt_);
     468             : 
     469          75 :     if(hessian_fnames.size()>0) {
     470          62 :       if(ncoeffssets_==1) {
     471         240 :         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          14 :         for(unsigned int i=0; i<hessian_fnames.size(); i++) {
     476          18 :           log.printf("   coefficient set %u: %s\n",i,hessianOFiles_[i]->getPath().c_str());
     477             :         }
     478             :       }
     479             :     }
     480             :   }
     481             : 
     482             : 
     483             :   //
     484         160 :   if(keywords.exists("MASK_FILE")) {
     485             :     std::vector<std::string> mask_fnames_in;
     486         158 :     parseVector("MASK_FILE",mask_fnames_in);
     487          79 :     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          82 :     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          79 :     coeffs_mask_pntrs_.resize(ncoeffssets_);
     496          85 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
     497         255 :       coeffs_mask_pntrs_[i] = new CoeffsVector(*coeffs_pntrs_[i]);
     498         255 :       coeffs_mask_pntrs_[i]->setLabels("mask");
     499          85 :       coeffs_mask_pntrs_[i]->setValues(1.0);
     500         255 :       coeffs_mask_pntrs_[i]->setOutputFmt("%f");
     501             :     }
     502             : 
     503          79 :     if(mask_fnames_in.size()>0) {
     504           3 :       if(ncoeffssets_==1) {
     505           3 :         size_t nread = coeffs_mask_pntrs_[0]->readFromFile(mask_fnames_in[0],true,true);
     506           3 :         log.printf("  read %zu values from mask file %s\n",nread,mask_fnames_in[0].c_str());
     507           3 :         size_t ndeactived = coeffs_mask_pntrs_[0]->countValues(0.0);
     508           3 :         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 coefficient 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          79 :     std::vector<std::string> mask_fnames_out;
     522         158 :     parseFilenames("OUTPUT_MASK_FILE",mask_fnames_out);
     523             : 
     524         164 :     for(unsigned int i=0; i<mask_fnames_out.size(); i++) {
     525           3 :       if(mask_fnames_in.size()>0) {
     526           3 :         plumed_massert(mask_fnames_out[i]!=mask_fnames_in[i],"MASK_FILE and OUTPUT_MASK_FILE cannot be the same");
     527             :       }
     528           3 :       OFile maskOFile;
     529           3 :       maskOFile.link(*this);
     530           3 :       maskOFile.enforceBackup();
     531           3 :       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           3 :       maskOFile.open(mask_fnames_out[i]);
     539           3 :       coeffs_mask_pntrs_[i]->writeToFile(maskOFile,true);
     540           3 :       maskOFile.close();
     541          82 :     }
     542             :   }
     543             : 
     544         160 :   if(getRestart() && ustride_targetdist_>0) {
     545           8 :     for(unsigned int i=0; i<nbiases_; i++) {
     546          16 :       if(dynamic_targetdists_[i]) {
     547           8 :         bias_pntrs_[i]->restartTargetDistributions();
     548             :       }
     549             :     }
     550             :   }
     551             : 
     552             : 
     553          80 :   std::vector<std::string> targetdist_averages_fnames;
     554         160 :   if(keywords.exists("TARGETDIST_AVERAGES_FILE")) {
     555         240 :     parseFilenames("TARGETDIST_AVERAGES_FILE",targetdist_averages_fnames,"targetdist-averages.data");
     556         160 :     parse("TARGETDIST_AVERAGES_OUTPUT",targetdist_averages_wstride_);
     557             : 
     558          80 :     if(coeffs_fnames.size()>0) {
     559         252 :       for(unsigned int i=0; i<targetdist_averages_fnames.size(); i++) {
     560          86 :         plumed_massert(targetdist_averages_fnames[i]!=coeffs_fnames[i],"COEFFS_FILE and TARGETDIST_AVERAGES_FILE cannot be the same");
     561             :       }
     562             :     }
     563          80 :     if(gradient_fnames.size()>0) {
     564         216 :       for(unsigned int i=0; i<targetdist_averages_fnames.size(); i++) {
     565          74 :         plumed_massert(targetdist_averages_fnames[i]!=gradient_fnames[i],"GRADIENT_FILE and TARGETDIST_AVERAGES_FILE cannot be the same");
     566             :       }
     567             :     }
     568          80 :     if(hessian_fnames.size()>0) {
     569         194 :       for(unsigned int i=0; i<targetdist_averages_fnames.size(); i++) {
     570          66 :         plumed_massert(targetdist_averages_fnames[i]!=hessian_fnames[i],"HESSIAN_FILE and TARGETDIST_AVERAGES_FILE cannot be the same");
     571             :       }
     572             :     }
     573          80 :     setupOFiles(targetdist_averages_fnames,targetdist_averagesOFiles_,mw_single_files);
     574         160 :     parse("TARGETDIST_AVERAGES_FMT",targetdist_averages_output_fmt_);
     575          80 :     if(targetdist_averages_output_fmt_.size()>0) {
     576          82 :       for(unsigned int i=0; i<ncoeffssets_; i++) {
     577         164 :         targetdist_averages_pntrs_[i]->setOutputFmt(targetdist_averages_output_fmt_);
     578             :       }
     579             :     }
     580             : 
     581         252 :     for(unsigned int i=0; i<targetdist_averagesOFiles_.size(); i++) {
     582         172 :       targetdist_averages_pntrs_[i]->writeToFile(*targetdist_averagesOFiles_[i]);
     583             :     }
     584             : 
     585          80 :     if(targetdist_averages_wstride_==0) {
     586         153 :       for(unsigned int i=0; i<targetdist_averagesOFiles_.size(); i++) {
     587          53 :         targetdist_averagesOFiles_[i]->close();
     588          53 :         delete targetdist_averagesOFiles_[i];
     589             :       }
     590             :       targetdist_averagesOFiles_.clear();
     591             :     }
     592             : 
     593          80 :     if(targetdist_averages_fnames.size()>0 && targetdist_averages_wstride_ > 0) {
     594          33 :       if(ncoeffssets_==1) {
     595         132 :         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         160 :   if(keywords.exists("BIAS_OUTPUT")) {
     608         160 :     parse("BIAS_OUTPUT",bias_output_stride_);
     609          80 :     if(bias_output_stride_>0) {
     610          79 :       bias_output_active_=true;
     611         164 :       for(unsigned int i=0; i<nbiases_; i++) {
     612         170 :         bias_pntrs_[i]->enableBiasFileOutput();
     613          85 :         bias_pntrs_[i]->setupBiasFileOutput();
     614          85 :         bias_pntrs_[i]->writeBiasToFile();
     615             :       }
     616             :     }
     617             :     else {
     618           1 :       bias_output_active_=false;
     619           1 :       bias_output_stride_=1000;
     620             :     }
     621             :   }
     622             : 
     623         160 :   if(keywords.exists("FES_OUTPUT")) {
     624         160 :     parse("FES_OUTPUT",fes_output_stride_);
     625          80 :     if(fes_output_stride_>0) {
     626          79 :       fes_output_active_=true;
     627         164 :       for(unsigned int i=0; i<nbiases_; i++) {
     628         170 :         bias_pntrs_[i]->enableFesFileOutput();
     629          85 :         bias_pntrs_[i]->setupFesFileOutput();
     630          85 :         bias_pntrs_[i]->writeFesToFile();
     631             :       }
     632             :     }
     633             :     else {
     634           1 :       fes_output_active_=false;
     635           1 :       fes_output_stride_=1000;
     636             :     }
     637             :   }
     638             : 
     639         160 :   if(keywords.exists("FES_PROJ_OUTPUT")) {
     640         160 :     parse("FES_PROJ_OUTPUT",fesproj_output_stride_);
     641          80 :     if(fesproj_output_stride_>0) {
     642          16 :       fesproj_output_active_=true;
     643          32 :       for(unsigned int i=0; i<nbiases_; i++) {
     644          32 :         bias_pntrs_[i]->enableFesProjFileOutput();
     645          16 :         bias_pntrs_[i]->setupFesProjFileOutput();
     646          16 :         bias_pntrs_[i]->writeFesProjToFile();
     647             :       }
     648             :     }
     649             :     else {
     650          64 :       fesproj_output_active_=false;
     651          64 :       fesproj_output_stride_=1000;
     652             :     }
     653             :   }
     654             : 
     655          86 :   for(unsigned int i=0; i<nbiases_; i++) {
     656         270 :     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         160 :   if(keywords.exists("TARGETDIST_OUTPUT")) {
     665         154 :     parse("TARGETDIST_OUTPUT",targetdist_output_stride_);
     666          77 :     if(targetdist_output_stride_>0) {
     667          36 :       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          36 :       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          36 :       targetdist_output_active_=true;
     675          72 :       for(unsigned int i=0; i<nbiases_; i++) {
     676          72 :         if(dynamic_targetdists_[i]) {
     677          36 :           bias_pntrs_[i]->enableDynamicTargetDistFileOutput();
     678          36 :           bias_pntrs_[i]->setupTargetDistFileOutput();
     679          36 :           bias_pntrs_[i]->writeTargetDistToFile();
     680             :         }
     681             :       }
     682             :     }
     683             :     else {
     684          41 :       targetdist_output_active_=false;
     685          41 :       targetdist_output_stride_=1000;
     686             :     }
     687             :   }
     688             : 
     689         160 :   if(keywords.exists("TARGETDIST_PROJ_OUTPUT")) {
     690         154 :     parse("TARGETDIST_PROJ_OUTPUT",targetdist_proj_output_stride_);
     691          77 :     if(targetdist_proj_output_stride_>0) {
     692           3 :       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           3 :       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           3 :       targetdist_proj_output_active_=true;
     700           6 :       for(unsigned int i=0; i<nbiases_; i++) {
     701           6 :         if(dynamic_targetdists_[i]) {
     702           3 :           bias_pntrs_[i]->enableDynamicTargetDistFileOutput();
     703           3 :           bias_pntrs_[i]->setupTargetDistProjFileOutput();
     704           3 :           bias_pntrs_[i]->writeTargetDistProjToFile();
     705             :         }
     706             :       }
     707             :     }
     708             :     else {
     709          74 :       targetdist_proj_output_active_=false;
     710          74 :       targetdist_proj_output_stride_=1000;
     711             :     }
     712             :   }
     713             : 
     714          80 :   if(ncoeffssets_==1) {
     715          77 :     log.printf("  Output Components:\n");
     716          77 :     log.printf(" ");
     717          77 :     if(monitor_instantaneous_gradient_) {
     718           6 :       addComponent("gradrms"); componentIsNotPeriodic("gradrms");
     719           2 :       log.printf(" ");
     720           6 :       addComponent("gradmax"); componentIsNotPeriodic("gradmax");
     721             :     }
     722          77 :     if(aver_gradient_pntrs_.size()>0) {
     723           2 :       log.printf(" ");
     724           6 :       addComponent("avergradrms"); componentIsNotPeriodic("avergradrms");
     725           2 :       log.printf(" ");
     726           6 :       addComponent("avergradmax"); componentIsNotPeriodic("avergradmax");
     727             :     }
     728          77 :     if(!fixed_stepsize_) {
     729           3 :       log.printf(" ");
     730           9 :       addComponent("stepsize"); componentIsNotPeriodic("stepsize");
     731           6 :       getPntrToComponent("stepsize")->set( getCurrentStepSize(0) );
     732             :     }
     733             :   }
     734             :   else {
     735           9 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
     736           9 :       log.printf("  Output Components for coefficient set %u:\n",i);
     737          27 :       std::string is=""; Tools::convert(i,is); is = "-" + coeffssetid_prefix_ + is;
     738           9 :       log.printf(" ");
     739           9 :       if(monitor_instantaneous_gradient_) {
     740           9 :         addComponent("gradrms"+is); componentIsNotPeriodic("gradrms"+is);
     741           3 :         log.printf(" ");
     742           9 :         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             :     }
     756          80 :   }
     757             : 
     758          80 : }
     759             : 
     760             : 
     761         160 : Optimizer::~Optimizer() {
     762             :   //
     763          80 :   if(!isTargetDistOutputActive()) {
     764          50 :     for(unsigned int i=0; i<nbiases_; i++) {
     765         100 :       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          72 :   else if(isTargetDistOutputActive() && getIterationCounter()%getTargetDistOutputStride()!=0) {
     773           1 :     writeTargetDistOutputFiles();
     774             :   }
     775             :   //
     776         252 :   for(unsigned int i=0; i<aux_coeffs_pntrs_.size(); i++) {
     777          86 :     delete aux_coeffs_pntrs_[i];
     778             :   }
     779             :   aux_coeffs_pntrs_.clear();
     780             :   //
     781         164 :   for(unsigned int i=0; i<aver_gradient_pntrs_.size(); i++) {
     782           2 :     delete aver_gradient_pntrs_[i];
     783             :   }
     784             :   aver_gradient_pntrs_.clear();
     785             :   //
     786         330 :   for(unsigned int i=0; i<coeffs_mask_pntrs_.size(); i++) {
     787          85 :     delete coeffs_mask_pntrs_[i];
     788             :   }
     789             :   coeffs_mask_pntrs_.clear();
     790             :   //
     791         330 :   for(unsigned int i=0; i<coeffsOFiles_.size(); i++) {
     792          85 :     coeffsOFiles_[i]->close();
     793          85 :     delete coeffsOFiles_[i];
     794             :   }
     795             :   coeffsOFiles_.clear();
     796         308 :   for(unsigned int i=0; i<gradientOFiles_.size(); i++) {
     797          74 :     gradientOFiles_[i]->close();
     798          74 :     delete gradientOFiles_[i];
     799             :   }
     800             :   gradientOFiles_.clear();
     801         292 :   for(unsigned int i=0; i<hessianOFiles_.size(); i++) {
     802          66 :     hessianOFiles_[i]->close();
     803          66 :     delete hessianOFiles_[i];
     804             :   }
     805             :   hessianOFiles_.clear();
     806         226 :   for(unsigned int i=0; i<targetdist_averagesOFiles_.size(); i++) {
     807          33 :     targetdist_averagesOFiles_[i]->close();
     808          33 :     delete targetdist_averagesOFiles_[i];
     809             :   }
     810             :   targetdist_averagesOFiles_.clear();
     811          80 : }
     812             : 
     813             : 
     814          84 : void Optimizer::registerKeywords( Keywords& keys ) {
     815          84 :   Action::registerKeywords(keys);
     816          84 :   ActionPilot::registerKeywords(keys);
     817          84 :   ActionWithValue::registerKeywords(keys);
     818             :   //
     819         168 :   keys.remove("NUMERICAL_DERIVATIVES");
     820             :   // Default always active keywords
     821         336 :   keys.add("compulsory","BIAS","the label of the VES bias to be optimized");
     822         336 :   keys.add("compulsory","STRIDE","the frequency of updating the coefficients given in the number of MD steps.");
     823         420 :   keys.add("compulsory","COEFFS_FILE","coeffs.data","the name of output file for the coefficients");
     824         420 :   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         336 :   keys.add("optional","COEFFS_FMT","specify format for coefficient file(s) (useful for decrease the number of digits in regtests)");
     826         336 :   keys.add("optional","COEFFS_SET_ID_PREFIX","suffix to add to the filename given in FILE to identify the bias, should only be given if a single filename is given in FILE when optimizing multiple biases.");
     827             :   //
     828         336 :   keys.add("optional","INITIAL_COEFFS","the name(s) of file(s) with the initial coefficients");
     829             :   // Hidden keywords to output the gradient to a file.
     830         336 :   keys.add("hidden","GRADIENT_FILE","the name of output file for the gradient");
     831         336 :   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         336 :   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         336 :   keys.reserve("compulsory","STEPSIZE","the step size used for the optimization");
     835         336 :   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         252 :   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         336 :   keys.reserve("hidden","HESSIAN_FILE","the name of output file for the Hessian");
     839         336 :   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         336 :   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         252 :   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         336 :   keys.reserve("optional","MASK_FILE","read in a mask file which allows one to employ different step sizes for different coefficients and/or deactivate 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         336 :   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         252 :   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         252 :   keys.addFlag("MONITOR_INSTANTANEOUS_GRADIENT",false,"if quantities related to the instantaneous gradient should be outputted.");
     850             :   //
     851         252 :   keys.reserveFlag("MONITOR_AVERAGE_GRADIENT",false,"if the averaged gradient should be monitored and quantities related to it should be outputted.");
     852         336 :   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         336 :   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 coefficient iterations.");
     855         336 :   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 coefficient iterations.");
     856         336 :   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 coefficient iterations.");
     857             :   //
     858         336 :   keys.add("optional","TARGETDIST_AVERAGES_FILE","the name of output file for the target distribution averages. By default it is targetdist-averages.data.");
     859         336 :   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 coefficient iterations. If no value is given are the averages only written at the beginning of the optimization");
     860         336 :   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         336 :   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 coefficient iterations.");
     863         336 :   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 coefficient iterations.");
     864         336 :   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 coefficient iterations.");
     865             :   //
     866         336 :   keys.reserve("optional","REWEIGHT_FACTOR_STRIDE","stride for updating the reweighting factor c(t). Note that the value is given in terms of coefficient iterations.");
     867             :   //
     868         168 :   keys.use("RESTART");
     869             :   //
     870         168 :   keys.use("UPDATE_FROM");
     871         168 :   keys.use("UPDATE_UNTIL");
     872             :   // Components that are always active
     873         336 :   keys.addOutputComponent("gradrms","MONITOR_INSTANTANEOUS_GRADIENT","the root mean square value of the coefficient gradient. For multiple biases this component is labeled using the number of the bias as gradrms-#.");
     874         336 :   keys.addOutputComponent("gradmax","MONITOR_INSTANTANEOUS_GRADIENT","the largest absolute value of the coefficient gradient. For multiple biases this component is labeled using the number of the bias as gradmax-#.");
     875             :   // keys.addOutputComponent("gradmaxidx","default","the index of the maximum absolute value of the gradient");
     876             : 
     877          84 : }
     878             : 
     879             : 
     880          77 : void Optimizer::useHessianKeywords(Keywords& keys) {
     881             :   // keys.use("FULL_HESSIAN");
     882         154 :   keys.use("HESSIAN_FILE");
     883         154 :   keys.use("HESSIAN_OUTPUT");
     884         154 :   keys.use("HESSIAN_FMT");
     885          77 : }
     886             : 
     887             : 
     888          84 : void Optimizer::useMultipleWalkersKeywords(Keywords& keys) {
     889         168 :   keys.use("MULTIPLE_WALKERS");
     890          84 : }
     891             : 
     892             : 
     893          78 : void Optimizer::useFixedStepSizeKeywords(Keywords& keys) {
     894         156 :   keys.use("STEPSIZE");
     895          78 : }
     896             : 
     897             : 
     898           4 : void Optimizer::useDynamicStepSizeKeywords(Keywords& keys) {
     899           8 :   keys.use("INITIAL_STEPSIZE");
     900          16 :   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-#.");
     901           4 : }
     902             : 
     903             : 
     904          82 : void Optimizer::useMaskKeywords(Keywords& keys) {
     905         164 :   keys.use("MASK_FILE");
     906         164 :   keys.use("OUTPUT_MASK_FILE");
     907          82 : }
     908             : 
     909             : 
     910          79 : void Optimizer::useRestartKeywords(Keywords& keys) {
     911         158 :   keys.use("START_OPTIMIZATION_AFRESH");
     912          79 : }
     913             : 
     914             : 
     915          77 : void Optimizer::useMonitorAverageGradientKeywords(Keywords& keys) {
     916         154 :   keys.use("MONITOR_AVERAGE_GRADIENT");
     917         154 :   keys.use("MONITOR_AVERAGES_GRADIENT_EXP_DECAY");
     918         308 :   keys.addOutputComponent("avergradrms","MONITOR_AVERAGE_GRADIENT","the root mean square value of the averaged coefficient gradient. For multiple biases this component is labeled using the number of the bias as gradrms-#.");
     919         308 :   keys.addOutputComponent("avergradmax","MONITOR_AVERAGE_GRADIENT","the largest absolute value of the averaged coefficient gradient. For multiple biases this component is labeled using the number of the bias as gradmax-#.");
     920          77 : }
     921             : 
     922             : 
     923          79 : void Optimizer::useDynamicTargetDistributionKeywords(Keywords& keys) {
     924         158 :   keys.use("TARGETDIST_STRIDE");
     925         158 :   keys.use("TARGETDIST_OUTPUT");
     926         158 :   keys.use("TARGETDIST_PROJ_OUTPUT");
     927          79 : }
     928             : 
     929             : 
     930           0 : void Optimizer::useReweightFactorKeywords(Keywords& keys) {
     931           0 :   keys.use("REWEIGHT_FACTOR_STRIDE");
     932           0 : }
     933             : 
     934             : 
     935          75 : void Optimizer::turnOnHessian() {
     936          75 :   plumed_massert(hessian_pntrs_.size()==0,"turnOnHessian() should only be run during initialization");
     937          75 :   use_hessian_=true;
     938             :   hessian_pntrs_.clear();
     939         156 :   for(unsigned int i=0; i<nbiases_; i++) {
     940         162 :     std::vector<CoeffsMatrix*> pntrs_hessian = enableHessian(bias_pntrs_[i],diagonal_hessian_);
     941         243 :     for(unsigned int k=0; k<pntrs_hessian.size(); k++) {
     942          81 :       pntrs_hessian[k]->turnOnIterationCounter();
     943         162 :       pntrs_hessian[k]->setIterationCounterAndTime(getIterationCounter(),getTime());
     944          81 :       hessian_pntrs_.push_back(pntrs_hessian[k]);
     945             :     }
     946             :   }
     947          75 :   plumed_massert(hessian_pntrs_.size()==ncoeffssets_,"problems in linking Hessians");
     948          75 :   if(diagonal_hessian_) {
     949          75 :     log.printf("  Optimization performed using diagonal Hessian matrix\n");
     950             :   }
     951             :   else {
     952           0 :     log.printf("  Optimization performed using full Hessian matrix\n");
     953             :   }
     954             :   //
     955          75 :   if(hessian_output_fmt_.size()>0) {
     956          66 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
     957         132 :       hessian_pntrs_[i]->setOutputFmt(hessian_output_fmt_);
     958             :     }
     959             :   }
     960             : 
     961          75 : }
     962             : 
     963             : 
     964           0 : void Optimizer::turnOffHessian() {
     965           0 :   use_hessian_=false;
     966           0 :   for(unsigned int i=0; i<nbiases_; i++) {
     967           0 :     bias_pntrs_[i]->disableHessian();
     968             :   }
     969             :   hessian_pntrs_.clear();
     970           0 :   for(unsigned int i=0; i<hessianOFiles_.size(); i++) {
     971           0 :     hessianOFiles_[i]->close();
     972           0 :     delete hessianOFiles_[i];
     973             :   }
     974             :   hessianOFiles_.clear();
     975           0 : }
     976             : 
     977             : 
     978          81 : std::vector<CoeffsMatrix*> Optimizer::enableHessian(VesBias* bias_pntr_in, const bool diagonal_hessian) {
     979          81 :   plumed_massert(use_hessian_,"the Hessian should not be used");
     980          81 :   bias_pntr_in->enableHessian(diagonal_hessian);
     981             :   std::vector<CoeffsMatrix*> hessian_pntrs_out = bias_pntr_in->getHessianPntrs();
     982         324 :   for(unsigned int k=0; k<hessian_pntrs_out.size(); k++) {
     983          81 :     plumed_massert(hessian_pntrs_out[k] != NULL,"Hessian is needed but not linked correctly");
     984             :   }
     985          81 :   return hessian_pntrs_out;
     986             : }
     987             : 
     988             : 
     989             : // CoeffsMatrix* Optimizer::switchToDiagonalHessian(VesBias* bias_pntr_in) {
     990             : //   plumed_massert(use_hessian_,"it does not make sense to switch to diagonal Hessian if it Hessian is not used");
     991             : //   diagonal_hessian_=true;
     992             : //   bias_pntr_in->enableHessian(diagonal_hessian_);
     993             : //   CoeffsMatrix* hessian_pntr_out = bias_pntr_in->getHessianPntr();
     994             : //   plumed_massert(hessian_pntr_out != NULL,"Hessian is needed but not linked correctly");
     995             : //   //
     996             : //   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());
     997             : //   return hessian_pntr_out;
     998             : // }
     999             : 
    1000             : 
    1001             : // CoeffsMatrix* Optimizer::switchToFullHessian(VesBias* bias_pntr_in) {
    1002             : //   plumed_massert(use_hessian_,"it does not make sense to switch to diagonal Hessian if it Hessian is not used");
    1003             : //   diagonal_hessian_=false;
    1004             : //   bias_pntr_in->enableHessian(diagonal_hessian_);
    1005             : //   CoeffsMatrix* hessian_pntr_out = bias_pntr_in->getHessianPntr();
    1006             : //   plumed_massert(hessian_pntr_out != NULL,"Hessian is needed but not linked correctly");
    1007             : //   //
    1008             : //   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());
    1009             : //   return hessian_pntr_out;
    1010             : // }
    1011             : 
    1012             : 
    1013       40910 : void Optimizer::update() {
    1014       40910 :   if(onStep() && !isFirstStep) {
    1015       40820 :     for(unsigned int i=0; i<nbiases_; i++) {
    1016       81640 :       bias_pntrs_[i]->updateGradientAndHessian(use_mwalkers_mpi_);
    1017             :     }
    1018       40820 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
    1019      122460 :       if(gradient_pntrs_[i]->isActive()) {coeffsUpdate(i);}
    1020             :       else {
    1021         500 :         std::string msg = "iteration " + getIterationCounterStr(+1) +
    1022         250 :                           " for " + bias_pntrs_[i]->getLabel() +
    1023             :                           " - the coefficients are not updated as CV values are outside the bias intervals";
    1024         125 :         warning(msg);
    1025             :       }
    1026             : 
    1027             :       // +1 as this is done before increaseIterationCounter() is used
    1028       40820 :       unsigned int curr_iter = getIterationCounter()+1;
    1029       40820 :       double curr_time = getTime();
    1030       40820 :       coeffs_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1031       40820 :       aux_coeffs_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1032       40820 :       gradient_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1033       40820 :       targetdist_averages_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1034       40820 :       if(use_hessian_) {
    1035       40770 :         hessian_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1036             :       }
    1037       40820 :       if(aver_gradient_pntrs_.size()>0) {
    1038          20 :         aver_gradient_pntrs_[i]->setIterationCounterAndTime(curr_iter,curr_time);
    1039          40 :         aver_gradient_pntrs_[i]->addToAverage(*gradient_pntrs_[i]);
    1040             :       }
    1041             :     }
    1042             :     increaseIterationCounter();
    1043       40760 :     updateOutputComponents();
    1044       81580 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
    1045       40820 :       writeOutputFiles(i);
    1046             :     }
    1047       81090 :     if(ustride_targetdist_>0 && getIterationCounter()%ustride_targetdist_==0) {
    1048         346 :       for(unsigned int i=0; i<nbiases_; i++) {
    1049         692 :         if(dynamic_targetdists_[i]) {
    1050         346 :           bias_pntrs_[i]->updateTargetDistributions();
    1051             :         }
    1052             :       }
    1053             :     }
    1054       40760 :     if(ustride_reweightfactor_>0 && getIterationCounter()%ustride_reweightfactor_==0) {
    1055           0 :       for(unsigned int i=0; i<nbiases_; i++) {
    1056           0 :         bias_pntrs_[i]->updateReweightFactor();
    1057             :       }
    1058             :     }
    1059             : 
    1060             : 
    1061             :     //
    1062       81510 :     if(isBiasOutputActive() && getIterationCounter()%getBiasOutputStride()==0) {
    1063          79 :       writeBiasOutputFiles();
    1064             :     }
    1065       81510 :     if(isFesOutputActive() && getIterationCounter()%getFesOutputStride()==0) {
    1066          79 :       writeFesOutputFiles();
    1067             :     }
    1068       40920 :     if(isFesProjOutputActive() && getIterationCounter()%getFesProjOutputStride()==0) {
    1069          16 :       writeFesProjOutputFiles();
    1070             :     }
    1071       81080 :     if(isTargetDistOutputActive() && getIterationCounter()%getTargetDistOutputStride()==0) {
    1072          35 :       writeTargetDistOutputFiles();
    1073             :     }
    1074       40790 :     if(isTargetDistProjOutputActive() && getIterationCounter()%getTargetDistProjOutputStride()==0) {
    1075           3 :       writeTargetDistProjOutputFiles();
    1076             :     }
    1077             :   }
    1078             :   else {
    1079         150 :     isFirstStep=false;
    1080             :   }
    1081       40910 : }
    1082             : 
    1083             : 
    1084       40760 : void Optimizer::updateOutputComponents() {
    1085       40760 :   if(ncoeffssets_==1) {
    1086       40730 :     if(!fixed_stepsize_) {
    1087          60 :       getPntrToComponent("stepsize")->set( getCurrentStepSize(0) );
    1088             :     }
    1089       40730 :     if(monitor_instantaneous_gradient_) {
    1090          40 :       getPntrToComponent("gradrms")->set( gradient_pntrs_[0]->getRMS() );
    1091          20 :       size_t gradient_maxabs_idx=0;
    1092          40 :       getPntrToComponent("gradmax")->set( gradient_pntrs_[0]->getMaxAbsValue(gradient_maxabs_idx) );
    1093             :     }
    1094       40730 :     if(aver_gradient_pntrs_.size()>0) {
    1095          40 :       getPntrToComponent("avergradrms")->set( aver_gradient_pntrs_[0]->getRMS() );
    1096          20 :       size_t avergradient_maxabs_idx=0;
    1097          40 :       getPntrToComponent("avergradmax")->set( aver_gradient_pntrs_[0]->getMaxAbsValue(avergradient_maxabs_idx) );
    1098             :     }
    1099             :   }
    1100             :   else {
    1101          90 :     for(unsigned int i=0; i<ncoeffssets_; i++) {
    1102         270 :       std::string is=""; Tools::convert(i,is); is = "-" + coeffssetid_prefix_ + is;
    1103          90 :       if(!fixed_stepsize_) {
    1104           0 :         getPntrToComponent("stepsize"+is)->set( getCurrentStepSize(i) );
    1105             :       }
    1106          90 :       if(monitor_instantaneous_gradient_) {
    1107          90 :         getPntrToComponent("gradrms"+is)->set( gradient_pntrs_[i]->getRMS() );
    1108          30 :         size_t gradient_maxabs_idx=0;
    1109          60 :         getPntrToComponent("gradmax"+is)->set( gradient_pntrs_[i]->getMaxAbsValue(gradient_maxabs_idx) );
    1110             :       }
    1111          90 :       if(aver_gradient_pntrs_.size()>0) {
    1112           0 :         getPntrToComponent("avergradrms"+is)->set( aver_gradient_pntrs_[0]->getRMS() );
    1113           0 :         size_t avergradient_maxabs_idx=0;
    1114           0 :         getPntrToComponent("avergradmax"+is)->set( aver_gradient_pntrs_[0]->getMaxAbsValue(avergradient_maxabs_idx) );
    1115             :       }
    1116             :     }
    1117             :   }
    1118       40760 : }
    1119             : 
    1120             : 
    1121           1 : void Optimizer::turnOffCoeffsOutputFiles() {
    1122           4 :   for(unsigned int i=0; i<coeffsOFiles_.size(); i++) {
    1123           1 :     coeffsOFiles_[i]->close();
    1124           1 :     delete coeffsOFiles_[i];
    1125             :   }
    1126             :   coeffsOFiles_.clear();
    1127           1 : }
    1128             : 
    1129             : 
    1130       40820 : void Optimizer::writeOutputFiles(const unsigned int coeffs_id) {
    1131       40820 :   if(coeffsOFiles_.size()>0 && iter_counter%coeffs_wstride_==0) {
    1132        3232 :     coeffs_pntrs_[coeffs_id]->writeToFile(*coeffsOFiles_[coeffs_id],aux_coeffs_pntrs_[coeffs_id],false);
    1133             :   }
    1134       40820 :   if(gradientOFiles_.size()>0 && iter_counter%gradient_wstride_==0) {
    1135         740 :     if(aver_gradient_pntrs_.size()==0) {
    1136        2160 :       gradient_pntrs_[coeffs_id]->writeToFile(*gradientOFiles_[coeffs_id],false);
    1137             :     }
    1138             :     else {
    1139          80 :       gradient_pntrs_[coeffs_id]->writeToFile(*gradientOFiles_[coeffs_id],aver_gradient_pntrs_[coeffs_id],false);
    1140             :     }
    1141             :   }
    1142       40820 :   if(hessianOFiles_.size()>0 && iter_counter%hessian_wstride_==0) {
    1143        1980 :     hessian_pntrs_[coeffs_id]->writeToFile(*hessianOFiles_[coeffs_id]);
    1144             :   }
    1145       40820 :   if(targetdist_averagesOFiles_.size()>0 && iter_counter%targetdist_averages_wstride_==0) {
    1146         990 :     targetdist_averages_pntrs_[coeffs_id]->writeToFile(*targetdist_averagesOFiles_[coeffs_id]);
    1147             :   }
    1148       40820 : }
    1149             : 
    1150             : 
    1151         389 : void Optimizer::setupOFiles(std::vector<std::string>& fnames, std::vector<OFile*>& OFiles, const bool multi_sim_single_files) {
    1152         389 :   plumed_assert(ncoeffssets_>0);
    1153         778 :   OFiles.resize(fnames.size(),NULL);
    1154        1414 :   for(unsigned int i=0; i<fnames.size(); i++) {
    1155         636 :     OFiles[i] = new OFile();
    1156         636 :     OFiles[i]->link(*this);
    1157         318 :     if(multi_sim_single_files) {
    1158          48 :       unsigned int r=0;
    1159          48 :       if(comm.Get_rank()==0) {r=multi_sim_comm.Get_rank();}
    1160          48 :       comm.Bcast(r,0);
    1161          48 :       if(r>0) {fnames[i]="/dev/null";}
    1162         144 :       OFiles[i]->enforceSuffix("");
    1163             :     }
    1164         636 :     OFiles[i]->open(fnames[i]);
    1165         318 :     OFiles[i]->setHeavyFlush();
    1166             :   }
    1167         389 : }
    1168             : 
    1169             : 
    1170          14 : void Optimizer::readCoeffsFromFiles(const std::vector<std::string>& fnames, const bool read_aux_coeffs) {
    1171          14 :   plumed_assert(ncoeffssets_>0);
    1172          14 :   plumed_assert(fnames.size()==ncoeffssets_);
    1173          14 :   if(ncoeffssets_==1) {
    1174          13 :     log.printf("  Read in coefficients from file ");
    1175             :   }
    1176             :   else {
    1177           1 :     log.printf("  Read in coefficients from files:\n");
    1178             :   }
    1179          16 :   for(unsigned int i=0; i<ncoeffssets_; i++) {
    1180          16 :     IFile ifile;
    1181          16 :     ifile.link(*this);
    1182          16 :     if(use_mwalkers_mpi_ && mwalkers_mpi_single_files_) {
    1183           8 :       ifile.enforceSuffix("");
    1184             :     }
    1185          32 :     ifile.open(fnames[i]);
    1186          48 :     if(!ifile.FieldExist(coeffs_pntrs_[i]->getDataLabel())) {
    1187           0 :       std::string error_msg = "Problem with reading coefficients from file " + ifile.getPath() + ": no field with name " + coeffs_pntrs_[i]->getDataLabel() + "\n";
    1188           0 :       plumed_merror(error_msg);
    1189             :     }
    1190          16 :     size_t ncoeffs_read = coeffs_pntrs_[i]->readFromFile(ifile,false,false);
    1191          16 :     if(ncoeffssets_==1) {
    1192          39 :       log.printf("%s (read %zu of %zu values)\n", ifile.getPath().c_str(),ncoeffs_read,coeffs_pntrs_[i]->numberOfCoeffs());
    1193             :     }
    1194             :     else {
    1195           9 :       log.printf("   coefficient set %u: %s (read %zu of %zu values)\n",i,ifile.getPath().c_str(),ncoeffs_read,coeffs_pntrs_[i]->numberOfCoeffs());
    1196             :     }
    1197          16 :     ifile.close();
    1198          16 :     if(read_aux_coeffs) {
    1199          15 :       ifile.open(fnames[i]);
    1200          45 :       if(!ifile.FieldExist(aux_coeffs_pntrs_[i]->getDataLabel())) {
    1201           0 :         std::string error_msg = "Problem with reading coefficients from file " + ifile.getPath() + ": no field with name " + aux_coeffs_pntrs_[i]->getDataLabel() + "\n";
    1202           0 :         plumed_merror(error_msg);
    1203             :       }
    1204          15 :       aux_coeffs_pntrs_[i]->readFromFile(ifile,false,false);
    1205          15 :       ifile.close();
    1206             :     }
    1207             :     else {
    1208           1 :       AuxCoeffs(i).setValues( Coeffs(i) );
    1209             :     }
    1210          16 :   }
    1211          14 : }
    1212             : 
    1213             : 
    1214          86 : void Optimizer::addCoeffsSetIDsToFilenames(std::vector<std::string>& fnames, std::string& coeffssetid_prefix) {
    1215         172 :   if(ncoeffssets_==1) {return;}
    1216             :   //
    1217           9 :   if(fnames.size()==1) {
    1218           0 :     fnames.resize(ncoeffssets_,fnames[0]);
    1219             :   }
    1220           9 :   plumed_assert(fnames.size()==ncoeffssets_);
    1221             :   //
    1222          27 :   for(unsigned int i=0; i<ncoeffssets_; i++) {
    1223          27 :     std::string is=""; Tools::convert(i,is);
    1224         162 :     fnames[i] = FileBase::appendSuffix(fnames[i],"."+coeffssetid_prefix_+is);
    1225             :   }
    1226             : }
    1227             : 
    1228             : 
    1229          94 : void Optimizer::setAllCoeffsSetIterationCounters() {
    1230         196 :   for(unsigned int i=0; i<ncoeffssets_; i++) {
    1231         306 :     coeffs_pntrs_[i]->setIterationCounterAndTime(getIterationCounter(),getTime());
    1232         204 :     aux_coeffs_pntrs_[i]->setIterationCounterAndTime(getIterationCounter(),getTime());
    1233         204 :     gradient_pntrs_[i]->setIterationCounterAndTime(getIterationCounter(),getTime());
    1234         204 :     targetdist_averages_pntrs_[i]->setIterationCounterAndTime(getIterationCounter(),getTime());
    1235         102 :     if(use_hessian_) {
    1236           0 :       hessian_pntrs_[i]->setIterationCounterAndTime(getIterationCounter(),getTime());
    1237             :     }
    1238             :   }
    1239          94 : }
    1240             : 
    1241             : 
    1242         125 : std::string Optimizer::getIterationCounterStr(const int offset) const {
    1243             :   std::string s;
    1244         125 :   Tools::convert(getIterationCounter()+offset,s);
    1245         125 :   return s;
    1246             : }
    1247             : 
    1248             : 
    1249          79 : void Optimizer::writeBiasOutputFiles() const {
    1250         164 :   for(unsigned int i=0; i<nbiases_; i++) {
    1251         170 :     bias_pntrs_[i]->writeBiasToFile();
    1252             :   }
    1253          79 : }
    1254             : 
    1255             : 
    1256          79 : void Optimizer::writeFesOutputFiles() const {
    1257         164 :   for(unsigned int i=0; i<nbiases_; i++) {
    1258         170 :     bias_pntrs_[i]->writeFesToFile();
    1259             :   }
    1260          79 : }
    1261             : 
    1262             : 
    1263          16 : void Optimizer::writeFesProjOutputFiles() const {
    1264          32 :   for(unsigned int i=0; i<nbiases_; i++) {
    1265          32 :     bias_pntrs_[i]->writeFesProjToFile();
    1266             :   }
    1267          16 : }
    1268             : 
    1269             : 
    1270          36 : void Optimizer::writeTargetDistOutputFiles() const {
    1271          72 :   for(unsigned int i=0; i<nbiases_; i++) {
    1272          72 :     if(dynamic_targetdists_[i]) {
    1273          36 :       bias_pntrs_[i]->writeTargetDistToFile();
    1274             :     }
    1275             :   }
    1276          36 : }
    1277             : 
    1278             : 
    1279           3 : void Optimizer::writeTargetDistProjOutputFiles() const {
    1280           6 :   for(unsigned int i=0; i<nbiases_; i++) {
    1281           6 :     if(dynamic_targetdists_[i]) {
    1282           3 :       bias_pntrs_[i]->writeTargetDistProjToFile();
    1283             :     }
    1284             :   }
    1285           3 : }
    1286             : 
    1287             : 
    1288             : 
    1289             : }
    1290        5874 : }

Generated by: LCOV version 1.14