1 // GetDP - Copyright (C) 1997-2021 P. Dular and C. Geuzaine, University of Liege
2 //
3 // See the LICENSE.txt file for license information. Please report all
4 // issues on https://gitlab.onelab.info/getdp/getdp/issues.
5
6 #include "GetDPConfig.h"
7 #include "Message.h"
8 #include "Bessel.h"
9
10 #if defined(HAVE_NO_FORTRAN)
11
zbesj_(double *,double *,double *,int *,int *,double *,double *,int *,int *)12 static void zbesj_(double*, double*, double*, int*, int*, double*,
13 double*, int*, int*)
14 {
15 Message::Fatal("Bessel functions require Fortran compiler");
16 }
17
zbesk_(double *,double *,double *,int *,int *,double *,double *,int *,int *)18 static void zbesk_(double*, double*, double*, int*, int*, double*,
19 double*, int*, int*)
20 {
21 Message::Fatal("Bessel functions require Fortran compiler");
22 }
23
zbesy_(double *,double *,double *,int *,int *,double *,double *,int *,double *,double *,int *)24 static void zbesy_(double*, double*, double*, int*, int*, double*,
25 double*, int*, double*, double*, int*)
26 {
27 Message::Fatal("Bessel functions require Fortran compiler");
28 }
29
zbesh_(double *,double *,double *,int *,int *,int *,double *,double *,int *,int *)30 static void zbesh_(double*, double*, double*, int*, int*, int*,
31 double*, double*, int*, int*)
32 {
33 Message::Fatal("Bessel functions require Fortran compiler");
34 }
35
36 #else
37
38 #if defined(HAVE_UNDERSCORE)
39 #define zbesj_ zbesj
40 define zbesk_ zbesk
41 #define zbesy_ zbesy
42 #define zbesh_ zbesh
43 #endif
44
45 extern "C" {
46 void zbesj_(double*, double*, double*, int*, int*, double*,
47 double*, int*, int*);
48 void zbesk_(double*, double*, double*, int*, int*, double*,
49 double*, int*, int*);
50
51 void zbesy_(double*, double*, double*, int*, int*, double*,
52 double*, int*, double*,
53 double*, int*);
54 void zbesh_(double*, double*, double*, int*, int*, int*, double*,
55 double*, int*, int*);
56 }
57
58 #endif
59
60 static int BesselError(int ierr, const char *str)
61 {
62 static int warn=0;
63
64 switch(ierr){
65 case 0 :
66 return 0;
67 case 1 :
68 Message::Error("Input error in %s", str);
69 return BESSEL_ERROR_INPUT;
70 case 2 :
71 return BESSEL_OVERFLOW;
72 case 3 :
73 if(!warn){
74 Message::Info("Half machine accuracy lost in %s (large argument or order)", str);
75 warn = 1;
76 }
77 return BESSEL_HALF_ACCURACY;
78 case 4 :
79 Message::Error("Complete loss of significance in %s (argument or order too large)", str);
80 return BESSEL_NO_ACCURACY;
81 case 5 :
82 Message::Error("Failed to converge in %s", str);
83 return BESSEL_NO_CONVERGENCE;
84 default:
85 Message::Info("Unknown Bessel status in %s (%d)", str, ierr);
86 return ierr;
87 }
88 }
89
90 // First kind Bessel functions
91
BesselJn(double n,int num,double x,double * val)92 int BesselJn(double n, int num, double x, double *val)
93 {
94 int nz = 0, ierr = 0, kode = 1;
95 double xi = 0.0;
96 double* ji = new double[num];
97
98 zbesj_(&x, &xi, &n, &kode, &num, val, ji, &nz, &ierr) ;
99
100 delete[] ji;
101
102 return BesselError(ierr, "BesselJn");
103 }
104
BesselJnComplex(double n,int num,double xr,double xi,double * valr,double * vali)105 int BesselJnComplex(double n, int num, double xr, double xi, double *valr, double *vali)
106 {
107 int nz = 0, ierr = 0, kode = 1;
108
109 zbesj_(&xr, &xi, &n, &kode, &num, valr, vali, &nz, &ierr) ;
110
111 return BesselError(ierr, "BesselJnComplex");
112 }
113
BesselKnComplex(double n,int num,double xr,double xi,double * valr,double * vali)114 int BesselKnComplex(double n, int num, double xr, double xi, double *valr, double *vali)
115 {
116 int nz = 0, ierr = 0, kode = 1;
117
118 zbesk_(&xr, &xi, &n, &kode, &num, valr, vali, &nz, &ierr) ;
119
120 return BesselError(ierr, "BesselKnComplex");
121 }
122
BesselSphericalJn(double n,int num,double x,double * val)123 int BesselSphericalJn(double n, int num, double x, double *val)
124 {
125 int ierr = BesselJn(n+0.5, num, x, val);
126 double coef = sqrt(0.5*M_PI/x);
127 for(int i = 0; i < num; i++){
128 val[i] *= coef;
129 }
130 return BesselError(ierr, "BesselSphericalJn");
131 }
132
BesselAltSphericalJn(double n,int num,double x,double * val)133 int BesselAltSphericalJn(double n, int num, double x, double *val)
134 {
135 int ierr = BesselJn(n+0.5, num, x, val);
136 double coef = sqrt(0.5*M_PI*x);
137 for(int i = 0; i < num; i++){
138 val[i] *= coef;
139 }
140 return BesselError(ierr, "BesselAltSphericalJn");
141 }
142
143 // Second kind Bessel functions
144
BesselYn(double n,int num,double x,double * val)145 int BesselYn(double n, int num, double x, double *val)
146 {
147 int nz = 0, ierr = 0, kode = 1;
148 double xi = 0.0;
149 double* yi = new double[num];
150 double* auxyr = new double[num];
151 double* auxyi = new double[num];
152
153 zbesy_(&x, &xi, &n, &kode, &num, val, yi, &nz, auxyr, auxyi, &ierr);
154
155 delete[] yi;
156 delete[] auxyr;
157 delete[] auxyi;
158
159 return BesselError(ierr, "BesselYn");
160 }
161
BesselSphericalYn(double n,int num,double x,double * val)162 int BesselSphericalYn(double n, int num, double x, double *val)
163 {
164 int ierr = BesselYn(n+0.5, num, x, val);
165 double coef = sqrt(0.5*M_PI/x);
166 for(int i = 0; i < num; i++){
167 val[i] *= coef;
168 }
169 return BesselError(ierr, "BesselSphericalYn");
170 }
171
BesselAltSphericalYn(double n,int num,double x,double * val)172 int BesselAltSphericalYn(double n, int num, double x, double *val)
173 {
174 int ierr = BesselYn(n+0.5, num, x, val);
175 double coef = sqrt(0.5*M_PI*x);
176 for(int i = 0; i < num; i++){
177 val[i] *= coef;
178 }
179 return BesselError(ierr, "BesselAltSphericalYn");
180 }
181
182 // Hankel functions (type = 1 or 2)
183
BesselHn(int type,double n,int num,double x,std::complex<double> * val)184 int BesselHn(int type, double n, int num, double x, std::complex<double> *val)
185 {
186 int nz = 0, ierr = 0, kode = 1;
187 double* hr = new double[num];
188 double* hi = new double[num];
189 double xi = 0.0;
190
191 zbesh_(&x, &xi, &n, &kode, &type, &num, hr, hi, &nz, &ierr);
192
193 for(int i=0; i < num; i++){
194 val[i] = std::complex<double>(hr[i], hi[i]);
195 }
196
197 delete[] hr;
198 delete[] hi;
199
200 return BesselError(ierr, "BesselHn");
201 }
202
BesselSphericalHn(int type,double n,int num,double x,std::complex<double> * val)203 int BesselSphericalHn(int type, double n, int num, double x, std::complex<double> *val)
204 {
205 int ierr = BesselHn(type, n+0.5, num, x, val);
206 double coef = sqrt(0.5*M_PI/x);
207 for(int i = 0; i < num; i++){
208 val[i] *= coef;
209 }
210 return BesselError(ierr, "BesselSphericalHn");
211 }
212
BesselAltSphericalHn(int type,double n,int num,double x,std::complex<double> * val)213 int BesselAltSphericalHn(int type, double n, int num, double x, std::complex<double> *val)
214 {
215 int ierr = BesselHn(type, n+0.5, num, x, val);
216 double coef = sqrt(0.5*M_PI*x);
217 for(int i = 0; i < num; i++){
218 val[i] *= coef;
219 }
220 return BesselError(ierr, "BesselAltSphericalHn");
221 }
222
223 // Utilities for backward compatibility
224
Spherical_j_n(int n,double x)225 double Spherical_j_n(int n, double x)
226 {
227 double res;
228 BesselSphericalJn(n, 1, x, &res);
229 return res;
230 }
231
AltSpherical_j_n(int n,double x)232 double AltSpherical_j_n(int n, double x)
233 {
234 double res;
235 BesselAltSphericalJn(n, 1, x, &res);
236 return res;
237 }
238
Spherical_y_n(int n,double x)239 double Spherical_y_n(int n, double x)
240 {
241 double res;
242 BesselSphericalYn(n, 1, x, &res);
243 return res;
244 }
245
AltSpherical_y_n(int n,double x)246 double AltSpherical_y_n(int n, double x)
247 {
248 double res;
249 BesselAltSphericalYn(n, 1, x, &res);
250 return res;
251 }
252