Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2017 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 "FunctionTemplateBase.h"
23 : #include "FunctionShortcut.h"
24 : #include "FunctionOfScalar.h"
25 : #include "FunctionOfVector.h"
26 : #include "core/ActionRegister.h"
27 : #include "tools/SwitchingFunction.h"
28 : #include <array>
29 : #include <cmath>
30 :
31 : namespace PLMD {
32 : namespace function {
33 :
34 : //+PLUMEDOC FUNCTION BESSEL
35 : /*
36 : Calculate the value of a Bessel function.
37 :
38 : \par Examples
39 :
40 : */
41 : //+ENDPLUMEDOC
42 :
43 : //+PLUMEDOC FUNCTION BESSEL_SCALAR
44 : /*
45 : Calculate the value of a Bessel function.
46 :
47 : \par Examples
48 :
49 : */
50 : //+ENDPLUMEDOC
51 :
52 : //+PLUMEDOC FUNCTION BESSEL_VECTOR
53 : /*
54 : Calculate the bessel function for all the elements in a vector
55 :
56 : \par Examples
57 :
58 : */
59 : //+ENDPLUMEDOC
60 :
61 :
62 54 : class Bessel : public FunctionTemplateBase {
63 : private:
64 : unsigned order;
65 : // Cheb coefficient for range [0,8]
66 : static std::vector<double> A;
67 : // Cheb coefficient for range (8,inf)
68 : static std::vector<double> B;
69 : double chbevl(double x,std::vector<double>& array) const; // sub copied from scipy in C
70 : void fill_coefficients();
71 : public:
72 0 : bool derivativesImplemented() override {
73 0 : return false;
74 : }
75 : void registerKeywords( Keywords& keys ) override;
76 : void read( ActionWithArguments* action ) override;
77 : void calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const override;
78 : };
79 :
80 : typedef FunctionShortcut<Bessel> BesselShortcut;
81 : PLUMED_REGISTER_ACTION(BesselShortcut,"BESSEL")
82 : typedef FunctionOfScalar<Bessel> ScalarBessel;
83 : PLUMED_REGISTER_ACTION(ScalarBessel,"BESSEL_SCALAR")
84 : typedef FunctionOfVector<Bessel> VectorBessel;
85 : PLUMED_REGISTER_ACTION(VectorBessel,"BESSEL_VECTOR")
86 :
87 40 : void Bessel::registerKeywords(Keywords& keys) {
88 80 : keys.add("compulsory","ORDER","0","the order of Bessel function to use. Can only be zero at the moment.");
89 40 : keys.setValueDescription("the value of the bessel function");
90 40 : }
91 :
92 7 : void Bessel::read( ActionWithArguments* action ) {
93 7 : if( action->getNumberOfArguments()!=1 ) {
94 0 : action->error("should only be one argument to bessel actions");
95 : }
96 7 : if( action->getPntrToArgument(0)->isPeriodic() ) {
97 0 : action->error("cannot use this function on periodic functions");
98 : }
99 7 : action->parse("ORDER",order);
100 7 : action->log.printf(" computing %dth order bessel function \n", order );
101 7 : if( order!=0 ) {
102 0 : action->error("only zero order bessel function is implemented");
103 : }
104 7 : fill_coefficients();
105 7 : }
106 :
107 14 : double Bessel::chbevl(double x,std::vector<double>& array) const {
108 : double b0, b1, b2;
109 14 : int n = array.size();
110 :
111 14 : b0 = array[0];
112 : b1 = 0.0;
113 : b2 = b1 ;
114 :
115 375 : for(int index = 1 ; index < n ; index++) {
116 : b2 = b1;
117 : b1 = b0;
118 361 : b0 = x * b1 - b2 + array[index];
119 : }
120 14 : return (0.5 * (b0 - b2));
121 : }
122 :
123 :
124 14 : void Bessel::calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const {
125 : plumed_dbg_assert( args.size()==1 );
126 14 : if( order==0 ) {
127 14 : double x = fabs(args[0]);
128 14 : if (x <= 8.0) {
129 5 : double y = (x / 2.0) - 2.0;
130 5 : vals[0] = chbevl(y, A) ;
131 5 : return;
132 : }
133 9 : vals[0] = chbevl(32.0 / x - 2.0, B) / sqrt(x) ;
134 : } else {
135 0 : plumed_error();
136 : }
137 : }
138 :
139 : std::vector<double> Bessel::A;
140 : std::vector<double> Bessel::B;
141 :
142 7 : void Bessel::fill_coefficients() {
143 7 : A.resize(30);
144 14 : A = {-4.41534164647933937950E-18,
145 : 3.33079451882223809783E-17,
146 : -2.43127984654795469359E-16,
147 : 1.71539128555513303061E-15,
148 : -1.16853328779934516808E-14,
149 : 7.67618549860493561688E-14,
150 : -4.85644678311192946090E-13,
151 : 2.95505266312963983461E-12,
152 : -1.72682629144155570723E-11,
153 : 9.67580903537323691224E-11,
154 : -5.18979560163526290666E-10,
155 : 2.65982372468238665035E-9,
156 : -1.30002500998624804212E-8,
157 : 6.04699502254191894932E-8,
158 : -2.67079385394061173391E-7,
159 : 1.11738753912010371815E-6,
160 : -4.41673835845875056359E-6,
161 : 1.64484480707288970893E-5,
162 : -5.75419501008210370398E-5,
163 : 1.88502885095841655729E-4,
164 : -5.76375574538582365885E-4,
165 : 1.63947561694133579842E-3,
166 : -4.32430999505057594430E-3,
167 : 1.05464603945949983183E-2,
168 : -2.37374148058994688156E-2,
169 : 4.93052842396707084878E-2,
170 : -9.49010970480476444210E-2,
171 : 1.71620901522208775349E-1,
172 : -3.04682672343198398683E-1,
173 : 6.76795274409476084995E-1
174 7 : };
175 7 : B.resize(25);
176 14 : B = {-7.23318048787475395456E-18,
177 : -4.83050448594418207126E-18,
178 : 4.46562142029675999901E-17,
179 : 3.46122286769746109310E-17,
180 : -2.82762398051658348494E-16,
181 : -3.42548561967721913462E-16,
182 : 1.77256013305652638360E-15,
183 : 3.81168066935262242075E-15,
184 : -9.55484669882830764870E-15,
185 : -4.15056934728722208663E-14,
186 : 1.54008621752140982691E-14,
187 : 3.85277838274214270114E-13,
188 : 7.18012445138366623367E-13,
189 : -1.79417853150680611778E-12,
190 : -1.32158118404477131188E-11,
191 : -3.14991652796324136454E-11,
192 : 1.18891471078464383424E-11,
193 : 4.94060238822496958910E-10,
194 : 3.39623202570838634515E-9,
195 : 2.26666899049817806459E-8,
196 : 2.04891858946906374183E-7,
197 : 2.89137052083475648297E-6,
198 : 6.88975834691682398426E-5,
199 : 3.36911647825569408990E-3,
200 : 8.04490411014108831608E-1
201 7 : };
202 7 : }
203 :
204 : }
205 : }
206 :
207 :
|