LCOV - code coverage report
Current view: top level - function - Bessel.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 35 41 85.4 %
Date: 2025-04-08 18:07:56 Functions: 5 6 83.3 %

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

Generated by: LCOV version 1.16