LCOV - code coverage report
Current view: top level - gridtools - EvaluateGridFunction.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 82 91 90.1 %
Date: 2026-11-05 10:19:04 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2015-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed 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             :    plumed 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 plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "EvaluateGridFunction.h"
      23             : #include "core/PlumedMain.h"
      24             : #include "core/ActionSet.h"
      25             : 
      26             : namespace PLMD {
      27             : namespace gridtools {
      28             : 
      29          91 : void EvaluateGridFunction::registerKeywords( Keywords& keys ) {
      30          91 :   keys.add("compulsory","INTERPOLATION_TYPE","spline","the method to use for interpolation.  Can be spline, linear, ceiling or floor.");
      31          91 :   keys.addFlag("ZERO_OUTSIDE_GRID_RANGE",false,"if we are asked to evaluate the function for a number that is outside the range of the grid set it to zero");
      32         182 :   keys.setValueDescription("scalar","interpolation of the input grid to get the value of the function at the input arguments");
      33          91 : }
      34             : 
      35          23 : std::vector<bool> EvaluateGridFunction::getPbc() const {
      36             :   const GridCoordinatesObject & gridobject = getGridObject();
      37          23 :   std::vector<bool> ipbc( gridobject.getDimension() );
      38          47 :   for(unsigned i=0; i<ipbc.size(); ++i) {
      39          24 :     ipbc[i] = gridobject.isPeriodic(i);
      40             :   }
      41          23 :   return ipbc;
      42             : }
      43             : 
      44          33 : void EvaluateGridFunction::read( EvaluateGridFunction& func, ActionWithArguments* action, function::FunctionOptions& options ) {
      45          33 :   func.function = action->getPntrToArgument(0);
      46          33 :   if( func.function->getRank()==0 || !func.function->hasDerivatives() ) {
      47           0 :     action->error("should have one grid as input to this action");
      48             :   }
      49             :   // Get the input grid
      50          33 :   func.gridact = ActionWithGrid::getInputActionWithGrid( func.function->getPntrToAction() );
      51          33 :   plumed_assert( func.gridact );
      52          33 :   if( func.gridact->getGridCoordinatesObject().getGridType()!="flat" ) {
      53           0 :     action->error("cannot interpolate on fibonacci sphere");
      54             :   }
      55          33 :   std::vector<std::string> argn;
      56          33 :   if( action->keywords.exists("ZERO_OUTSIDE_GRID_RANGE") ) {
      57          12 :     action->parseFlag("ZERO_OUTSIDE_GRID_RANGE",func.set_zero_outside_range);
      58             :   } else {
      59          27 :     func.set_zero_outside_range=false;
      60             :   }
      61          33 :   if( func.set_zero_outside_range ) {
      62           0 :     action->log.printf("  function is zero outside grid range \n");
      63             :   }
      64             :   // Get the type of interpolation that we are doing
      65             :   std::string itype;
      66          33 :   action->parse("INTERPOLATION_TYPE",itype);
      67          33 :   if( itype=="spline" ) {
      68          12 :     func.interpolation_type=spline;
      69          24 :     func.spline_interpolator=Tools::make_unique<Interpolator>( func.function, func.gridact->getGridCoordinatesObject() );
      70          21 :   } else if( itype=="linear" ) {
      71           5 :     func.interpolation_type=linear;
      72          16 :   } else if( itype=="floor" ) {
      73           1 :     func.interpolation_type=floor;
      74          15 :   } else if( itype=="ceiling" ) {
      75          15 :     func.interpolation_type=ceiling;
      76             :   } else {
      77           0 :     action->error("type " + itype + " of interpolation is not defined");
      78             :   }
      79          33 :   action->log.printf("  generating off grid points using %s interpolation \n", itype.c_str() );
      80          33 : }
      81             : 
      82       47872 : void EvaluateGridFunction::calc( const EvaluateGridFunction& func, bool noderiv, const View<const double> args, function::FunctionOutput& funcout ) {
      83             :   const GridCoordinatesObject & gridobject = func.getGridObject();
      84       47872 :   if( func.set_zero_outside_range && !gridobject.inbounds( args ) ) {
      85           0 :     funcout.values[0]=0.0;
      86           0 :     return;
      87             :   }
      88             :   unsigned dimension = gridobject.getDimension();
      89             :   plumed_dbg_assert( args.size()==dimension && funcout.values.size()==1 );
      90       47872 :   if( func.interpolation_type==spline ) {
      91       32155 :     std::vector<double> der( dimension );
      92       32155 :     funcout.values[0] =  func.spline_interpolator->splineInterpolation( args, der );
      93       32155 :     if( noderiv ) {
      94             :       return ;
      95             :     }
      96       74485 :     for(unsigned j=0; j<dimension; ++j) {
      97       50735 :       funcout.derivs[0][j] = der[j];
      98             :     }
      99       15717 :   } else if( func.interpolation_type==linear ) {
     100        6840 :     std::vector<double> xfloor(dimension);
     101        6840 :     std::vector<unsigned> indices(dimension), nindices(dimension), ind(dimension);
     102        6840 :     gridobject.getIndices( args, indices );
     103        6840 :     unsigned nn=gridobject.getIndex(args);
     104        6840 :     gridobject.getGridPointCoordinates( nn, nindices, xfloor );
     105        6840 :     double y1 = func.function->get(nn);
     106        6840 :     funcout.values[0] = y1;
     107       20080 :     for(unsigned i=0; i<args.size(); ++i) {
     108             :       int x0=1;
     109       13240 :       if(nindices[i]==indices[i]) {
     110             :         x0=0;
     111             :       }
     112       13240 :       double ddx=gridobject.getGridSpacing()[i];
     113       13240 :       double X = fabs((args[i]-xfloor[i])/ddx-(double)x0);
     114       39280 :       for(unsigned j=0; j<args.size(); ++j) {
     115       26040 :         ind[j] = indices[j];
     116             :       }
     117       13240 :       if( gridobject.isPeriodic(i) && (ind[i]+1)==gridobject.getNbin(false)[i] ) {
     118           0 :         ind[i]=0;
     119             :       } else {
     120       13240 :         ind[i] = ind[i] + 1;
     121             :       }
     122       13240 :       if( X<epsilon ) {
     123        6400 :         continue ;
     124             :       }
     125        6840 :       funcout.values[0] += ( func.function->get( gridobject.getIndex(ind) ) - y1 )*X;
     126        6840 :       if( noderiv ) {
     127           0 :         continue ;
     128             :       }
     129        6840 :       funcout.derivs[0][i] = ( func.function->get( gridobject.getIndex(ind) ) - y1 ) / ddx;
     130             :     }
     131        8877 :   } else if( func.interpolation_type==floor ) {
     132          61 :     std::vector<unsigned> indices(dimension);
     133          61 :     gridobject.getIndices( args, indices );
     134          61 :     unsigned nn = gridobject.getIndex(indices);
     135             :     plumed_dbg_assert( nn<func.function->getNumberOfValues() );
     136          61 :     funcout.values[0] = func.function->get( nn );
     137          61 :     if( noderiv ) {
     138             :       return;
     139             :     }
     140         122 :     for(unsigned j=0; j<dimension; ++j) {
     141          61 :       funcout.derivs[0][j] = func.function->getGridDerivative( nn, j );
     142             :     }
     143        8816 :   } else if( func.interpolation_type==ceiling ) {
     144        8816 :     std::vector<unsigned> indices(dimension);
     145        8816 :     gridobject.getIndices( args, indices );
     146       17632 :     for(unsigned i=0; i<indices.size(); ++i) {
     147       11020 :       if( gridobject.isPeriodic(i) && (indices[i]+1)==gridobject.getNbin(false)[i] ) {
     148        2204 :         indices[i]=0;
     149             :       } else {
     150        6612 :         indices[i] = indices[i] + 1;
     151             :       }
     152             :     }
     153        8816 :     unsigned nn = gridobject.getIndex(indices);
     154        8816 :     funcout.values[0] = func.function->get( nn );
     155        8816 :     if( noderiv ) {
     156             :       return;
     157             :     }
     158       17632 :     for(unsigned j=0; j<dimension; ++j) {
     159        8816 :       funcout.derivs[0][j] = func.function->getGridDerivative( nn, j );
     160             :     }
     161             :   } else {
     162           0 :     plumed_error();
     163             :   }
     164             : }
     165             : 
     166             : }
     167             : }

Generated by: LCOV version 1.16