LifeV
bessik.cpp
Go to the documentation of this file.
1 // bessik.cpp -- computation of modified Bessel functions In, Kn
2 // and their derivatives. Algorithms and coefficient values from
3 // "Computation of Special Functions", Zhang and Jin, John
4 // Wiley and Sons, 1996.
5 //
6 // (C) 2003, C. Bond. All rights reserved.
7 //
8 #include <lifev/navier_stokes/function/bessel/bessel.hpp>
9 namespace bessel
10 {
11 double gamma (double x);
12 
13 int bessik01a (double x, double& i0, double& i1, double& k0, double& k1,
14  double& i0p, double& i1p, double& k0p, double& k1p)
15 {
16  double r, x2, ca, cb, ct, ww, w0, xr, xr2;
17  int k, kz;
18  static double a[] =
19  {
20  0.125,
21  7.03125e-2,
22  7.32421875e-2,
23  1.1215209960938e-1,
24  2.2710800170898e-1,
25  5.7250142097473e-1,
26  1.7277275025845,
27  6.0740420012735,
28  2.4380529699556e1,
29  1.1001714026925e2,
30  5.5133589612202e2,
31  3.0380905109224e3
32  };
33  static double b[] =
34  {
35  -0.375,
36  -1.171875e-1,
37  -1.025390625e-1,
38  -1.4419555664063e-1,
39  -2.7757644653320e-1,
40  -6.7659258842468e-1,
41  -1.9935317337513,
42  -6.8839142681099,
43  -2.7248827311269e1,
44  -1.2159789187654e2,
45  -6.0384407670507e2,
46  -3.3022722944809e3
47  };
48  static double a1[] =
49  {
50  0.125,
51  0.2109375,
52  1.0986328125,
53  1.1775970458984e1,
54  2.1461706161499e2,
55  5.9511522710323e3,
56  2.3347645606175e5,
57  1.2312234987631e7
58  };
59 
60  if (x < 0.0)
61  {
62  return 1;
63  }
64  if (x == 0.0)
65  {
66  i0 = 1.0;
67  i1 = 0.0;
68  k0 = 1e308;
69  k1 = 1e308;
70  i0p = 0.0;
71  i1p = 0.5;
72  k0p = -1e308;
73  k1p = -1e308;
74  return 0;
75  }
76  x2 = x * x;
77  if (x <= 18.0)
78  {
79  i0 = 1.0;
80  r = 1.0;
81  for (k = 1; k <= 50; k++)
82  {
83  r *= 0.25 * x2 / (k * k);
84  i0 += r;
85  if (std::fabs (r / i0) < eps)
86  {
87  break;
88  }
89  }
90  i1 = 1.0;
91  r = 1.0;
92  for (k = 1; k <= 50; k++)
93  {
94  r *= 0.25 * x2 / (k * (k + 1) );
95  i1 += r;
96  if (std::fabs (r / i1) < eps)
97  {
98  break;
99  }
100  }
101  i1 *= 0.5 * x;
102  }
103  else
104  {
105  if (x >= 50.0)
106  {
107  kz = 7;
108  }
109  else if (x >= 35.0)
110  {
111  kz = 9;
112  }
113  else
114  {
115  kz = 12;
116  }
117  ca = std::exp (x) / std::sqrt (2.0 * M_PI * x);
118  i0 = 1.0;
119  xr = 1.0 / x;
120  for (k = 0; k < kz; k++)
121  {
122  i0 += a[k] * std::pow (xr, k + 1);
123  }
124  i0 *= ca;
125  i1 = 1.0;
126  for (k = 0; k < kz; k++)
127  {
128  i1 += b[k] * std::pow (xr, k + 1);
129  }
130  i1 *= ca;
131  }
132  if (x <= 9.0)
133  {
134  ct = - (std::log (0.5 * x) + el);
135  k0 = 0.0;
136  w0 = 0.0;
137  r = 1.0;
138  ww = 0.0;
139  for (k = 1; k <= 50; k++)
140  {
141  w0 += 1.0 / k;
142  r *= 0.25 * x2 / (k * k);
143  k0 += r * (w0 + ct);
144  if (std::fabs ( (k0 - ww) / k0) < eps)
145  {
146  break;
147  }
148  ww = k0;
149  }
150  k0 += ct;
151  }
152  else
153  {
154  cb = 0.5 / x;
155  xr2 = 1.0 / x2;
156  k0 = 1.0;
157  for (k = 0; k < 8; k++)
158  {
159  k0 += a1[k] * std::pow (xr2, k + 1);
160  }
161  k0 *= cb / i0;
162  }
163  k1 = (1.0 / x - i1 * k0) / i0;
164  i0p = i1;
165  i1p = i0 - i1 / x;
166  k0p = -k1;
167  k1p = -k0 - k1 / x;
168  return 0;
169 }
170 
171 int bessik01b (double x, double& i0, double& i1, double& k0, double& k1,
172  double& i0p, double& i1p, double& k0p, double& k1p)
173 {
174  double t, t2, dtmp, dtmp1;
175 
176  if (x < 0.0)
177  {
178  return 1;
179  }
180  if (x == 0.0)
181  {
182  i0 = 1.0;
183  i1 = 0.0;
184  k0 = 1e308;
185  k1 = 1e308;
186  i0p = 0.0;
187  i1p = 0.5;
188  k0p = -1e308;
189  k1p = -1e308;
190  return 0;
191  }
192  if (x < 3.75)
193  {
194  t = x / 3.75;
195  t2 = t * t;
196  i0 = ( ( ( ( (0.0045813 * t2 + 0.0360768) * t2 + 0.2659732) * t2 +
197  1.2067492) * t2 + 3.0899424) * t2 + 3.5156229) * t2 + 1.0;
198  i1 = x * ( ( ( ( (0.00032411 * t2 + 0.00301532) * t2 + 0.02658733 * t2 +
199  0.15084934) * t2 + 0.51498869) * t2 + 0.87890594) * t2 + 0.5);
200  }
201  else
202  {
203  t = 3.75 / x;
204  dtmp1 = std::exp (x) / std::sqrt (x);
205  dtmp = ( ( ( ( ( ( (0.00392377 * t - 0.01647633) * t + 0.026355537) * t - 0.02057706) * t +
206  0.00916281) * t - 0.00157565) * t + 0.00225319) * t + 0.01328592) * t + 0.39894228;
207  i0 = dtmp * dtmp1;
208  dtmp = ( ( ( ( ( ( (-0.00420059 * t + 0.01787654) * t - 0.02895312) * t + 0.02282967) * t -
209  0.01031555) * t + 0.00163801) * t - 0.00362018) * t - 0.03988024) * t + 0.39894228;
210  i1 = dtmp * dtmp1;
211  }
212  if (x < 2.0)
213  {
214  t = 0.5 * x;
215  t2 = t * t; // already calculated above
216  dtmp = ( ( ( ( (0.0000074 * t2 + 0.0001075) * t2 + 0.00262698) * t2 + 0.0348859) * t2 +
217  0.23069756) * t2 + 0.4227842) * t2 - 0.57721566;
218  k0 = dtmp - i0 * std::log (t);
219  dtmp = ( ( ( ( (-0.00004686 * t2 - 0.00110404) * t2 - 0.01919402) * t2 -
220  0.18156897) * t2 - 0.67278578) * t2 + 0.15443144) * t2 + 1.0;
221  k1 = dtmp / x + i1 * std::log (t);
222  }
223  else
224  {
225  t = 2.0 / x;
226  dtmp1 = std::exp (-x) / std::sqrt (x);
227  dtmp = ( ( ( ( (0.00053208 * t - 0.0025154) * t + 0.00587872) * t - 0.01062446) * t +
228  0.02189568) * t - 0.07832358) * t + 1.25331414;
229  k0 = dtmp * dtmp1;
230  dtmp = ( ( ( ( (-0.00068245 * t + 0.00325614) * t - 0.00780353) * t + 0.01504268) * t -
231  0.0365562) * t + 0.23498619) * t + 1.25331414;
232  k1 = dtmp * dtmp1;
233  }
234  i0p = i1;
235  i1p = i0 - i1 / x;
236  k0p = -k1;
237  k1p = -k0 - k1 / x;
238  return 0;
239 }
240 int bessikna (int n, double x, int& nm, double* in, double* kn,
241  double* inp, double* knp)
242 {
243  double bi0, bi1, bk0, bk1, g, g0, g1, f, f0, f1, h, h0, h1, s0;
244  int k, m;
245 
246  if ( (x < 0.0) || (n < 0) )
247  {
248  return 1;
249  }
250  if (x < eps)
251  {
252  for (k = 0; k <= n; k++)
253  {
254  in[k] = 0.0;
255  kn[k] = 1e308;
256  inp[k] = 0.0;
257  knp[k] = -1e308;
258  }
259  in[0] = 1.0;
260  inp[1] = 0.5;
261  return 0;
262  }
263  nm = n;
264  bessik01a (x, in[0], in[1], kn[0], kn[1], inp[0], inp[1], knp[0], knp[1]);
265  if (n < 2)
266  {
267  return 0;
268  }
269  bi0 = in[0];
270  bi1 = in[1];
271  bk0 = kn[0];
272  bk1 = kn[1];
273  if ( (x > 40.0) && (n < (int) (0.25 * x) ) )
274  {
275  h0 = bi0;
276  h1 = bi1;
277  for (k = 2; k <= n; k++)
278  {
279  h = -2.0 * (k - 1.0) * h1 / x + h0;
280  in[k] = h;
281  h0 = h1;
282  h1 = h;
283  }
284  }
285  else
286  {
287  m = msta1 (x, 200);
288  if (m < n)
289  {
290  nm = m;
291  }
292  else
293  {
294  m = msta2 (x, n, 15);
295  }
296  f0 = 0.0;
297  f1 = 1.0e-100;
298  for (k = m; k >= 0; k--)
299  {
300  f = 2.0 * (k + 1.0) * f1 / x + f0;
301  if (x <= nm)
302  {
303  in[k] = f;
304  }
305  f0 = f1;
306  f1 = f;
307  }
308  s0 = bi0 / f;
309  for (k = 0; k <= m; k++)
310  {
311  in[k] *= s0;
312  }
313  }
314  g0 = bk0;
315  g1 = bk1;
316  for (k = 2; k <= nm; k++)
317  {
318  g = 2.0 * (k - 1.0) * g1 / x + g0;
319  kn[k] = g;
320  g0 = g1;
321  g1 = g;
322  }
323  for (k = 2; k <= nm; k++)
324  {
325  inp[k] = in[k - 1] - k * in[k] / x;
326  knp[k] = -kn[k - 1] - k * kn[k] / x;
327  }
328  return 0;
329 }
330 int bessiknb (int n, double x, int& nm, double* in, double* kn,
331  double* inp, double* knp)
332 {
333  double s0, bs, f (0), f0, f1, sk0, a0, bkl, vt, r, g, g0, g1;
334  int k, kz, m, l;
335 
336  if ( (x < 0.0) || (n < 0) )
337  {
338  return 1;
339  }
340  if (x < eps)
341  {
342  for (k = 0; k <= n; k++)
343  {
344  in[k] = 0.0;
345  kn[k] = 1e308;
346  inp[k] = 0.0;
347  knp[k] = -1e308;
348  }
349  in[0] = 1.0;
350  inp[1] = 0.5;
351  return 0;
352  }
353  nm = n;
354  if (n == 0)
355  {
356  nm = 1;
357  }
358  m = msta1 (x, 200);
359  if (m < nm)
360  {
361  nm = m;
362  }
363  else
364  {
365  m = msta2 (x, nm, 15);
366  }
367  bs = 0.0;
368  sk0 = 0.0;
369  f0 = 0.0;
370  f1 = 1.0e-100;
371  for (k = m; k >= 0; k--)
372  {
373  f = 2.0 * (k + 1.0) * f1 / x + f0;
374  if (k <= nm)
375  {
376  in[k] = f;
377  }
378  if ( (k != 0) && (k == 2 * (int) (k / 2) ) )
379  {
380  sk0 += 4.0 * f / k;
381  }
382  bs += 2.0 * f;
383  f0 = f1;
384  f1 = f;
385  }
386  s0 = std::exp (x) / (bs - f);
387  for (k = 0; k <= nm; k++)
388  {
389  in[k] *= s0;
390  }
391  if (x <= 8.0)
392  {
393  kn[0] = - (std::log (0.5 * x) + el) * in[0] + s0 * sk0;
394  kn[1] = (1.0 / x - in[1] * kn[0]) / in[0];
395  }
396  else
397  {
398  a0 = std::sqrt (M_PI_2 / x) * std::exp (-x);
399  if (x >= 200.0)
400  {
401  kz = 6;
402  }
403  else if (x >= 80.0)
404  {
405  kz = 8;
406  }
407  else if (x >= 25.0)
408  {
409  kz = 10;
410  }
411  else
412  {
413  kz = 16;
414  }
415  for (l = 0; l < 2; l++)
416  {
417  bkl = 1.0;
418  vt = 4.0 * l;
419  r = 1.0;
420  for (k = 1; k <= kz; k++)
421  {
422  r *= 0.125 * (vt - std::pow (2.0 * k - 1.0, 2) ) / (k * x);
423  bkl += r;
424  }
425  kn[l] = a0 * bkl;
426  }
427  }
428  g0 = kn[0];
429  g1 = kn[1];
430  for (k = 2; k <= nm; k++)
431  {
432  g = 2.0 * (k - 1.0) * g1 / x + g0;
433  kn[k] = g;
434  g0 = g1;
435  g1 = g;
436  }
437  inp[0] = in[1];
438  knp[0] = -kn[1];
439  for (k = 1; k <= nm; k++)
440  {
441  inp[k] = in[k - 1] - k * in[k] / x;
442  knp[k] = -kn[k - 1] - k * kn[k] / x;
443  }
444  return 0;
445 }
446 
447 // The following program computes the modified Bessel functions
448 // Iv(x) and Kv(x) for arbitrary positive order. For negative
449 // order use:
450 //
451 // I-v(x) = Iv(x) + 2/pi sin(v pi) Kv(x)
452 // K-v(x) = Kv(x)
453 //
454 int bessikv (double v, double x, double& vm, double* iv, double* kv,
455  double* ivp, double* kvp)
456 {
457  double x2, v0, piv, vt, a1, v0p, gap (0), r, bi0, ca, sum;
458  double f (0), f1, f2, ct, cs, wa, gan, ww, w0, v0n;
459  double r1, r2, bk0, bk1, bk2, a2, cb;
460  int n, k, kz, m;
461 
462  if ( (v < 0.0) || (x < 0.0) )
463  {
464  return 1;
465  }
466  x2 = x * x;
467  n = (int) v;
468  v0 = v - n;
469  if (n == 0)
470  {
471  n = 1;
472  }
473  if (x == 0.0)
474  {
475  for (k = 0; k <= n; k++)
476  {
477  iv[k] = 0.0;
478  kv[k] = -1e308;
479  ivp[k] = 0.0;
480  kvp[k] = 1e308;
481  }
482  if (v0 == 0.0)
483  {
484  iv[0] = 1.0;
485  ivp[1] = 0.5;
486  }
487  vm = v;
488  return 0;
489  }
490  piv = M_PI * v0;
491  vt = 4.0 * v0 * v0;
492  if (v0 == 0.0)
493  {
494  a1 = 1.0;
495  }
496  else
497  {
498  v0p = 1.0 + v0;
499  gap = gamma (v0p);
500  a1 = std::pow (0.5 * x, v0) / gap;
501  }
502  if (x >= 50.0)
503  {
504  kz = 8;
505  }
506  else if (x >= 35.0)
507  {
508  kz = 10;
509  }
510  else
511  {
512  kz = 14;
513  }
514  if (x <= 18.0)
515  {
516  bi0 = 1.0;
517  r = 1.0;
518  for (k = 1; k <= 30; k++)
519  {
520  r *= 0.25 * x2 / (k * (k + v0) );
521  bi0 += r;
522  if (std::fabs (r / bi0) < eps)
523  {
524  break;
525  }
526  }
527  bi0 *= a1;
528  }
529  else
530  {
531  ca = std::exp (x) / std::sqrt (2.0 * M_PI * x);
532  sum = 1.0;
533  r = 1.0;
534  for (k = 1; k <= kz; k++)
535  {
536  r *= -0.125 * (vt - std::pow (2.0 * k - 1.0, 2.0) ) / (k * x);
537  sum += r;
538  }
539  bi0 = ca * sum;
540  }
541  m = msta1 (x, 200);
542  if (m < n)
543  {
544  n = m;
545  }
546  else
547  {
548  m = msta2 (x, n, 15);
549  }
550  f2 = 0.0;
551  f1 = 1.0e-100;
552  for (k = m; k >= 0; k--)
553  {
554  f = 2.0 * (v0 + k + 1.0) * f1 / x + f2;
555  if (k <= n)
556  {
557  iv[k] = f;
558  }
559  f2 = f1;
560  f1 = f;
561  }
562  cs = bi0 / f;
563  for (k = 0; k <= n; k++)
564  {
565  iv[k] *= cs;
566  }
567  ivp[0] = v0 * iv[0] / x + iv[1];
568  for (k = 1; k <= n; k++)
569  {
570  ivp[k] = - (k + v0) * iv[k] / x + iv[k - 1];
571  }
572  ww = 0.0;
573  if (x <= 9.0)
574  {
575  if (v0 == 0.0)
576  {
577  ct = -std::log (0.5 * x) - el;
578  cs = 0.0;
579  w0 = 0.0;
580  r = 1.0;
581  for (k = 1; k <= 50; k++)
582  {
583  w0 += 1.0 / k;
584  r *= 0.25 * x2 / (k * k);
585  cs += r * (w0 + ct);
586  wa = std::fabs (cs);
587  if (std::fabs ( (wa - ww) / wa) < eps)
588  {
589  break;
590  }
591  ww = wa;
592  }
593  bk0 = ct + cs;
594  }
595  else
596  {
597  v0n = 1.0 - v0;
598  gan = gamma (v0n);
599  a2 = 1.0 / (gan * std::pow (0.5 * x, v0) );
600  a1 = std::pow (0.5 * x, v0) / gap;
601  sum = a2 - a1;
602  r1 = 1.0;
603  r2 = 1.0;
604  for (k = 1; k <= 120; k++)
605  {
606  r1 *= 0.25 * x2 / (k * (k - v0) );
607  r2 *= 0.25 * x2 / (k * (k + v0) );
608  sum += a2 * r1 - a1 * r2;
609  wa = std::fabs (sum);
610  if (std::fabs ( (wa - ww) / wa) < eps)
611  {
612  break;
613  }
614  ww = wa;
615  }
616  bk0 = M_PI_2 * sum / std::sin (piv);
617  }
618  }
619  else
620  {
621  cb = std::exp (-x) * std::sqrt (M_PI_2 / x);
622  sum = 1.0;
623  r = 1.0;
624  for (k = 1; k <= kz; k++)
625  {
626  r *= 0.125 * (vt - std::pow (2.0 * k - 1.0, 2.0) ) / (k * x);
627  sum += r;
628  }
629  bk0 = cb * sum;
630  }
631  bk1 = (1.0 / x - iv[1] * bk0) / iv[0];
632  kv[0] = bk0;
633  kv[1] = bk1;
634  for (k = 2; k <= n; k++)
635  {
636  bk2 = 2.0 * (v0 + k - 1.0) * bk1 / x + bk0;
637  kv[k] = bk2;
638  bk0 = bk1;
639  bk1 = bk2;
640  }
641  kvp[0] = v0 * kv[0] / x - kv[1];
642  for (k = 1; k <= n; k++)
643  {
644  kvp[k] = - (k + v0) * kv[k] / x - kv[k - 1];
645  }
646  vm = n + v0;
647  return 0;
648 }
649 }
#define eps
Definition: bessel.hpp:14
int msta1(double x, int mp)
Definition: bessjy.cpp:312
int bessik01b(double x, double &i0, double &i1, double &k0, double &k1, double &i0p, double &i1p, double &k0p, double &k1p)
Definition: bessik.cpp:171
int msta2(double x, int n, int mp)
Definition: bessjy.cpp:337
Definition: bessik.cpp:9
int bessikna(int n, double x, int &nm, double *in, double *kn, double *inp, double *knp)
Definition: bessik.cpp:240
#define M_PI
Definition: winmath.h:20
double gamma(double x)
Definition: gamma.cpp:15
int bessiknb(int n, double x, int &nm, double *in, double *kn, double *inp, double *knp)
Definition: bessik.cpp:330
int bessik01a(double x, double &i0, double &i1, double &k0, double &k1, double &i0p, double &i1p, double &k0p, double &k1p)
Definition: bessik.cpp:13
#define el
Definition: bessel.hpp:15
int bessikv(double v, double x, double &vm, double *iv, double *kv, double *ivp, double *kvp)
Definition: bessik.cpp:454