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