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 48 : 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 { return false; }
73 : void registerKeywords( Keywords& keys ) override;
74 : void read( ActionWithArguments* action ) override;
75 : void calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const override;
76 : };
77 :
78 : typedef FunctionShortcut<Bessel> BesselShortcut;
79 : PLUMED_REGISTER_ACTION(BesselShortcut,"BESSEL")
80 : typedef FunctionOfScalar<Bessel> ScalarBessel;
81 : PLUMED_REGISTER_ACTION(ScalarBessel,"BESSEL_SCALAR")
82 : typedef FunctionOfVector<Bessel> VectorBessel;
83 : PLUMED_REGISTER_ACTION(VectorBessel,"BESSEL_VECTOR")
84 :
85 34 : void Bessel::registerKeywords(Keywords& keys) {
86 68 : keys.add("compulsory","ORDER","0","the order of Bessel function to use. Can only be zero at the moment.");
87 68 : keys.setValueDescription("scalar/vector","the value of the bessel function");
88 34 : }
89 :
90 7 : void Bessel::read( ActionWithArguments* action ) {
91 7 : if( action->getNumberOfArguments()!=1 ) action->error("should only be one argument to bessel actions");
92 7 : if( action->getPntrToArgument(0)->isPeriodic() ) action->error("cannot use this function on periodic functions");
93 14 : action->parse("ORDER",order); action->log.printf(" computing %dth order bessel function \n", order );
94 7 : if( order!=0 ) action->error("only zero order bessel function is implemented");
95 7 : fill_coefficients();
96 7 : }
97 :
98 14 : double Bessel::chbevl(double x,std::vector<double>& array) const {
99 : double b0, b1, b2;
100 14 : int n = array.size();
101 :
102 14 : b0 = array[0];
103 : b1 = 0.0;
104 : b2 = b1 ;
105 :
106 375 : for(int index = 1 ; index < n ; index++) {
107 : b2 = b1;
108 : b1 = b0;
109 361 : b0 = x * b1 - b2 + array[index];
110 : }
111 14 : return (0.5 * (b0 - b2));
112 : }
113 :
114 :
115 14 : void Bessel::calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const {
116 : plumed_dbg_assert( args.size()==1 );
117 14 : if( order==0 ) {
118 14 : double x = fabs(args[0]);
119 14 : if (x <= 8.0) {
120 5 : double y = (x / 2.0) - 2.0;
121 5 : vals[0] = chbevl(y, A) ;
122 5 : return;
123 : }
124 9 : vals[0] = chbevl(32.0 / x - 2.0, B) / sqrt(x) ;
125 0 : } else plumed_error();
126 : }
127 :
128 : std::vector<double> Bessel::A;
129 : std::vector<double> Bessel::B;
130 :
131 7 : void Bessel::fill_coefficients() {
132 7 : A.resize(30);
133 14 : A = {-4.41534164647933937950E-18,
134 : 3.33079451882223809783E-17,
135 : -2.43127984654795469359E-16,
136 : 1.71539128555513303061E-15,
137 : -1.16853328779934516808E-14,
138 : 7.67618549860493561688E-14,
139 : -4.85644678311192946090E-13,
140 : 2.95505266312963983461E-12,
141 : -1.72682629144155570723E-11,
142 : 9.67580903537323691224E-11,
143 : -5.18979560163526290666E-10,
144 : 2.65982372468238665035E-9,
145 : -1.30002500998624804212E-8,
146 : 6.04699502254191894932E-8,
147 : -2.67079385394061173391E-7,
148 : 1.11738753912010371815E-6,
149 : -4.41673835845875056359E-6,
150 : 1.64484480707288970893E-5,
151 : -5.75419501008210370398E-5,
152 : 1.88502885095841655729E-4,
153 : -5.76375574538582365885E-4,
154 : 1.63947561694133579842E-3,
155 : -4.32430999505057594430E-3,
156 : 1.05464603945949983183E-2,
157 : -2.37374148058994688156E-2,
158 : 4.93052842396707084878E-2,
159 : -9.49010970480476444210E-2,
160 : 1.71620901522208775349E-1,
161 : -3.04682672343198398683E-1,
162 : 6.76795274409476084995E-1
163 7 : };
164 7 : B.resize(25);
165 14 : B = {-7.23318048787475395456E-18,
166 : -4.83050448594418207126E-18,
167 : 4.46562142029675999901E-17,
168 : 3.46122286769746109310E-17,
169 : -2.82762398051658348494E-16,
170 : -3.42548561967721913462E-16,
171 : 1.77256013305652638360E-15,
172 : 3.81168066935262242075E-15,
173 : -9.55484669882830764870E-15,
174 : -4.15056934728722208663E-14,
175 : 1.54008621752140982691E-14,
176 : 3.85277838274214270114E-13,
177 : 7.18012445138366623367E-13,
178 : -1.79417853150680611778E-12,
179 : -1.32158118404477131188E-11,
180 : -3.14991652796324136454E-11,
181 : 1.18891471078464383424E-11,
182 : 4.94060238822496958910E-10,
183 : 3.39623202570838634515E-9,
184 : 2.26666899049817806459E-8,
185 : 2.04891858946906374183E-7,
186 : 2.89137052083475648297E-6,
187 : 6.88975834691682398426E-5,
188 : 3.36911647825569408990E-3,
189 : 8.04490411014108831608E-1
190 7 : };
191 7 : }
192 :
193 : }
194 : }
195 :
196 :
|