LCOV - code coverage report
Current view: top level - ves - BasisFunctions.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 238 276 86.2 %
Date: 2025-04-08 21:11:17 Functions: 17 21 81.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2016-2021 The VES code team
       3             :    (see the PEOPLE-VES file at the root of this folder for a list of names)
       4             : 
       5             :    See http://www.ves-code.org for more information.
       6             : 
       7             :    This file is part of VES code module.
       8             : 
       9             :    The VES code module is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    The VES code module is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with the VES code module.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : 
      23             : #include "BasisFunctions.h"
      24             : #include "TargetDistribution.h"
      25             : #include "VesBias.h"
      26             : #include "VesTools.h"
      27             : #include "GridIntegrationWeights.h"
      28             : 
      29             : #include "tools/Grid.h"
      30             : #include "tools/Tools.h"
      31             : 
      32             : 
      33             : namespace PLMD {
      34             : namespace ves {
      35             : 
      36         271 : void BasisFunctions::registerKeywords(Keywords& keys) {
      37         271 :   Action::registerKeywords(keys);
      38         271 :   keys.add("compulsory","ORDER","The order of the basis function expansion.");
      39         271 :   keys.add("compulsory","MINIMUM","The minimum of the interval on which the basis functions are defined.");
      40         271 :   keys.add("compulsory","MAXIMUM","The maximum of the interval on which the basis functions are defined.");
      41         271 :   keys.add("hidden","NGRID_POINTS","The number of grid points used for numerical integrals");
      42         271 :   keys.addFlag("DEBUG_INFO",false,"Print out more detailed information about the basis set. Useful for debugging.");
      43         271 :   keys.addFlag("NUMERICAL_INTEGRALS",false,"Calculate basis function integral for the uniform distribution numerically. Useful for debugging.");
      44         271 : }
      45             : 
      46             : 
      47         249 : BasisFunctions::BasisFunctions(const ActionOptions&ao):
      48             :   Action(ao),
      49         249 :   print_debug_info_(false),
      50         249 :   has_been_set(false),
      51         498 :   description_("Undefined"),
      52         249 :   type_("Undefined"),
      53         249 :   norder_(0),
      54         249 :   nbasis_(1),
      55         249 :   bf_label_prefix_("f"),
      56         249 :   bf_labels_(nbasis_,"f0"),
      57         249 :   periodic_(false),
      58         249 :   interval_bounded_(true),
      59         249 :   interval_intrinsic_min_str_("1.0"),
      60         249 :   interval_intrinsic_max_str_("-1.0"),
      61         249 :   interval_intrinsic_min_(1.0),
      62         249 :   interval_intrinsic_max_(-1.0),
      63         249 :   interval_intrinsic_range_(0.0),
      64         249 :   interval_intrinsic_mean_(0.0),
      65         249 :   interval_min_str_(""),
      66         249 :   interval_max_str_(""),
      67         249 :   interval_min_(0.0),
      68         249 :   interval_max_(0.0),
      69         249 :   interval_range_(0.0),
      70         249 :   interval_mean_(0.0),
      71         249 :   argT_derivf_(1.0),
      72         249 :   numerical_uniform_integrals_(false),
      73         249 :   nbins_(1001),
      74         249 :   uniform_integrals_(nbasis_,0.0),
      75         249 :   vesbias_pntr_(NULL),
      76         747 :   action_pntr_(NULL) {
      77         249 :   bf_keywords_.push_back(getName());
      78         249 :   if(keywords.exists("ORDER")) {
      79         237 :     parse("ORDER",norder_);
      80         474 :     addKeywordToList("ORDER",norder_);
      81             :   }
      82         249 :   nbasis_=norder_+1;
      83             :   //
      84             :   std::string str_imin;
      85             :   std::string str_imax;
      86         249 :   if(keywords.exists("MINIMUM") && keywords.exists("MAXIMUM")) {
      87         247 :     parse("MINIMUM",str_imin);
      88         494 :     addKeywordToList("MINIMUM",str_imin);
      89         247 :     parse("MAXIMUM",str_imax);
      90         494 :     addKeywordToList("MAXIMUM",str_imax);
      91             :   } else {
      92             :     str_imin = "-1.0";
      93             :     str_imax = "1.0";
      94             :   }
      95             :   interval_min_str_ = str_imin;
      96             :   interval_max_str_ = str_imax;
      97         249 :   if(!Tools::convertNoexcept(str_imin,interval_min_)) {
      98           0 :     plumed_merror(getName()+": cannot convert the value given in MINIMUM to a double");
      99             :   }
     100         249 :   if(!Tools::convertNoexcept(str_imax,interval_max_)) {
     101           0 :     plumed_merror(getName()+": cannot convert the value given in MAXIMUM to a double");
     102             :   }
     103         249 :   if(interval_min_>interval_max_) {
     104           0 :     plumed_merror(getName()+": MINIMUM and MAXIMUM are not correctly defined");
     105             :   }
     106             :   //
     107         249 :   parseFlag("DEBUG_INFO",print_debug_info_);
     108         249 :   if(keywords.exists("NUMERICAL_INTEGRALS")) {
     109         336 :     parseFlag("NUMERICAL_INTEGRALS",numerical_uniform_integrals_);
     110             :   }
     111         249 :   if(keywords.exists("NGRID_POINTS")) {
     112         494 :     parse("NGRID_POINTS",nbins_);
     113             :   }
     114             :   // log.printf(" %s \n",getKeywordString().c_str());
     115             : 
     116         249 : }
     117             : 
     118             : 
     119          79 : void BasisFunctions::setIntrinsicInterval(const double interval_intrinsic_min_in, const double interval_intrinsic_max_in) {
     120          79 :   interval_intrinsic_min_ = interval_intrinsic_min_in;
     121          79 :   interval_intrinsic_max_ = interval_intrinsic_max_in;
     122          79 :   VesTools::convertDbl2Str(interval_intrinsic_min_,interval_intrinsic_min_str_);
     123          79 :   VesTools::convertDbl2Str(interval_intrinsic_max_,interval_intrinsic_max_str_);
     124          79 :   plumed_massert(interval_intrinsic_min_<interval_intrinsic_max_,"setIntrinsicInterval: intrinsic intervals are not defined correctly");
     125          79 : }
     126             : 
     127             : 
     128         170 : void BasisFunctions::setIntrinsicInterval(const std::string& interval_intrinsic_min_str_in, const std::string& interval_intrinsic_max_str_in) {
     129         170 :   interval_intrinsic_min_str_ = interval_intrinsic_min_str_in;
     130         170 :   interval_intrinsic_max_str_ = interval_intrinsic_max_str_in;
     131         170 :   if(!Tools::convertNoexcept(interval_intrinsic_min_str_,interval_intrinsic_min_)) {
     132           0 :     plumed_merror("setIntrinsicInterval: cannot convert string value given for the minimum of the intrinsic interval to a double");
     133             :   }
     134         170 :   if(!Tools::convertNoexcept(interval_intrinsic_max_str_,interval_intrinsic_max_)) {
     135           0 :     plumed_merror("setIntrinsicInterval: cannot convert string value given for the maximum of the intrinsic interval to a double");
     136             :   }
     137         170 :   plumed_massert(interval_intrinsic_min_<interval_intrinsic_max_,"setIntrinsicInterval: intrinsic intervals are not defined correctly");
     138         170 : }
     139             : 
     140             : 
     141           0 : void BasisFunctions::setInterval(const double interval_min_in, const double interval_max_in) {
     142           0 :   interval_min_ = interval_min_in;
     143           0 :   interval_max_ = interval_max_in;
     144           0 :   VesTools::convertDbl2Str(interval_min_,interval_min_str_);
     145           0 :   VesTools::convertDbl2Str(interval_max_,interval_max_str_);
     146           0 :   plumed_massert(interval_min_<interval_max_,"setInterval: intervals are not defined correctly");
     147           0 : }
     148             : 
     149             : 
     150           2 : void BasisFunctions::setInterval(const std::string& interval_min_str_in, const std::string& interval_max_str_in) {
     151           2 :   interval_min_str_ = interval_min_str_in;
     152           2 :   interval_max_str_ = interval_max_str_in;
     153           2 :   if(!Tools::convertNoexcept(interval_min_str_,interval_min_)) {
     154           0 :     plumed_merror("setInterval: cannot convert string value given for the minimum of the interval to a double");
     155             :   }
     156           2 :   if(!Tools::convertNoexcept(interval_max_str_,interval_max_)) {
     157           0 :     plumed_merror("setInterval: cannot convert string value given for the maximum of the interval to a double");
     158             :   }
     159           2 :   plumed_massert(interval_min_<interval_max_,"setInterval: intervals are not defined correctly");
     160           2 : }
     161             : 
     162             : 
     163         249 : void BasisFunctions::setupInterval() {
     164             :   // if(!intervalBounded()){plumed_merror("setupInterval() only works for bounded interval");}
     165         249 :   interval_intrinsic_range_ = interval_intrinsic_max_-interval_intrinsic_min_;
     166         249 :   interval_intrinsic_mean_  = 0.5*(interval_intrinsic_max_+interval_intrinsic_min_);
     167         249 :   interval_range_ = interval_max_-interval_min_;
     168         249 :   interval_mean_  = 0.5*(interval_max_+interval_min_);
     169         249 :   argT_derivf_ = interval_intrinsic_range_/interval_range_;
     170         249 : }
     171             : 
     172             : 
     173          78 : void BasisFunctions::setupLabels() {
     174         884 :   for(unsigned int i=0; i < nbasis_; i++) {
     175             :     std::string is;
     176         806 :     Tools::convert(i,is);
     177        1612 :     bf_labels_[i]=bf_label_prefix_+is+"(s)";
     178             :   }
     179          78 : }
     180             : 
     181             : 
     182          79 : void BasisFunctions::setupUniformIntegrals() {
     183          79 :   numerical_uniform_integrals_=true;
     184          79 :   numericalUniformIntegrals();
     185          79 : }
     186             : 
     187             : 
     188         249 : void BasisFunctions::setupBF() {
     189         249 :   if(interval_intrinsic_min_>interval_intrinsic_max_) {
     190           0 :     plumed_merror("setupBF: default intervals are not correctly set");
     191             :   }
     192         249 :   setupInterval();
     193         249 :   setupLabels();
     194         249 :   if(bf_labels_.size()==1) {
     195           0 :     plumed_merror("setupBF: the labels of the basis functions are not correct.");
     196             :   }
     197         249 :   if(!numerical_uniform_integrals_) {
     198         243 :     setupUniformIntegrals();
     199             :   } else {
     200           6 :     numericalUniformIntegrals();
     201             :   }
     202         249 :   if(uniform_integrals_.size()==1) {
     203           0 :     plumed_merror("setupBF: the integrals of the basis functions is not correct.");
     204             :   }
     205         249 :   if(type_=="Undefined") {
     206           0 :     plumed_merror("setupBF: the type of the basis function is not defined.");
     207             :   }
     208         249 :   if(description_=="Undefined") {
     209           0 :     plumed_merror("setupBF: the description of the basis function is not defined.");
     210             :   }
     211         249 :   has_been_set=true;
     212         249 :   printInfo();
     213         249 : }
     214             : 
     215             : 
     216         249 : void BasisFunctions::printInfo() const {
     217         249 :   if(!has_been_set) {
     218           0 :     plumed_merror("the basis set has not be setup correctly");
     219             :   }
     220         249 :   log.printf("  One-dimensional basis set\n");
     221         249 :   log.printf("   Description: %s\n",description_.c_str());
     222         249 :   log.printf("   Type: %s\n",type_.c_str());
     223         249 :   if(periodic_) {
     224         111 :     log.printf("   The basis functions are periodic\n");
     225             :   }
     226         249 :   log.printf("   Order of basis set: %u\n",norder_);
     227         249 :   log.printf("   Number of basis functions: %u\n",nbasis_);
     228             :   // log.printf("   Interval of basis set: %f to %f\n",interval_min_,interval_max_);
     229         249 :   log.printf("   Interval of basis set: %s to %s\n",interval_min_str_.c_str(),interval_max_str_.c_str());
     230         249 :   log.printf("   Description of basis functions:\n");
     231        4293 :   for(unsigned int i=0; i < nbasis_; i++) {
     232        4044 :     log.printf("    %2u       %10s\n",i,bf_labels_[i].c_str());
     233             :   }
     234             :   //
     235         249 :   if(print_debug_info_) {
     236          38 :     log.printf("  Debug information:\n");
     237             :     // log.printf("   Default interval of basis set: [%f,%f]\n",interval_intrinsic_min_,interval_intrinsic_max_);
     238          38 :     log.printf("   Intrinsic interval of basis set: [%s,%s]\n",interval_intrinsic_min_str_.c_str(),interval_intrinsic_max_str_.c_str());
     239          38 :     log.printf("   Intrinsic interval of basis set: range=%f,  mean=%f\n",interval_intrinsic_range_,interval_intrinsic_mean_);
     240             :     // log.printf("   Defined interval of basis set: [%f,%f]\n",interval_min_,interval_max_);
     241          38 :     log.printf("   Defined interval of basis set: [%s,%s]\n",interval_min_str_.c_str(),interval_max_str_.c_str());
     242          38 :     log.printf("   Defined interval of basis set: range=%f,  mean=%f\n",interval_range_,interval_mean_);
     243          38 :     log.printf("   Derivative factor due to interval translation: %f\n",argT_derivf_);
     244          38 :     log.printf("   Integral of basis functions over the interval:\n");
     245          38 :     if(numerical_uniform_integrals_) {
     246          22 :       log.printf("   Note: calculated numerically\n");
     247             :     }
     248         558 :     for(unsigned int i=0; i < nbasis_; i++) {
     249         520 :       log.printf("    %2u       %16.10f\n",i,uniform_integrals_[i]);
     250             :     }
     251          38 :     log.printf("   --------------------------\n");
     252             :   }
     253         249 : }
     254             : 
     255             : 
     256           0 : void BasisFunctions::linkVesBias(VesBias* vesbias_pntr_in) {
     257           0 :   vesbias_pntr_ = vesbias_pntr_in;
     258           0 :   action_pntr_ = static_cast<Action*>(vesbias_pntr_in);
     259           0 : }
     260             : 
     261             : 
     262           0 : void BasisFunctions::linkAction(Action* action_pntr_in) {
     263           0 :   action_pntr_ = action_pntr_in;
     264           0 : }
     265             : 
     266             : 
     267          85 : void BasisFunctions::numericalUniformIntegrals() {
     268          85 :   std::vector<std::string> grid_min(1);
     269          85 :   grid_min[0]=intervalMinStr();
     270          85 :   std::vector<std::string> grid_max(1);
     271          85 :   grid_max[0]=intervalMaxStr();
     272          85 :   std::vector<unsigned int> grid_bins(1);
     273          85 :   grid_bins[0]=nbins_;
     274          85 :   std::vector<std::unique_ptr<Value>> arguments(1);
     275         170 :   arguments[0]= Tools::make_unique<Value>(nullptr,"arg",false);
     276          85 :   if(arePeriodic()) {
     277          20 :     arguments[0]->setDomain(intervalMinStr(),intervalMaxStr());
     278             :   } else {
     279          75 :     arguments[0]->setNotPeriodic();
     280             :   }
     281         170 :   auto uniform_grid = Tools::make_unique<Grid>("uniform",Tools::unique2raw(arguments),grid_min,grid_max,grid_bins,false,false);
     282             :   //
     283          85 :   double inverse_normalization = 1.0/(intervalMax()-intervalMin());
     284       85245 :   for(Grid::index_t l=0; l<uniform_grid->getSize(); l++) {
     285       85160 :     uniform_grid->setValue(l,inverse_normalization);
     286             :   }
     287          85 :   uniform_integrals_ = numericalTargetDistributionIntegralsFromGrid(uniform_grid.get());
     288         170 : }
     289             : 
     290             : 
     291         261 : std::vector<double> BasisFunctions::numericalTargetDistributionIntegralsFromGrid(const Grid* grid_pntr) const {
     292         261 :   plumed_massert(grid_pntr!=NULL,"the grid is not defined");
     293         261 :   plumed_massert(grid_pntr->getDimension()==1,"the target distribution grid should be one dimensional");
     294             :   //
     295         261 :   std::vector<double> targetdist_integrals(nbasis_,0.0);
     296         522 :   std::vector<double> integration_weights = GridIntegrationWeights::getIntegrationWeights(grid_pntr);
     297             : 
     298      138336 :   for(Grid::index_t k=0; k < grid_pntr->getSize(); k++) {
     299      138075 :     double arg = grid_pntr->getPoint(k)[0];
     300      138075 :     std::vector<double> bf_values(nbasis_);
     301      138075 :     std::vector<double> bf_derivs(nbasis_);
     302      138075 :     bool inside=true;
     303      138075 :     double argT=0.0;
     304      138075 :     getAllValues(arg,argT,inside,bf_values,bf_derivs);
     305     3336092 :     for(unsigned int i=0; i < nbasis_; i++) {
     306     3198017 :       targetdist_integrals[i] += (integration_weights[k] * grid_pntr->getValue(k)) * bf_values[i];
     307             :     }
     308             :   }
     309             :   // assume that the first function is the constant
     310         261 :   bool inside=true;
     311         261 :   double argT=0.0;
     312         261 :   targetdist_integrals[0] = getValue(0.0,0,argT,inside);
     313         261 :   return targetdist_integrals;
     314             : }
     315             : 
     316             : 
     317         247 : std::vector<double> BasisFunctions::getTargetDistributionIntegrals(const TargetDistribution* targetdist_pntr) const {
     318         247 :   if(targetdist_pntr==NULL) {
     319             :     return getUniformIntegrals();
     320             :   } else {
     321             :     Grid* targetdist_grid = targetdist_pntr->getTargetDistGridPntr();
     322         176 :     return numericalTargetDistributionIntegralsFromGrid(targetdist_grid);
     323             :   }
     324             : }
     325             : 
     326             : 
     327         142 : std::string BasisFunctions::getKeywordString() const {
     328         142 :   std::string str_keywords=bf_keywords_[0];
     329         762 :   for(unsigned int i=1; i<bf_keywords_.size(); i++) {
     330        1240 :     str_keywords+=" "+bf_keywords_[i];
     331             :   }
     332         142 :   return str_keywords;
     333             : }
     334             : 
     335             : 
     336         261 : double BasisFunctions::getValue(const double arg, const unsigned int n, double& argT, bool& inside_range) const {
     337         261 :   plumed_massert(n<numberOfBasisFunctions(),"getValue: n is outside range of the defined order of the basis set");
     338         261 :   inside_range=true;
     339         261 :   std::vector<double> tmp_values(numberOfBasisFunctions());
     340         261 :   std::vector<double> tmp_derivs(numberOfBasisFunctions());
     341         261 :   getAllValues(arg, argT, inside_range, tmp_values, tmp_derivs);
     342         522 :   return tmp_values[n];
     343             : }
     344             : 
     345             : 
     346           0 : void BasisFunctions::getAllValuesNumericalDerivs(const double arg, double& argT, bool& inside_range, std::vector<double>& values, std::vector<double>& derivs) const {
     347             :   // use forward difference, unless very close to the boundary
     348             :   double delta = sqrt(epsilon);
     349           0 :   if((arg+delta)>intervalMax()) {
     350             :     delta *= -1.0;
     351             :   }
     352           0 :   inside_range=true;
     353           0 :   std::vector<double> values_delta(numberOfBasisFunctions());
     354           0 :   std::vector<double> derivs_dummy(numberOfBasisFunctions());
     355           0 :   getAllValues(arg+delta, argT, inside_range, values_delta, derivs_dummy);
     356           0 :   getAllValues(arg, argT, inside_range, values, derivs_dummy);
     357           0 :   for(unsigned int i=0; i<numberOfBasisFunctions(); i++) {
     358           0 :     derivs[i] = (values_delta[i]-values[i])/delta;
     359             :   }
     360           0 : }
     361             : 
     362             : 
     363          71 : void BasisFunctions::getMultipleValue(const std::vector<double>& args, std::vector<double>& argsT, std::vector<std::vector<double> >& values, std::vector<std::vector<double> >& derivs, const bool numerical_deriv) const {
     364          71 :   argsT.resize(args.size());
     365             :   values.clear();
     366             :   derivs.clear();
     367       23019 :   for(unsigned int i=0; i<args.size(); i++) {
     368       22948 :     std::vector<double> tmp_values(getNumberOfBasisFunctions());
     369       22948 :     std::vector<double> tmp_derivs(getNumberOfBasisFunctions());
     370       22948 :     bool inside_interval=true;
     371       22948 :     if(!numerical_deriv) {
     372       22948 :       getAllValues(args[i],argsT[i],inside_interval,tmp_values,tmp_derivs);
     373             :     } else {
     374           0 :       getAllValuesNumericalDerivs(args[i],argsT[i],inside_interval,tmp_values,tmp_derivs);
     375             :     }
     376       22948 :     values.push_back(tmp_values);
     377       22948 :     derivs.push_back(tmp_derivs);
     378             :   }
     379          71 : }
     380             : 
     381             : 
     382          71 : void BasisFunctions::writeBasisFunctionsToFile(OFile& ofile_values, OFile& ofile_derivs, const std::string& min_in, const std::string& max_in, unsigned int nbins_in, const bool ignore_periodicity, const std::string& output_fmt_values, const std::string& output_fmt_derivs, const bool numerical_deriv) const {
     383          71 :   std::vector<std::string> min(1);
     384             :   min[0]=min_in;
     385          71 :   std::vector<std::string> max(1);
     386             :   max[0]=max_in;
     387          71 :   std::vector<unsigned int> nbins(1);
     388          71 :   nbins[0]=nbins_in;
     389          71 :   std::vector<std::unique_ptr<Value>> value_pntr(1);
     390         142 :   value_pntr[0]= Tools::make_unique<Value>(nullptr,"arg",false);
     391          71 :   if(arePeriodic() && !ignore_periodicity) {
     392          46 :     value_pntr[0]->setDomain(intervalMinStr(),intervalMaxStr());
     393             :   } else {
     394          48 :     value_pntr[0]->setNotPeriodic();
     395             :   }
     396         142 :   Grid args_grid = Grid("grid",Tools::unique2raw(value_pntr),min,max,nbins,false,false);
     397             : 
     398          71 :   std::vector<double> args(args_grid.getSize(),0.0);
     399       23019 :   for(unsigned int i=0; i<args.size(); i++) {
     400       22948 :     args[i] = args_grid.getPoint(i)[0];
     401             :   }
     402             :   std::vector<double> argsT;
     403             :   std::vector<std::vector<double> > values;
     404             :   std::vector<std::vector<double> > derivs;
     405             : 
     406         142 :   ofile_values.addConstantField("bf_keywords").printField("bf_keywords","{"+getKeywordString()+"}");
     407         142 :   ofile_derivs.addConstantField("bf_keywords").printField("bf_keywords","{"+getKeywordString()+"}");
     408             : 
     409         213 :   ofile_values.addConstantField("min").printField("min",intervalMinStr());
     410         213 :   ofile_values.addConstantField("max").printField("max",intervalMaxStr());
     411             : 
     412         213 :   ofile_derivs.addConstantField("min").printField("min",intervalMinStr());
     413         213 :   ofile_derivs.addConstantField("max").printField("max",intervalMaxStr());
     414             : 
     415         142 :   ofile_values.addConstantField("nbins").printField("nbins",static_cast<int>(args_grid.getNbin()[0]));
     416         142 :   ofile_derivs.addConstantField("nbins").printField("nbins",static_cast<int>(args_grid.getNbin()[0]));
     417             : 
     418          71 :   if(arePeriodic()) {
     419          52 :     ofile_values.addConstantField("periodic").printField("periodic","true");
     420          52 :     ofile_derivs.addConstantField("periodic").printField("periodic","true");
     421             :   } else {
     422          90 :     ofile_values.addConstantField("periodic").printField("periodic","false");
     423          90 :     ofile_derivs.addConstantField("periodic").printField("periodic","false");
     424             :   }
     425             : 
     426          71 :   getMultipleValue(args,argsT,values,derivs,numerical_deriv);
     427          71 :   ofile_values.fmtField(output_fmt_values);
     428          71 :   ofile_derivs.fmtField(output_fmt_derivs);
     429       23019 :   for(unsigned int i=0; i<args.size(); i++) {
     430       45896 :     ofile_values.printField("arg",args[i]);
     431       22948 :     ofile_derivs.printField("arg",args[i]);
     432      410060 :     for(unsigned int k=0; k<getNumberOfBasisFunctions(); k++) {
     433      774224 :       ofile_values.printField(getBasisFunctionLabel(k),values[i][k]);
     434      774224 :       ofile_derivs.printField("d_"+getBasisFunctionLabel(k),derivs[i][k]);
     435             :     }
     436       22948 :     ofile_values.printField();
     437       22948 :     ofile_derivs.printField();
     438             :   }
     439          71 :   ofile_values.fmtField();
     440          71 :   ofile_derivs.fmtField();
     441             : 
     442         213 : }
     443             : 
     444             : 
     445             : }
     446             : }

Generated by: LCOV version 1.16