1

I am trying to calculate second order bessel functions (Y_v(x)) using Java. Where v, the order of the bessel function, is non integer.

Apache, I know, has a function to calculated first order bessel functions (J_v(x))

import org.apache.commons.math3.special.BesselJ;

BesselJ bj = new BesselJ(10.5);
double bjr = bj.value(r);

Which can calculate non-integer first order bessel functions (but not negative order functions). I do not believe it has an equivalent for second order.

I have found a formula for calculating second order bessel functions (equation 6.4.2 of Numerical Recipies among other places) which calculates second order bessel functions from first order functions.

enter image description here

However this equation requires the first order bessel functions to accept negative v values which the apache BesselJ function does not.

I have written a program to calculate BesselJ functions whch accept negative values using the formula (Numerical Recipes 6.4.1)

enter image description here

import org.apache.commons.math3.special.Gamma;
import org.apache.commons.math3.util.ArithmeticUtils;

private static int lmax;
private static double[][] Gammas;
private static int besselcount;

public static Double Bessel_J(double m, double x){

    double BJ = 0.0;
    for (int k = 0; k < besselcount;k++){
        double kk = (double) k;     
        double llmm = (double) lmax;
        double A = Math.pow(x/2.,(2.*kk)+m);
        double B = Gammas[(int) (m+llmm+0.5)][k];
        if (B==0.0||B==-0.0){break;}
            BJ = BJ + A*B;
        }

        return BJ;
}

public static void main(String[] args) throws Exception {

    besselcount = 80;
    lmax = 20;

    Gammas = new double[2*lmax+2][besselcount+1];
    for (int n = 0;n <= ((2*lmax)+1);n++){
        for (int m = 0;m <=besselcount;m++) {
            double nn = (double) n;
            double mm = (double) m;
            double llmm = (double) lmax;
            Gammas[n][m] =   Math.pow(-1,m)/(ArithmeticUtils.factorialDouble(m)*Gamma.gamma(1.+nn-llmm-0.5+mm));
        }
    }

    for (double x = 0.02; x < 50.0 ; x = x + 0.02){
        double bj = Bessel_J(-10.5, x);
        System.out.println(x+" "+bj);
    }

}

(Having the gammas precalculated and stored in an array is just because of how the bessel function is used in the rest of the code, to avoid recalculating this unnecessarily)

The function I have written works for low x values but then looses stability. For the v = -10.5 value I have used after around x = 30. As shown in the figure.

enter image description here

On the wolfram alpha website is says mathematica uses the same equations to calculate bessel functions and mathematica's BesselJ function can calculate

Show[Plot[BesselJ[-10.5, x], {x, 0, 50}], ImageSize -> Full]

Without loosing stability.

enter image description here

Any advice on either how to correct my functions or alternative ways to calculate second order bessel functions using Java would be very much appreciated.

Please say if any clarification would be useful.

Thank you

James
  • 105
  • 3
  • 17
  • I haven't had a chance to test this yet, but it could be that `double` has insufficient precision. Have you tried using `BigDecimal` instead? – azurefrog Apr 26 '16 at 18:31
  • Thank you for the interest. I am afraid I have tried improving the precision using Apfloat (as I needed hyperbolic functions) and this did not resolve the issue. – James Apr 26 '16 at 18:36

0 Answers0