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 "core/ActionShortcut.h" 24 : 25 : //+PLUMEDOC GRIDCALC INTEGRATE_GRID 26 : /* 27 : Calculate the numerical integral of the function stored on the grid 28 : 29 : This action takes a function, $f(x)$, that is stored on a grid of points between $a$ and $b$. It then computes the following definite integral 30 : numerically: 31 : 32 : $$ 33 : y = \int_a^b f(x) \textrm{d}x 34 : $$ 35 : 36 : The approximate value of this integral would be computed using: 37 : 38 : $$ 39 : y = \frac{b-a}{n} \sum_{i=0}^{n} f\left( a + \frac{i(b-a)}{n} \right) 40 : $$ 41 : 42 : where $n$ is the number of points at which the grid has been computed. 43 : 44 : The following example input demonstrates how this action can be used: 45 : 46 : ```plumed 47 : c1: COORDINATIONNUMBER SPECIESA=1-10 SPECIESB=1-200 SWITCH={RATIONAL R_0=1.0} 48 : hu: KDE ARG=c1 GRID_BIN=200 GRID_MIN=0 GRID_MAX=10 BANDWIDTH=0.1 49 : h: CUSTOM ARG=hu FUNC=x/10 PERIODIC=NO 50 : iv: INTEGRATE_GRID ARG=h PERIODIC=NO 51 : ``` 52 : 53 : In this case, the [KDE](KDE.md) action is used to compute a histogram that shows the instanenous distribution for 10 coordination numbers. This distribution is 54 : unormalised so that [CUSTOM](CUSTOM.md) command here is used to normalise the distribution. The resulting integral that is computed here should thsu be one. 55 : 56 : Notice also that the action can still be used if the function stored on the grid is a function of 2 or more variables. For example, the following input performs an integral 57 : that is very similar to the one performed in the previous. Now, however, the input grid is two dimensional. 58 : 59 : ```plumed 60 : c1: COORDINATIONNUMBER SPECIESA=1-10 SPECIESB=1-200 SWITCH={RATIONAL R_0=1.0} 61 : q6: Q6 SPECIESA=1-10 SPECIESB=1-200 SWITCH={RATIONAL R_0=1.0} 62 : hu: KDE ARG=c1,q6 GRID_BIN=200,200 GRID_MIN=0,-0.5 GRID_MAX=10,2 BANDWIDTH=0.1,0.1 63 : h: CUSTOM ARG=hu FUNC=x/10 PERIODIC=NO 64 : iv: INTEGRATE_GRID ARG=h PERIODIC=NO 65 : ``` 66 : 67 : */ 68 : //+ENDPLUMEDOC 69 : 70 : namespace PLMD { 71 : namespace gridtools { 72 : 73 : class IntegrateGrid : public ActionShortcut { 74 : public: 75 : static void registerKeywords(Keywords&); 76 : explicit IntegrateGrid(const ActionOptions&); 77 : }; 78 : 79 : PLUMED_REGISTER_ACTION(IntegrateGrid,"INTEGRATE_GRID") 80 : 81 28 : void IntegrateGrid::registerKeywords(Keywords& keys ) { 82 28 : ActionShortcut::registerKeywords( keys ); 83 56 : keys.addInputKeyword("compulsory","ARG","grid","the label of the function on a grid that is being integrated"); 84 28 : keys.add("compulsory","PERIODIC","if the value of the output integral has a periodid domain then you use this keyword to specify the periodicity. If the output integral is not periodic you must state this using PERIODIC=NO"); 85 56 : keys.setValueDescription("scalar","the numerical integral of the input function over its whole domain"); 86 28 : keys.needsAction("GET_VOLUME_ELEMENT"); 87 28 : keys.needsAction("SUM"); 88 28 : keys.needsAction("CUSTOM"); 89 28 : } 90 : 91 16 : IntegrateGrid::IntegrateGrid(const ActionOptions&ao): 92 : Action(ao), 93 16 : ActionShortcut(ao) { 94 : std::string gridname; 95 16 : parse("ARG", gridname); 96 16 : readInputLine( getShortcutLabel() + "_volelem: GET_VOLUME_ELEMENT ARG=" + gridname ); 97 48 : readInputLine( getShortcutLabel() + "_sum: SUM ARG=" + gridname + " PERIODIC=NO" ); 98 : std::string period; 99 16 : parse("PERIODIC", period); 100 64 : readInputLine( getShortcutLabel() + ": CUSTOM ARG=" + getShortcutLabel() + "_volelem," + getShortcutLabel() + "_sum FUNC=x*y PERIODIC=" + period ); 101 16 : } 102 : 103 : 104 : } 105 : }