Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2016-2018 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 "function/FunctionShortcut.h"
24 : #include "function/FunctionOfScalar.h"
25 : #include "function/FunctionOfVector.h"
26 : #include "EvaluateGridFunction.h"
27 : #include "ActionWithGrid.h"
28 :
29 : //+PLUMEDOC GRIDANALYSIS EVALUATE_FUNCTION_FROM_GRID
30 : /*
31 : Calculate the function stored on the input grid at an arbitrary point
32 :
33 : This action can be used to evaluate a function that is stored on a grid at an arbitrary point in space via interpolation. For example, the
34 : following input illustrates how you can use this action to evaulate the square of the distance between atom 1 and atom 2
35 :
36 : ```plumed
37 : d2: REFERENCE_GRID GRID_MIN=0 GRID_MAX=10 GRID_BIN=20 FUNC=d1*d1 VAR=d1 PERIODIC=NO
38 : d1: DISTANCE ATOMS=1,2
39 : ff: EVALUATE_FUNCTION_FROM_GRID GRID=d2
40 : PRINT ARG=d1,ff FILE=colvar
41 : ```
42 :
43 : You can perform the same calculation using [CUSTOM](CUSTOM.md), which will do the calculation exactly and not perform any interpolation. However,
44 : if for some reason you only have the values of the function at a grid of point EVALUATE_FUNCTION_FROM_GRID may be a useful alternative as you can
45 : use [REFERENCE_GRID](REFERENCE_GRID.md) to read in the values of the function at your grid of point from a file as shown below:
46 :
47 : ```plumed
48 : #SETTINGS INPUTFILES=regtest/gridtools/rt-weights-integral/kde.grid
49 :
50 : ff: REFERENCE_GRID FILE=regtest/gridtools/rt-weights-integral/kde.grid VALUE=h
51 : aa: ANGLE ATOMS=1,2,3
52 : tt: TORSION ATOMS=1,2,3,4
53 : val: EVALUATE_FUNCTION_FROM_GRID ...
54 : GRID=ff INTERPOLATION_TYPE=spline
55 : ZERO_OUTSIDE_GRID_RANGE
56 : ...
57 : PRINT ARG=aa,tt,val FILE=colvar
58 : ```
59 :
60 : Notice that the ARG command does not need to be used with the EVALUATE_FUNCTION_FROM_GRID command to specify the labels of the input arguments at which you
61 : would like the function to be evaluated. Instead, you only specify the GRID that is being used as input for the interpolation. The reason that it is not
62 : necessary to specify the arguments is that PLUMED stores labels for each coordinate axis of a grid. These labels appear at the top of the
63 : columns that contain the grid points when you output grids using [DUMPGRID](DUMPGRID.md). Furthermore, in the first of the inputs above the labels of these
64 : input arguments are specified using the VAR option for [REFERENCE_GRID](REFERENCE_GRID.md). Meanwhile, for the second the titles of the columsn are
65 : read in from the input file. Consequently, PLUMED searches for a value named `d1` when evaluating `ff` in the first input. For the second input it searches
66 : for values labelled `aa` and `tt` and evaluates `val` from them. You can, however, also use an ARG keyword in the input file as illustrated below if this helps
67 : you to remember what precisely is being evluated:
68 :
69 : ```plumed
70 : d2: REFERENCE_GRID GRID_MIN=0 GRID_MAX=10 GRID_BIN=20 FUNC=d1*d1 VAR=d1 PERIODIC=NO
71 : d1: DISTANCE ATOMS=1,2
72 : ff: EVALUATE_FUNCTION_FROM_GRID GRID=d2 ARG=d1
73 : PRINT ARG=d1,ff FILE=colvar
74 : ```
75 :
76 : Notice that input the inputs above the input values are scalars. The output from EVALUATE_FUNCTION_FROM_GRID is thus also a scalar. If, however, one uses an
77 : input such as the one shown below:
78 :
79 : ```plumed
80 : #SETTINGS INPUTFILES=regtest/gridtools/rt-weights-integral/kde.grid
81 :
82 : ff: REFERENCE_GRID FILE=regtest/gridtools/rt-weights-integral/kde.grid VALUE=h
83 : aa: ANGLE ATOMS1=1,2,3 ATOMS2=4,5,6 ATOMS3=7,8,9
84 : tt: TORSION ATOMS1=1,2,3,4 ATOMS2=5,6,7,8 ATOMS3=9,10,11,12
85 : val: EVALUATE_FUNCTION_FROM_GRID GRID=ff
86 : PRINT ARG=aa,tt,val FILE=colvar
87 : ```
88 :
89 : The value, `val`, that is output by the EVALUATE_FUNCTION_FROM_GRID action will be a vector. In other words, in the same way you can use scalars, vectors, matrices and even
90 : functions on grids in the input to the [CUSTOM](CUSTOM.md) command you can also use scalars, vectors, matrices and functions on grid in the input to the EVALUATE_FUNCTION_FROM_GRID
91 : command.
92 :
93 : ## The MASK keyword
94 :
95 : If the input to this action is a vector you can use the MASK keyword as illustrated below:
96 :
97 : ```plumed
98 : #SETTINGS INPUTFILES=regtest/gridtools/rt-weights-integral/kde.grid
99 :
100 : ff: REFERENCE_GRID FILE=regtest/gridtools/rt-weights-integral/kde.grid VALUE=h
101 : d: DISTANCE ATOMS1=1,2 ATOMS2=4,5 ATOMS3=7,8
102 : m: LESS_THAN ARG=d SWITCH={CUSTOM R_0=1 FUNC=step(0.1-x)}
103 : aa: ANGLE ATOMS1=1,2,3 ATOMS2=4,5,6 ATOMS3=7,8,9
104 : tt: TORSION ATOMS1=1,2,3,4 ATOMS2=5,6,7,8 ATOMS3=9,10,11,12
105 : val: EVALUATE_FUNCTION_FROM_GRID GRID=ff MASK=m
106 : prod: CUSTOM ARG=m,val FUNC=x*y PERIODIC=NO
107 : sum: SUM ARG=prod PERIODIC=NO
108 : PRINT ARG=sum FILE=colvar
109 : ```
110 :
111 : This input calculates the function of the angles and torsions that is provided in the input grid file for the three pairs of input angles and torsions. The sum of these quantities
112 : is then computed. Importantly, however, each of the evaluated values of the function is only added to the final sum if the corresponding distance that is calculated by the [DISTANCE](DISTANCE.md)
113 : action with label `d` is less than 0.1 nm.
114 :
115 : */
116 : //+ENDPLUMEDOC
117 :
118 : namespace PLMD {
119 : namespace gridtools {
120 :
121 : class EvaluateFunctionOnGrid : public ActionShortcut {
122 : public:
123 : static void registerKeywords(Keywords&);
124 : explicit EvaluateFunctionOnGrid(const ActionOptions&);
125 : };
126 :
127 : PLUMED_REGISTER_ACTION(EvaluateFunctionOnGrid,"EVALUATE_FUNCTION_FROM_GRID")
128 : typedef function::FunctionOfScalar<EvaluateGridFunction> ScalarEvalGrid;
129 : PLUMED_REGISTER_ACTION(ScalarEvalGrid,"EVALUATE_FUNCTION_FROM_GRID_SCALAR")
130 : typedef function::FunctionOfVector<EvaluateGridFunction> VectorEvalGrid;
131 : PLUMED_REGISTER_ACTION(VectorEvalGrid,"EVALUATE_FUNCTION_FROM_GRID_VECTOR")
132 :
133 10 : void EvaluateFunctionOnGrid::registerKeywords(Keywords& keys ) {
134 10 : ActionShortcut::registerKeywords( keys );
135 20 : keys.addInputKeyword("compulsory","GRID","grid","the name of the grid that we are using to evaluate the function");
136 20 : keys.addInputKeyword("optional","ARG","scalar/vector","the arguments that you would like to use when evaluating the function. If not specified these are determined from the names of the grid dimensions");
137 10 : keys.reserve("compulsory","PERIODIC","if the output of your function is periodic then you should specify the periodicity of the function. If the output is not periodic you must state this using PERIODIC=NO");
138 20 : keys.addInputKeyword("optional","MASK","vector/matrix","the label for a sparse vector/matrix that should be used to determine which elements of the vector/matrix should be computed");
139 : EvaluateGridFunction ii;
140 10 : ii.registerKeywords( keys );
141 10 : keys.addActionNameSuffix("_SCALAR");
142 20 : keys.addActionNameSuffix("_VECTOR");
143 10 : }
144 :
145 6 : EvaluateFunctionOnGrid::EvaluateFunctionOnGrid(const ActionOptions&ao):
146 : Action(ao),
147 6 : ActionShortcut(ao) {
148 : // Get the grid that we are evaluating here
149 6 : std::vector<std::string> gridn(1);
150 6 : parse("GRID",gridn[0]);
151 6 : std::vector<Value*> gridv;
152 6 : ActionWithArguments::interpretArgumentList( gridn, plumed.getActionSet(), this, gridv );
153 : // Read the input arguments from the input file
154 6 : std::vector<std::string> argn;
155 12 : parseVector("ARG",argn);
156 : // Now get the arguments
157 6 : ActionWithGrid* ag = dynamic_cast<ActionWithGrid*>( gridv[0]->getPntrToAction() );
158 6 : if( !ag ) {
159 0 : error("argument to GRID argument is not a grid");
160 : }
161 6 : if( argn.size()==0 ) {
162 3 : std::vector<std::string> argn2( ag->getGridCoordinateNames() );
163 3 : argn.resize( argn2.size() );
164 7 : for(unsigned i=0; i<argn2.size(); ++i) {
165 : argn[i]=argn2[i];
166 : }
167 3 : }
168 6 : if( argn.size()!=gridv[0]->getRank() ) {
169 0 : error("found wrong number of arguments in Evaluate function on grid");
170 : }
171 : // Now use this information to create a gridobject
172 6 : if( ag->getGridCoordinatesObject().getGridType()=="fibonacci" ) {
173 0 : error("cannot interpolate on fibonacci sphere");
174 : }
175 : // Now get the actual values we are using
176 6 : std::vector<Value*> vals;
177 6 : ActionWithArguments::interpretArgumentList( argn, plumed.getActionSet(), this, vals );
178 6 : if( vals.size()==0 ) {
179 0 : error("found no input arguments to function");
180 : }
181 6 : std::string allargs = gridn[0];
182 16 : for(unsigned i=0; i<argn.size(); ++i) {
183 20 : allargs += "," + argn[i];
184 : }
185 6 : function::FunctionShortcut<int>::createAction( this, vals, allargs );
186 12 : }
187 :
188 :
189 : }
190 : }
|