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 { 60 0 : return false; 61 : } 62 : }; 63 : 64 13789 : PLUMED_REGISTER_ACTION(InterpolateGrid,"INTERPOLATE_GRID") 65 : 66 6 : void InterpolateGrid::registerKeywords( Keywords& keys ) { 67 6 : ActionWithInputGrid::registerKeywords( keys ); 68 12 : keys.add("optional","GRID_BIN","the number of bins for the grid"); 69 12 : keys.add("optional","GRID_SPACING","the approximate grid spacing (to be used as an alternative or together with GRID_BIN)"); 70 6 : keys.remove("KERNEL"); 71 6 : keys.remove("BANDWIDTH"); 72 6 : } 73 : 74 2 : InterpolateGrid::InterpolateGrid(const ActionOptions&ao): 75 : Action(ao), 76 2 : ActionWithInputGrid(ao) { 77 2 : plumed_assert( ingrid->getNumberOfComponents()==1 ); 78 2 : if( ingrid->noDerivatives() ) { 79 0 : error("cannot interpolate a grid that does not have derivatives"); 80 : } 81 : // Create the input from the old string 82 4 : auto grid=createGrid( "grid", "COMPONENTS=" + getLabel() + " " + ingrid->getInputString() ); 83 : // notice that createGrid also sets mygrid=grid.get() 84 : 85 : std::vector<unsigned> nbin; 86 4 : parseVector("GRID_BIN",nbin); 87 : std::vector<double> gspacing; 88 4 : parseVector("GRID_SPACING",gspacing); 89 2 : if( nbin.size()!=ingrid->getDimension() && gspacing.size()!=ingrid->getDimension() ) { 90 0 : error("GRID_BIN or GRID_SPACING must be set"); 91 : } 92 : 93 : // Need this for creation of tasks 94 2 : grid->setBounds( ingrid->getMin(), ingrid->getMax(), nbin, gspacing ); 95 2 : setAveragingAction( std::move(grid), true ); 96 : 97 : // Now create task list 98 202 : for(unsigned i=0; i<mygrid->getNumberOfPoints(); ++i) { 99 200 : addTaskToList(i); 100 : } 101 : // And activate all tasks 102 2 : deactivateAllTasks(); 103 202 : for(unsigned i=0; i<mygrid->getNumberOfPoints(); ++i) { 104 200 : taskFlags[i]=1; 105 : } 106 2 : lockContributors(); 107 2 : } 108 : 109 8 : unsigned InterpolateGrid::getNumberOfQuantities() const { 110 8 : return 2 + ingrid->getDimension(); 111 : } 112 : 113 200 : void InterpolateGrid::compute( const unsigned& current, MultiValue& myvals ) const { 114 200 : std::vector<double> pos( mygrid->getDimension() ); 115 200 : mygrid->getGridPointCoordinates( current, pos ); 116 200 : std::vector<double> der( mygrid->getDimension() ); 117 : double val = getFunctionValueAndDerivatives( pos, der ); 118 : myvals.setValue( 0, 1.0 ); 119 : myvals.setValue(1, val ); 120 400 : for(unsigned i=0; i<mygrid->getDimension(); ++i) { 121 200 : myvals.setValue( 2+i, der[i] ); 122 : } 123 200 : } 124 : 125 : } 126 : }