Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2016-2018 The VES code team
3 : (see the PEOPLE-VES file at the root of this folder for a list of names)
4 :
5 : See http://www.ves-code.org for more information.
6 :
7 : This file is part of VES code module.
8 :
9 : The VES code module 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 : The VES code module 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 the VES code module. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 :
23 : #include "BasisFunctions.h"
24 :
25 : #include "core/ActionRegister.h"
26 :
27 :
28 : namespace PLMD {
29 : namespace ves {
30 :
31 : //+PLUMEDOC VES_BASISF BF_FOURIER
32 : /*
33 : Fourier basis functions.
34 :
35 : Use as basis functions Fourier series defined on a periodic interval.
36 : You need to provide the periodic interval \f$[a,b]\f$
37 : on which the basis functions are to be used, and the order of the
38 : expansion \f$N\f$ (i.e. the highest Fourier mode used).
39 : The total number of basis functions is \f$2N+1\f$ as for each Fourier
40 : mode there is both the cosine and sine term,
41 : and the constant \f$f_{0}(x)=1\f$ is also included.
42 : These basis functions should only be used for periodic CVs.
43 :
44 : The Fourier series basis functions are given by
45 : \f{align}{
46 : f_{0}(x) &= 1 \\
47 : f_{1}(x) &= cos(\frac{2\pi }{P} x) \\
48 : f_{2}(x) &= sin(\frac{2\pi }{P} x) \\
49 : f_{3}(x) &= cos(2 \cdot \frac{2\pi}{P} x) \\
50 : f_{4}(x) &= sin(2 \cdot \frac{2\pi}{P} x) \\
51 : & \vdots \\
52 : f_{2k-1}(x) &= cos(k \cdot \frac{2\pi}{P} x) \\
53 : f_{2k}(x) &= sin(k \cdot \frac{2\pi}{P} x) \\
54 : & \vdots \\
55 : f_{2N-1}(x) &= cos(N \cdot \frac{2\pi}{P} x) \\
56 : f_{2N}(x) &= sin(N \cdot \frac{2\pi}{P} x) \\
57 : \f}
58 : where \f$P=(b-a)\f$ is the periodicity of the interval.
59 : They are orthogonal over the interval \f$[a,b]\f$
60 : \f[
61 : \int_{a}^{b} dx \, f_{n}(x)\, f_{m}(x) =
62 : \begin{cases}
63 : 0 & n \neq m \\
64 : (b-a) & n = m = 0 \\
65 : (b-a)/2 & n = m \neq 0
66 : \end{cases}.
67 : \f]
68 :
69 :
70 : \par Examples
71 :
72 : Here we employ a Fourier expansion of order 10 over the periodic interval
73 : \f$-\pi\f$ to \f$+\pi\f$.
74 : This results in a total number of 21 basis functions.
75 : The label used to identify the basis function action can then be
76 : referenced later on in the input file.
77 : \plumedfile
78 : BF_FOURIER MINIMUM=-pi MAXIMUM=+pi ORDER=10 LABEL=bf_fourier
79 : \endplumedfile
80 :
81 :
82 : */
83 : //+ENDPLUMEDOC
84 :
85 91 : class BF_Fourier : public BasisFunctions {
86 : virtual void setupLabels();
87 : virtual void setupUniformIntegrals();
88 : public:
89 : static void registerKeywords(Keywords&);
90 : explicit BF_Fourier(const ActionOptions&);
91 : void getAllValues(const double, double&, bool&, std::vector<double>&, std::vector<double>&) const;
92 : };
93 :
94 :
95 6543 : PLUMED_REGISTER_ACTION(BF_Fourier,"BF_FOURIER")
96 :
97 :
98 92 : void BF_Fourier::registerKeywords(Keywords& keys) {
99 92 : BasisFunctions::registerKeywords(keys);
100 92 : }
101 :
102 :
103 91 : BF_Fourier::BF_Fourier(const ActionOptions&ao):
104 91 : PLUMED_VES_BASISFUNCTIONS_INIT(ao)
105 : {
106 91 : setNumberOfBasisFunctions(2*getOrder()+1);
107 273 : setIntrinsicInterval("-pi","+pi");
108 : setPeriodic();
109 : setIntervalBounded();
110 182 : setType("trigonometric_cos-sin");
111 182 : setDescription("Trigonometric (cos/sin)");
112 91 : setupBF();
113 91 : checkRead();
114 91 : }
115 :
116 :
117 3243198 : void BF_Fourier::getAllValues(const double arg, double& argT, bool& inside_range, std::vector<double>& values, std::vector<double>& derivs) const {
118 : // plumed_assert(values.size()==numberOfBasisFunctions());
119 : // plumed_assert(derivs.size()==numberOfBasisFunctions());
120 3243198 : inside_range=true;
121 3243198 : argT=translateArgument(arg, inside_range);
122 3243198 : values[0]=1.0;
123 3243198 : derivs[0]=0.0;
124 32362764 : for(unsigned int i=1; i < getOrder()+1; i++) {
125 14559783 : double io = i;
126 14559783 : double cos_tmp = cos(io*argT);
127 14559783 : double sin_tmp = sin(io*argT);
128 29119566 : values[2*i-1] = cos_tmp;
129 29119566 : derivs[2*i-1] = -io*sin_tmp*intervalDerivf();
130 29119566 : values[2*i] = sin_tmp;
131 29119566 : derivs[2*i] = io*cos_tmp*intervalDerivf();
132 : }
133 3243198 : if(!inside_range) {
134 69638 : for(unsigned int i=0; i<derivs.size(); i++) {derivs[i]=0.0;}
135 : }
136 3243198 : }
137 :
138 :
139 91 : void BF_Fourier::setupLabels() {
140 182 : setLabel(0,"1");
141 997 : for(unsigned int i=1; i < getOrder()+1; i++) {
142 453 : std::string is; Tools::convert(i,is);
143 1359 : setLabel(2*i-1,"cos("+is+"*s)");
144 1359 : setLabel(2*i,"sin("+is+"*s)");
145 : }
146 91 : }
147 :
148 :
149 90 : void BF_Fourier::setupUniformIntegrals() {
150 : setAllUniformIntegralsToZero();
151 : setUniformIntegral(0,1.0);
152 90 : }
153 :
154 :
155 : }
156 4839 : }
|