Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2016-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 "core/ActionRegister.h" 23 : #include "core/PlumedMain.h" 24 : #include "ActionWithInputGrid.h" 25 : 26 : //+PLUMEDOC GRIDANALYSIS INTERPOLATE_GRID 27 : /* 28 : Interpolate a smooth function stored on a grid onto a grid with a smaller grid spacing. 29 : 30 : This action takes a function evaluated on a grid as input and can be used to interpolate the values of that 31 : function on to a finer grained grid. The interpolation within this algorithm is done using splines. 32 : 33 : \par Examples 34 : 35 : The input below can be used to post process a trajectory. It calculates a \ref HISTOGRAM as a function the 36 : distance between atoms 1 and 2 using kernel density estimation. During the calculation the values of the kernels 37 : are evaluated at 100 points on a uniform grid between 0.0 and 3.0. Prior to outputting this function at the end of the 38 : simulation this function is interpolated onto a finer grid of 200 points between 0.0 and 3.0. 39 : 40 : \plumedfile 41 : x: DISTANCE ATOMS=1,2 42 : hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 43 : ii: INTERPOLATE_GRID GRID=hA1 GRID_BIN=200 44 : DUMPGRID GRID=ii FILE=histo.dat 45 : \endplumedfile 46 : 47 : */ 48 : //+ENDPLUMEDOC 49 : 50 : namespace PLMD { 51 : namespace gridtools { 52 : 53 : class InterpolateGrid : public ActionWithInputGrid { 54 : public: 55 : static void registerKeywords( Keywords& keys ); 56 : explicit InterpolateGrid(const ActionOptions&ao); 57 : unsigned getNumberOfQuantities() const override; 58 : void compute( const unsigned& current, MultiValue& myvals ) const override; 59 0 : bool isPeriodic() override { return false; } 60 : }; 61 : 62 10423 : PLUMED_REGISTER_ACTION(InterpolateGrid,"INTERPOLATE_GRID") 63 : 64 3 : void InterpolateGrid::registerKeywords( Keywords& keys ) { 65 3 : ActionWithInputGrid::registerKeywords( keys ); 66 6 : keys.add("optional","GRID_BIN","the number of bins for the grid"); 67 6 : keys.add("optional","GRID_SPACING","the approximate grid spacing (to be used as an alternative or together with GRID_BIN)"); 68 6 : keys.remove("KERNEL"); keys.remove("BANDWIDTH"); 69 3 : } 70 : 71 2 : InterpolateGrid::InterpolateGrid(const ActionOptions&ao): 72 : Action(ao), 73 2 : ActionWithInputGrid(ao) 74 : { 75 2 : plumed_assert( ingrid->getNumberOfComponents()==1 ); 76 2 : if( ingrid->noDerivatives() ) error("cannot interpolate a grid that does not have derivatives"); 77 : // Create the input from the old string 78 8 : auto grid=createGrid( "grid", "COMPONENTS=" + getLabel() + " " + ingrid->getInputString() ); 79 : // notice that createGrid also sets mygrid=grid.get() 80 : 81 4 : std::vector<unsigned> nbin; parseVector("GRID_BIN",nbin); 82 4 : std::vector<double> gspacing; parseVector("GRID_SPACING",gspacing); 83 2 : if( nbin.size()!=ingrid->getDimension() && gspacing.size()!=ingrid->getDimension() ) { 84 0 : error("GRID_BIN or GRID_SPACING must be set"); 85 : } 86 : 87 : // Need this for creation of tasks 88 2 : grid->setBounds( ingrid->getMin(), ingrid->getMax(), nbin, gspacing ); 89 2 : setAveragingAction( std::move(grid), true ); 90 : 91 : // Now create task list 92 202 : for(unsigned i=0; i<mygrid->getNumberOfPoints(); ++i) addTaskToList(i); 93 : // And activate all tasks 94 2 : deactivateAllTasks(); 95 202 : for(unsigned i=0; i<mygrid->getNumberOfPoints(); ++i) taskFlags[i]=1; 96 2 : lockContributors(); 97 2 : } 98 : 99 8 : unsigned InterpolateGrid::getNumberOfQuantities() const { 100 8 : return 2 + ingrid->getDimension(); 101 : } 102 : 103 200 : void InterpolateGrid::compute( const unsigned& current, MultiValue& myvals ) const { 104 200 : std::vector<double> pos( mygrid->getDimension() ); mygrid->getGridPointCoordinates( current, pos ); 105 200 : std::vector<double> der( mygrid->getDimension() ); double val = getFunctionValueAndDerivatives( pos, der ); 106 : myvals.setValue( 0, 1.0 ); myvals.setValue(1, val ); 107 400 : for(unsigned i=0; i<mygrid->getDimension(); ++i) myvals.setValue( 2+i, der[i] ); 108 200 : } 109 : 110 : } 111 : }