Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/functions/bessel.py
8815 views
1
r"""
2
Bessel Functions
3
4
This module provides symbolic Bessel Functions. These functions use the
5
`mpmath library`_ for numerical evaluation and Maxima, GiNaC, Pynac for
6
symbolics.
7
8
The main objects which are exported from this module are:
9
10
* ``bessel_J`` -- The Bessel J function
11
* ``bessel_Y`` -- The Bessel Y function
12
* ``bessel_I`` -- The Bessel I function
13
* ``bessel_K`` -- The Bessel K function
14
* ``Bessel`` -- A factory function for producing Bessel functions of
15
various kinds and orders
16
17
- Bessel functions, first defined by the Swiss mathematician
18
Daniel Bernoulli and named after Friedrich Bessel, are canonical
19
solutions y(x) of Bessel's differential equation:
20
21
.. math::
22
23
x^2 \frac{d^2 y}{dx^2} + x \frac{dy}{dx} + \left(x^2 - \nu^2\right)y =
24
0,
25
26
for an arbitrary complex number `\nu` (the order).
27
28
- In this module, `J_\nu` denotes the unique solution of Bessel's equation
29
which is non-singular at `x = 0`. This function is known as the Bessel
30
Function of the First Kind. This function also arises as a special case
31
of the hypergeometric function `{}_0F_1`:
32
33
.. math::
34
35
J_\nu(x) = \frac{x^n}{2^\nu \Gamma(\nu + 1)} {}_0F_1(\nu +
36
1, -\frac{x^2}{4}).
37
38
- The second linearly independent solution to Bessel's equation (which is
39
singular at `x=0`) is denoted by `Y_\nu` and is called the Bessel
40
Function of the Second Kind:
41
42
.. math::
43
44
Y_\nu(x) = \frac{ J_\nu(x) \cos(\pi \nu) -
45
J_{-\nu}(x)}{\sin(\pi \nu)}.
46
47
- There are also two commonly used combinations of the Bessel J and Y
48
Functions. The Bessel I Function, or the Modified Bessel Function of the
49
First Kind, is defined by:
50
51
.. math::
52
53
I_\nu(x) = i^{-\nu} J_\nu(ix).
54
55
The Bessel K Function, or the Modified Bessel Function of the Second Kind,
56
is defined by:
57
58
.. math::
59
60
K_\nu(x) = \frac{\pi}{2} \cdot \frac{I_{-\nu}(x) -
61
I_n(x)}{\sin(\pi \nu)}.
62
63
We should note here that the above formulas for Bessel Y and K functions
64
should be understood as limits when `\nu` is an integer.
65
66
- It follows from Bessel's differential equation that the derivative of
67
`J_n(x)` with respect to `x` is:
68
69
.. math::
70
71
\frac{d}{dx} J_n(x) = \frac{1}{x^n} \left(x^n J_{n-1}(x) - n x^{n-1}
72
J_n(z) \right)
73
74
- Another important formulation of the two linearly independent
75
solutions to Bessel's equation are the Hankel functions
76
`H_\nu^{(1)}(x)` and `H_\nu^{(2)}(x)`,
77
defined by:
78
79
.. math::
80
81
H_\nu^{(1)}(x) = J_\nu(x) + i Y_\nu(x)
82
83
.. math::
84
85
H_\nu^{(2)}(x) = J_\nu(x) - i Y_\nu(x)
86
87
where `i` is the imaginary unit (and `J_*` and
88
`Y_*` are the usual J- and Y-Bessel functions). These
89
linear combinations are also known as Bessel functions of the third
90
kind; they are also two linearly independent solutions of Bessel's
91
differential equation. They are named for Hermann Hankel.
92
93
EXAMPLES:
94
95
Evaluate the Bessel J function symbolically and numerically::
96
97
sage: bessel_J(0, x)
98
bessel_J(0, x)
99
sage: bessel_J(0, 0)
100
bessel_J(0, 0)
101
sage: bessel_J(0, x).diff(x)
102
-1/2*bessel_J(1, x) + 1/2*bessel_J(-1, x)
103
104
sage: N(bessel_J(0, 0), digits = 20)
105
1.0000000000000000000
106
sage: find_root(bessel_J(0,x), 0, 5)
107
2.404825557695773
108
109
Plot the Bessel J function::
110
111
sage: f(x) = Bessel(0)(x); f
112
x |--> bessel_J(0, x)
113
sage: plot(f, (x, 1, 10))
114
115
Visualize the Bessel Y function on the complex plane::
116
117
sage: complex_plot(bessel_Y(0, x), (-5, 5), (-5, 5))
118
119
Evaluate a combination of Bessel functions::
120
121
sage: f(x) = bessel_J(1, x) - bessel_Y(0, x)
122
sage: f(pi)
123
bessel_J(1, pi) - bessel_Y(0, pi)
124
sage: f(pi).n()
125
-0.0437509653365599
126
sage: f(pi).n(digits=50)
127
-0.043750965336559909054985168023342675387737118378169
128
129
Symbolically solve a second order differential equation with initial
130
conditions `y(1) = a` and `y'(1) = b` in terms of Bessel functions::
131
132
sage: y = function('y', x)
133
sage: a, b = var('a, b')
134
sage: diffeq = x^2*diff(y,x,x) + x*diff(y,x) + x^2*y == 0
135
sage: f = desolve(diffeq, y, [1, a, b]); f
136
(a*bessel_Y(1, 1) + b*bessel_Y(0, 1))*bessel_J(0, x)/(bessel_J(0,
137
1)*bessel_Y(1, 1) - bessel_J(1, 1)*bessel_Y(0, 1)) -
138
(a*bessel_J(1, 1) + b*bessel_J(0, 1))*bessel_Y(0, x)/(bessel_J(0,
139
1)*bessel_Y(1, 1) - bessel_J(1, 1)*bessel_Y(0, 1))
140
141
142
For more examples, see the docstring for :meth:`Bessel`.
143
144
AUTHORS:
145
146
- Benjamin Jones (2012-12-27): initial version
147
148
- Some of the documentation here has been adapted from David Joyner's
149
original documentation of Sage's special functions module (2006).
150
151
REFERENCES:
152
153
- Abramowitz and Stegun: Handbook of Mathematical Functions,
154
http://www.math.sfu.ca/~cbm/aands/
155
156
- http://en.wikipedia.org/wiki/Bessel_function
157
158
- mpmath Library `Bessel Functions`_
159
160
.. _`mpmath Library`: http://code.google.com/p/mpmath/
161
.. _`Bessel Functions`: http://mpmath.googlecode.com/svn/trunk/doc/build/functions/bessel.html
162
163
"""
164
165
#*****************************************************************************
166
# Copyright (C) 2013 Benjamin Jones <[email protected]>
167
#
168
# Distributed under the terms of the GNU General Public License (GPL)
169
#
170
# This code is distributed in the hope that it will be useful,
171
# but WITHOUT ANY WARRANTY; without even the implied warranty of
172
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
173
# General Public License for more details.
174
#
175
# The full text of the GPL is available at:
176
#
177
# http://www.gnu.org/licenses/
178
#*****************************************************************************
179
180
from sage.functions.other import sqrt
181
from sage.functions.log import exp
182
from sage.functions.hyperbolic import sinh, cosh
183
from sage.libs.mpmath import utils as mpmath_utils
184
from sage.misc.latex import latex
185
from sage.rings.all import RR, Integer
186
from sage.structure.coerce import parent
187
from sage.structure.element import get_coercion_model
188
from sage.symbolic.constants import pi
189
from sage.symbolic.function import BuiltinFunction, is_inexact
190
from sage.symbolic.expression import Expression
191
192
# remove after deprecation period
193
from sage.calculus.calculus import maxima
194
from sage.functions.other import real, imag
195
from sage.misc.sage_eval import sage_eval
196
from sage.rings.real_mpfr import RealField
197
from sage.plot.plot import plot
198
from sage.rings.all import ZZ
199
200
201
class Function_Bessel_J(BuiltinFunction):
202
r"""
203
The Bessel J Function, denoted by bessel_J(`\nu`, x) or `J_\nu(x)`.
204
As a Taylor series about `x=0` it is equal to:
205
206
.. math::
207
208
J_\nu(x) = \sum_{k=0}^\infty \frac{(-1)^k}{k! \Gamma(k+\nu+1)}
209
\left(\frac{x}{2}\right)^{2k+\nu}
210
211
The parameter `\nu` is called the order and may be any real or
212
complex number; however, integer and half-integer values are most
213
common. It is defined for all complex numbers `x` when `\nu`
214
is an integer or greater than zero and it diverges as `x \to 0`
215
for negative non-integer values of `\nu`.
216
217
For integer orders `\nu = n` there is an integral representation:
218
219
.. math::
220
221
J_n(x) = \frac{1}{\pi} \int_0^\pi \cos(n t - x \sin(t)) \; dt
222
223
This function also arises as a special case of the hypergeometric
224
function `{}_0F_1`:
225
226
.. math::
227
228
J_\nu(x) = \frac{x^n}{2^\nu \Gamma(\nu + 1)} {}_0F_1\left(\nu +
229
1, -\frac{x^2}{4}\right).
230
231
EXAMPLES::
232
233
sage: bessel_J(1.0, 1.0)
234
0.440050585744933
235
sage: bessel_J(2, I).n(digits=30)
236
-0.135747669767038281182852569995
237
238
sage: bessel_J(1, x)
239
bessel_J(1, x)
240
sage: n = var('n')
241
sage: bessel_J(n, x)
242
bessel_J(n, x)
243
244
Examples of symbolic manipulation::
245
246
sage: a = bessel_J(pi, bessel_J(1, I)); a
247
bessel_J(pi, bessel_J(1, I))
248
sage: N(a, digits=20)
249
0.00059023706363796717363 - 0.0026098820470081958110*I
250
251
sage: f = bessel_J(2, x)
252
sage: f.diff(x)
253
-1/2*bessel_J(3, x) + 1/2*bessel_J(1, x)
254
255
Comparison to a well-known integral representation of `J_1(1)`::
256
257
sage: A = numerical_integral(1/pi*cos(x - sin(x)), 0, pi)
258
sage: A[0] # abs tol 1e-14
259
0.44005058574493355
260
sage: bessel_J(1.0, 1.0) - A[0] < 1e-15
261
True
262
263
Currently, integration is not supported (directly) since we cannot
264
yet convert hypergeometric functions to and from Maxima::
265
266
sage: f = bessel_J(2, x)
267
sage: f.integrate(x)
268
Traceback (most recent call last):
269
...
270
TypeError: cannot coerce arguments: no canonical coercion from <type 'list'> to Symbolic Ring
271
272
sage: m = maxima(bessel_J(2, x))
273
sage: m.integrate(x)
274
hypergeometric([3/2],[5/2,3],-x^2/4)*x^3/24
275
276
Visualization::
277
278
sage: plot(bessel_J(1,x), (x,0,5), color='blue')
279
sage: complex_plot(bessel_J(1, x), (-5, 5), (-5, 5)) # long time
280
281
ALGORITHM:
282
283
Numerical evaluation is handled by the mpmath library. Symbolics are
284
handled by a combination of Maxima and Sage (Ginac/Pynac).
285
"""
286
def __init__(self):
287
"""
288
See the docstring for :meth:`Function_Bessel_J`.
289
290
EXAMPLES::
291
292
sage: sage.functions.bessel.Function_Bessel_J()
293
bessel_J
294
"""
295
BuiltinFunction.__init__(self, "bessel_J", nargs=2,
296
conversions=dict(mathematica='BesselJ',
297
maxima='bessel_j',
298
sympy='besselj'))
299
300
# remove after deprecation period
301
def __call__(self, *args, **kwds):
302
"""
303
Custom ``__call__`` method which uses the old Bessel function code if
304
the ``algorithm`` or ``prec`` arguments are used. This should be
305
removed after the deprecation period.
306
307
EXAMPLES::
308
309
sage: bessel_J(0, 1.0, "maxima", 53)
310
doctest:1: DeprecationWarning: precision argument is deprecated; algorithm argument is currently deprecated, but will be available as a named keyword in the future
311
See http://trac.sagemath.org/4102 for details.
312
.7651976865579666
313
"""
314
if len(args) > 2 or len(kwds) > 0:
315
from sage.misc.superseded import deprecation
316
deprecation(4102, 'precision argument is deprecated; algorithm '
317
'argument is currently deprecated, but will be '
318
'available as a named keyword in the future')
319
return _bessel_J(*args, **kwds)
320
else:
321
return super(BuiltinFunction, self).__call__(*args, **kwds)
322
323
def _eval_(self, n, x):
324
"""
325
EXAMPLES::
326
327
sage: a, b = var('a, b')
328
sage: bessel_J(a, b)
329
bessel_J(a, b)
330
sage: bessel_J(1.0, 1.0)
331
0.440050585744933
332
"""
333
if (not isinstance(n, Expression) and
334
not isinstance(x, Expression) and
335
(is_inexact(n) or is_inexact(x))):
336
coercion_model = get_coercion_model()
337
n, x = coercion_model.canonical_coercion(n, x)
338
return self._evalf_(n, x, parent(n))
339
340
return None
341
342
def _evalf_(self, n, x, parent=None):
343
"""
344
EXAMPLES::
345
346
sage: bessel_J(0.0, 1.0)
347
0.765197686557966
348
sage: bessel_J(0, 1).n(digits=20)
349
0.76519768655796655145
350
"""
351
import mpmath
352
return mpmath_utils.call(mpmath.besselj, n, x, parent=parent)
353
354
def _derivative_(self, n, x, diff_param):
355
"""
356
Return the derivative of the Bessel J function.
357
358
EXAMPLES::
359
360
sage: f(z) = bessel_J(10, z)
361
sage: derivative(f, z)
362
z |--> -1/2*bessel_J(11, z) + 1/2*bessel_J(9, z)
363
sage: nu = var('nu')
364
sage: bessel_J(nu, z).diff(nu)
365
Traceback (most recent call last):
366
...
367
NotImplementedError: derivative with respect to order
368
369
"""
370
if diff_param == 1:
371
return (bessel_J(n - 1, x) - bessel_J(n + 1, x)) / Integer(2)
372
else:
373
raise NotImplementedError('derivative with respect to order')
374
375
def _print_latex_(self, n, z):
376
"""
377
Custom _print_latex_ method.
378
379
EXAMPLES::
380
381
sage: latex(bessel_J(1, x))
382
\operatorname{J_{1}}(x)
383
"""
384
return r"\operatorname{J_{%s}}(%s)" % (latex(n), latex(z))
385
386
bessel_J = Function_Bessel_J()
387
388
389
class Function_Bessel_Y(BuiltinFunction):
390
r"""
391
The Bessel Y functions, also known as the Bessel functions of the second
392
kind, Weber functions, or Neumann functions.
393
394
`Y_\nu(z)` is a holomorphic function of `z` on the complex plane,
395
cut along the negative real axis. It is singular at `z = 0`. When `z`
396
is fixed, `Y_\nu(z)` is an entire function of the order `\nu`.
397
398
DEFINITION:
399
400
.. math::
401
402
Y_n(z) = \frac{J_\nu(z) \cos(\nu z) -
403
J_{-\nu}(z)}{\sin(\nu z)}
404
405
Its derivative with respect to `z` is:
406
407
.. math::
408
409
\frac{d}{dz} Y_n(z) = \frac{1}{z^n} \left(z^n Y_{n-1}(z) - n z^{n-1}
410
Y_n(z) \right)
411
412
EXAMPLES::
413
414
sage: bessel_Y(1, x)
415
bessel_Y(1, x)
416
sage: bessel_Y(1.0, 1.0)
417
-0.781212821300289
418
sage: n = var('n')
419
sage: bessel_Y(n, x)
420
bessel_Y(n, x)
421
sage: bessel_Y(2, I).n()
422
1.03440456978312 - 0.135747669767038*I
423
sage: bessel_Y(0, 0).n()
424
-infinity
425
426
Examples of symbolic manipulation::
427
428
sage: a = bessel_Y(pi, bessel_Y(1, I)); a
429
bessel_Y(pi, bessel_Y(1, I))
430
sage: N(a, digits=20)
431
4.2059146571791095708 + 21.307914215321993526*I
432
433
sage: f = bessel_Y(2, x)
434
sage: f.diff(x)
435
-1/2*bessel_Y(3, x) + 1/2*bessel_Y(1, x)
436
437
High precision and complex valued inputs (see :trac:`4230`)::
438
439
sage: bessel_Y(0, 1).n(128)
440
0.088256964215676957982926766023515162828
441
sage: bessel_Y(0, RealField(200)(1))
442
0.088256964215676957982926766023515162827817523090675546711044
443
sage: bessel_Y(0, ComplexField(200)(0.5+I))
444
0.077763160184438051408593468823822434235010300228009867784073 + 1.0142336049916069152644677682828326441579314239591288411739*I
445
446
Visualization::
447
448
sage: plot(bessel_Y(1,x), (x,0,5), color='blue')
449
sage: complex_plot(bessel_Y(1, x), (-5, 5), (-5, 5)) # long time
450
451
ALGORITHM:
452
453
Numerical evaluation is handled by the mpmath library. Symbolics are
454
handled by a combination of Maxima and Sage (Ginac/Pynac).
455
"""
456
def __init__(self):
457
"""
458
See the docstring for :meth:`Function_Bessel_Y`.
459
460
EXAMPLES::
461
462
sage: sage.functions.bessel.Function_Bessel_Y()(0, x)
463
bessel_Y(0, x)
464
"""
465
BuiltinFunction.__init__(self, "bessel_Y", nargs=2,
466
conversions=dict(mathematica='BesselY',
467
maxima='bessel_y',
468
sympy='bessely'))
469
470
# remove after deprecation period
471
def __call__(self, *args, **kwds):
472
"""
473
Custom ``__call__`` method which uses the old Bessel function code if
474
the ``algorithm`` or ``prec`` arguments are used. This should be
475
removed after the deprecation period.
476
477
EXAMPLES::
478
479
sage: bessel_Y(0, 1, "maxima", 53)
480
doctest:1: DeprecationWarning: precision argument is deprecated; algorithm argument is currently deprecated, but will be available as a named keyword in the future
481
See http://trac.sagemath.org/4102 for details.
482
0.0882569642156769
483
"""
484
if len(args) > 2 or len(kwds) > 0:
485
from sage.misc.superseded import deprecation
486
deprecation(4102, 'precision argument is deprecated; algorithm '
487
'argument is currently deprecated, but will be '
488
'available as a named keyword in the future')
489
return _bessel_Y(*args, **kwds)
490
else:
491
return super(BuiltinFunction, self).__call__(*args, **kwds)
492
493
def _eval_(self, n, x):
494
"""
495
EXAMPLES::
496
497
sage: a,b = var('a, b')
498
sage: bessel_Y(a, b)
499
bessel_Y(a, b)
500
sage: bessel_Y(0, 1).n(128)
501
0.088256964215676957982926766023515162828
502
"""
503
if (not isinstance(n, Expression) and not isinstance(x, Expression) and
504
(is_inexact(n) or is_inexact(x))):
505
coercion_model = get_coercion_model()
506
n, x = coercion_model.canonical_coercion(n, x)
507
return self._evalf_(n, x, parent(n))
508
509
return None # leaves the expression unevaluated
510
511
def _evalf_(self, n, x, parent=None):
512
"""
513
EXAMPLES::
514
515
sage: bessel_Y(1.0+2*I, 3.0+4*I)
516
0.699410324467538 + 0.228917940896421*I
517
sage: bessel_Y(0, 1).n(256)
518
0.08825696421567695798292676602351516282781752309067554671104384761199978932351
519
"""
520
import mpmath
521
return mpmath_utils.call(mpmath.bessely, n, x, parent=parent)
522
523
def _derivative_(self, n, x, diff_param):
524
"""
525
Return the derivative of the Bessel Y function.
526
527
EXAMPLES::
528
529
sage: f(x) = bessel_Y(10, x)
530
sage: derivative(f, x)
531
x |--> -1/2*bessel_Y(11, x) + 1/2*bessel_Y(9, x)
532
sage: nu = var('nu')
533
sage: bessel_Y(nu, x).diff(nu)
534
Traceback (most recent call last):
535
...
536
NotImplementedError: derivative with respect to order
537
"""
538
if diff_param == 1:
539
return (bessel_Y(n - 1, x) - bessel_Y(n + 1, x)) / Integer(2)
540
else:
541
raise NotImplementedError('derivative with respect to order')
542
543
def _print_latex_(self, n, z):
544
"""
545
Custom _print_latex_ method.
546
547
EXAMPLES::
548
549
sage: latex(bessel_Y(1, x))
550
\operatorname{Y_{1}}(x)
551
"""
552
return r"\operatorname{Y_{%s}}(%s)" % (latex(n), latex(z))
553
554
bessel_Y = Function_Bessel_Y()
555
556
557
class Function_Bessel_I(BuiltinFunction):
558
r"""
559
The Bessel I function, or the Modified Bessel Function of the First Kind.
560
561
DEFINITION:
562
563
.. math::
564
565
I_\nu(x) = i^{-\nu} J_\nu(ix)
566
567
EXAMPLES::
568
569
sage: bessel_I(1, x)
570
bessel_I(1, x)
571
sage: bessel_I(1.0, 1.0)
572
0.565159103992485
573
sage: n = var('n')
574
sage: bessel_I(n, x)
575
bessel_I(n, x)
576
sage: bessel_I(2, I).n()
577
-0.114903484931900
578
579
Examples of symbolic manipulation::
580
581
sage: a = bessel_I(pi, bessel_I(1, I))
582
sage: N(a, digits=20)
583
0.00026073272117205890528 - 0.0011528954889080572266*I
584
585
sage: f = bessel_I(2, x)
586
sage: f.diff(x)
587
1/2*bessel_I(3, x) + 1/2*bessel_I(1, x)
588
589
Special identities that bessel_I satisfies::
590
591
sage: bessel_I(1/2, x)
592
sqrt(2)*sqrt(1/(pi*x))*sinh(x)
593
sage: eq = bessel_I(1/2, x) == bessel_I(0.5, x)
594
sage: eq.test_relation()
595
True
596
sage: bessel_I(-1/2, x)
597
sqrt(2)*sqrt(1/(pi*x))*cosh(x)
598
sage: eq = bessel_I(-1/2, x) == bessel_I(-0.5, x)
599
sage: eq.test_relation()
600
True
601
602
Examples of asymptotic behavior::
603
604
sage: limit(bessel_I(0, x), x=oo)
605
+Infinity
606
sage: limit(bessel_I(0, x), x=0)
607
1
608
609
High precision and complex valued inputs::
610
611
sage: bessel_I(0, 1).n(128)
612
1.2660658777520083355982446252147175376
613
sage: bessel_I(0, RealField(200)(1))
614
1.2660658777520083355982446252147175376076703113549622068081
615
sage: bessel_I(0, ComplexField(200)(0.5+I))
616
0.80644357583493619472428518415019222845373366024179916785502 + 0.22686958987911161141397453401487525043310874687430711021434*I
617
618
Visualization::
619
620
sage: plot(bessel_I(1,x), (x,0,5), color='blue')
621
sage: complex_plot(bessel_I(1, x), (-5, 5), (-5, 5)) # long time
622
623
ALGORITHM:
624
625
Numerical evaluation is handled by the mpmath library. Symbolics are
626
handled by a combination of Maxima and Sage (Ginac/Pynac).
627
"""
628
def __init__(self):
629
"""
630
See the docstring for :meth:`Function_Bessel_I`.
631
632
EXAMPLES::
633
634
sage: bessel_I(1,x)
635
bessel_I(1, x)
636
"""
637
BuiltinFunction.__init__(self, "bessel_I", nargs=2,
638
conversions=dict(mathematica='BesselI',
639
maxima='bessel_i',
640
sympy='besseli'))
641
642
# remove after deprecation period
643
def __call__(self, *args, **kwds):
644
"""
645
Custom ``__call__`` method which uses the old Bessel function code if
646
the ``algorithm`` or ``prec`` arguments are used. This should be
647
removed after the deprecation period.
648
649
EXAMPLES::
650
651
sage: bessel_I(0, 1, "maxima", 53)
652
doctest:1: DeprecationWarning: precision argument is deprecated; algorithm argument is currently deprecated, but will be available as a named keyword in the future
653
See http://trac.sagemath.org/4102 for details.
654
1.266065877752009
655
"""
656
if len(args) > 2 or len(kwds) > 0:
657
from sage.misc.superseded import deprecation
658
deprecation(4102, 'precision argument is deprecated; algorithm '
659
'argument is currently deprecated, but will be '
660
'available as a named keyword in the future')
661
return _bessel_I(*args, **kwds)
662
else:
663
return super(BuiltinFunction, self).__call__(*args, **kwds)
664
665
def _eval_(self, n, x):
666
"""
667
EXAMPLES::
668
669
sage: y=var('y')
670
sage: bessel_I(y,x)
671
bessel_I(y, x)
672
sage: bessel_I(0.0, 1.0)
673
1.26606587775201
674
sage: bessel_I(1/2, 1)
675
sqrt(2)*sinh(1)/sqrt(pi)
676
sage: bessel_I(-1/2, pi)
677
sqrt(2)*cosh(pi)/pi
678
"""
679
if (not isinstance(n, Expression) and not isinstance(x, Expression) and
680
(is_inexact(n) or is_inexact(x))):
681
coercion_model = get_coercion_model()
682
n, x = coercion_model.canonical_coercion(n, x)
683
return self._evalf_(n, x, parent(n))
684
685
# special identities
686
if n == Integer(1) / Integer(2):
687
return sqrt(2 / (pi * x)) * sinh(x)
688
elif n == -Integer(1) / Integer(2):
689
return sqrt(2 / (pi * x)) * cosh(x)
690
691
return None # leaves the expression unevaluated
692
693
def _evalf_(self, n, x, parent=None):
694
"""
695
EXAMPLES::
696
697
sage: bessel_I(1,3).n(digits=20)
698
3.9533702174026093965
699
"""
700
import mpmath
701
return mpmath_utils.call(mpmath.besseli, n, x, parent=parent)
702
703
def _derivative_(self, n, x, diff_param):
704
"""
705
Return the derivative of the Bessel I function `I_n(x)` with respect
706
to `x`.
707
708
EXAMPLES::
709
710
sage: f(z) = bessel_I(10, x)
711
sage: derivative(f, x)
712
z |--> 1/2*bessel_I(11, x) + 1/2*bessel_I(9, x)
713
sage: nu = var('nu')
714
sage: bessel_I(nu, x).diff(nu)
715
Traceback (most recent call last):
716
...
717
NotImplementedError: derivative with respect to order
718
"""
719
if diff_param == 1:
720
return (bessel_I(n - 1, x) + bessel_I(n + 1, x)) / Integer(2)
721
else:
722
raise NotImplementedError('derivative with respect to order')
723
724
def _print_latex_(self, n, z):
725
"""
726
Custom _print_latex_ method.
727
728
EXAMPLES::
729
730
sage: latex(bessel_I(1, x))
731
\operatorname{I_{1}}(x)
732
"""
733
return r"\operatorname{I_{%s}}(%s)" % (latex(n), latex(z))
734
735
bessel_I = Function_Bessel_I()
736
737
738
class Function_Bessel_K(BuiltinFunction):
739
r"""
740
The Bessel K function, or the modified Bessel function of the second kind.
741
742
DEFINITION:
743
744
.. math::
745
746
K_\nu(x) = \frac{\pi}{2} \frac{I_{-\nu}(x)-I_\nu(x)}{\sin(\nu \pi)}
747
748
EXAMPLES::
749
750
sage: bessel_K(1, x)
751
bessel_K(1, x)
752
sage: bessel_K(1.0, 1.0)
753
0.601907230197235
754
sage: n = var('n')
755
sage: bessel_K(n, x)
756
bessel_K(n, x)
757
sage: bessel_K(2, I).n()
758
-2.59288617549120 + 0.180489972066962*I
759
760
Examples of symbolic manipulation::
761
762
sage: a = bessel_K(pi, bessel_K(1, I)); a
763
bessel_K(pi, bessel_K(1, I))
764
sage: N(a, digits=20)
765
3.8507583115005220157 + 0.068528298579883425792*I
766
767
sage: f = bessel_K(2, x)
768
sage: f.diff(x)
769
1/2*bessel_K(3, x) + 1/2*bessel_K(1, x)
770
771
sage: bessel_K(1/2, x)
772
bessel_K(1/2, x)
773
sage: bessel_K(1/2, -1)
774
bessel_K(1/2, -1)
775
sage: bessel_K(1/2, 1)
776
sqrt(1/2)*sqrt(pi)*e^(-1)
777
778
Examples of asymptotic behavior::
779
780
sage: bessel_K(0, 0.0)
781
+infinity
782
sage: limit(bessel_K(0, x), x=0)
783
+Infinity
784
sage: limit(bessel_K(0, x), x=oo)
785
0
786
787
High precision and complex valued inputs::
788
789
sage: bessel_K(0, 1).n(128)
790
0.42102443824070833333562737921260903614
791
sage: bessel_K(0, RealField(200)(1))
792
0.42102443824070833333562737921260903613621974822666047229897
793
sage: bessel_K(0, ComplexField(200)(0.5+I))
794
0.058365979093103864080375311643360048144715516692187818271179 - 0.67645499731334483535184142196073004335768129348518210260256*I
795
796
Visualization::
797
798
sage: plot(bessel_K(1,x), (x,0,5), color='blue')
799
sage: complex_plot(bessel_K(1, x), (-5, 5), (-5, 5)) # long time
800
801
ALGORITHM:
802
803
Numerical evaluation is handled by the mpmath library. Symbolics are
804
handled by a combination of Maxima and Sage (Ginac/Pynac).
805
806
TESTS:
807
808
Verify that :trac:`3426` is fixed:
809
810
The Bessel K function can be evaluated numerically at complex orders::
811
812
sage: bessel_K(10 * I, 10).n()
813
9.82415743819925e-8
814
815
For a fixed imaginary order and increasing, real, second component the
816
value of Bessel K is exponentially decaying::
817
818
sage: for x in [10, 20, 50, 100, 200]: print bessel_K(5*I, x).n()
819
5.27812176514912e-6
820
3.11005908421801e-10
821
2.66182488515423e-23 - 8.59622057747552e-58*I
822
4.11189776828337e-45 - 1.01494840019482e-80*I
823
1.15159692553603e-88 - 6.75787862113718e-125*I
824
"""
825
def __init__(self):
826
"""
827
See the docstring for :meth:`Function_Bessel_K`.
828
829
EXAMPLES::
830
831
sage: sage.functions.bessel.Function_Bessel_K()
832
bessel_K
833
"""
834
BuiltinFunction.__init__(self, "bessel_K", nargs=2,
835
conversions=dict(mathematica='BesselK',
836
maxima='bessel_k',
837
sympy='besselk'))
838
839
# remove after deprecation period
840
def __call__(self, *args, **kwds):
841
"""
842
Custom ``__call__`` method which uses the old Bessel function code if
843
the ``algorithm`` or ``prec`` arguments are used. This should be
844
removed after the deprecation period.
845
846
EXAMPLES::
847
848
sage: bessel_K(0, 1, "maxima", 53)
849
doctest:1: DeprecationWarning: precision argument is deprecated; algorithm argument is currently deprecated, but will be available as a named keyword in the future
850
See http://trac.sagemath.org/4102 for details.
851
0.0882569642156769
852
"""
853
if len(args) > 2 or len(kwds) > 0:
854
from sage.misc.superseded import deprecation
855
deprecation(4102, 'precision argument is deprecated; algorithm '
856
'argument is currently deprecated, but will be '
857
'available as a named keyword in the future')
858
return _bessel_Y(*args, **kwds)
859
else:
860
return super(BuiltinFunction, self).__call__(*args, **kwds)
861
862
def _eval_(self, n, x):
863
"""
864
EXAMPLES::
865
866
sage: bessel_K(1,0)
867
bessel_K(1, 0)
868
sage: bessel_K(1.0, 0.0)
869
+infinity
870
sage: bessel_K(-1, 1).n(128)
871
0.60190723019723457473754000153561733926
872
"""
873
if (not isinstance(n, Expression) and not isinstance(x, Expression) and
874
(is_inexact(n) or is_inexact(x))):
875
coercion_model = get_coercion_model()
876
n, x = coercion_model.canonical_coercion(n, x)
877
return self._evalf_(n, x, parent(n))
878
879
# special identity
880
if n == Integer(1) / Integer(2) and x > 0:
881
return sqrt(pi / 2) * exp(-x) * x ** (-Integer(1) / Integer(2))
882
883
return None # leaves the expression unevaluated
884
885
def _evalf_(self, n, x, parent=None):
886
"""
887
EXAMPLES::
888
889
sage: bessel_K(0.0, 1.0)
890
0.421024438240708
891
sage: bessel_K(0, RealField(128)(1))
892
0.42102443824070833333562737921260903614
893
"""
894
import mpmath
895
return mpmath_utils.call(mpmath.besselk, n, x, parent=parent)
896
897
def _derivative_(self, n, x, diff_param):
898
"""
899
Return the derivative of the Bessel K function.
900
901
EXAMPLES::
902
903
sage: f(x) = bessel_K(10, x)
904
sage: derivative(f, x)
905
x |--> 1/2*bessel_K(11, x) + 1/2*bessel_K(9, x)
906
sage: nu = var('nu')
907
sage: bessel_K(nu, x).diff(nu)
908
Traceback (most recent call last):
909
...
910
NotImplementedError: derivative with respect to order
911
"""
912
if diff_param == 1:
913
return (bessel_K(n - 1, x) + bessel_K(n + 1, x)) / Integer(2)
914
else:
915
raise NotImplementedError('derivative with respect to order')
916
917
def _print_latex_(self, n, z):
918
"""
919
Custom _print_latex_ method.
920
921
EXAMPLES::
922
923
sage: latex(bessel_K(1, x))
924
\operatorname{K_{1}}(x)
925
"""
926
return r"\operatorname{K_{%s}}(%s)" % (latex(n), latex(z))
927
928
bessel_K = Function_Bessel_K()
929
930
931
# dictionary used in Bessel
932
bessel_type_dict = {'I': bessel_I, 'J': bessel_J, 'K': bessel_K, 'Y': bessel_Y}
933
934
935
def Bessel(*args, **kwds):
936
"""
937
A function factory that produces symbolic I, J, K, and Y Bessel functions.
938
There are several ways to call this function:
939
940
- ``Bessel(order, type)``
941
- ``Bessel(order)`` -- type defaults to 'J'
942
- ``Bessel(order, typ=T)``
943
- ``Bessel(typ=T)`` -- order is unspecified, this is a 2-parameter
944
function
945
- ``Bessel()`` -- order is unspecified, type is 'J'
946
947
where ``order`` can be any integer and T must be one of the strings 'I',
948
'J', 'K', or 'Y'.
949
950
See the EXAMPLES below.
951
952
EXAMPLES:
953
954
Construction of Bessel functions with various orders and types::
955
956
sage: Bessel()
957
bessel_J
958
sage: Bessel(1)(x)
959
bessel_J(1, x)
960
sage: Bessel(1, 'Y')(x)
961
bessel_Y(1, x)
962
sage: Bessel(-2, 'Y')(x)
963
bessel_Y(-2, x)
964
sage: Bessel(typ='K')
965
bessel_K
966
sage: Bessel(0, typ='I')(x)
967
bessel_I(0, x)
968
969
Evaluation::
970
971
sage: f = Bessel(1)
972
sage: f(3.0)
973
0.339058958525936
974
sage: f(3)
975
bessel_J(1, 3)
976
sage: f(3).n(digits=50)
977
0.33905895852593645892551459720647889697308041819801
978
979
sage: g = Bessel(typ='J')
980
sage: g(1,3)
981
bessel_J(1, 3)
982
sage: g(2, 3+I).n()
983
0.634160370148554 + 0.0253384000032695*I
984
sage: abs(numerical_integral(1/pi*cos(3*sin(x)), 0.0, pi)[0] - Bessel(0, 'J')(3.0)) < 1e-15
985
True
986
987
Symbolic calculus::
988
989
sage: f(x) = Bessel(0, 'J')(x)
990
sage: derivative(f, x)
991
x |--> -1/2*bessel_J(1, x) + 1/2*bessel_J(-1, x)
992
sage: derivative(f, x, x)
993
x |--> 1/4*bessel_J(2, x) - 1/2*bessel_J(0, x) + 1/4*bessel_J(-2, x)
994
995
Verify that `J_0` satisfies Bessel's differential equation numerically
996
using the ``test_relation()`` method::
997
998
sage: y = bessel_J(0, x)
999
sage: diffeq = x^2*derivative(y,x,x) + x*derivative(y,x) + x^2*y == 0
1000
sage: diffeq.test_relation(proof=False)
1001
True
1002
1003
Conversion to other systems::
1004
1005
sage: x,y = var('x,y')
1006
sage: f = maxima(Bessel(typ='K')(x,y))
1007
sage: f.derivative('x')
1008
%pi*csc(%pi*x)*('diff(bessel_i(-x,y),x,1)-'diff(bessel_i(x,y),x,1))/2-%pi*bessel_k(x,y)*cot(%pi*x)
1009
sage: f.derivative('y')
1010
-(bessel_k(x+1,y)+bessel_k(x-1,y))/2
1011
1012
Compute the particular solution to Bessel's Differential Equation that
1013
satisfies `y(1) = 1` and `y'(1) = 1`, then verify the initial conditions
1014
and plot it::
1015
1016
sage: y = function('y', x)
1017
sage: diffeq = x^2*diff(y,x,x) + x*diff(y,x) + x^2*y == 0
1018
sage: f = desolve(diffeq, y, [1, 1, 1]); f
1019
(bessel_Y(1, 1) + bessel_Y(0, 1))*bessel_J(0, x)/(bessel_J(0,
1020
1)*bessel_Y(1, 1) - bessel_J(1, 1)*bessel_Y(0, 1)) - (bessel_J(1,
1021
1) + bessel_J(0, 1))*bessel_Y(0, x)/(bessel_J(0, 1)*bessel_Y(1, 1)
1022
- bessel_J(1, 1)*bessel_Y(0, 1))
1023
sage: f.subs(x=1).n() # numerical verification
1024
1.00000000000000
1025
sage: fp = f.diff(x)
1026
sage: fp.subs(x=1).n()
1027
1.00000000000000
1028
1029
sage: f.subs(x=1).simplify_full() # symbolic verification
1030
1
1031
sage: fp = f.diff(x)
1032
sage: fp.subs(x=1).simplify_full()
1033
1
1034
1035
sage: plot(f, (x,0,5))
1036
1037
Plotting::
1038
1039
sage: f(x) = Bessel(0)(x); f
1040
x |--> bessel_J(0, x)
1041
sage: plot(f, (x, 1, 10))
1042
1043
sage: plot([ Bessel(i, 'J') for i in range(5) ], 2, 10)
1044
1045
sage: G = Graphics()
1046
sage: G += sum([ plot(Bessel(i), 0, 4*pi, rgbcolor=hue(sin(pi*i/10))) for i in range(5) ])
1047
sage: show(G)
1048
1049
A recreation of Abramowitz and Stegun Figure 9.1::
1050
1051
sage: G = plot(Bessel(0, 'J'), 0, 15, color='black')
1052
sage: G += plot(Bessel(0, 'Y'), 0, 15, color='black')
1053
sage: G += plot(Bessel(1, 'J'), 0, 15, color='black', linestyle='dotted')
1054
sage: G += plot(Bessel(1, 'Y'), 0, 15, color='black', linestyle='dotted')
1055
sage: show(G, ymin=-1, ymax=1)
1056
1057
"""
1058
# Determine the order and type of function from the arguments and keywords.
1059
# These are recored in local variables: _type, _order, _system, _nargs.
1060
_type = None
1061
if len(args) == 0: # no order specified
1062
_order = None
1063
_nargs = 2
1064
elif len(args) == 1: # order is specified
1065
_order = args[0]
1066
_nargs = 1
1067
elif len(args) == 2: # both order and type are positional arguments
1068
_order = args[0]
1069
_type = args[1]
1070
_nargs = 1
1071
else:
1072
from sage.misc.superseded import deprecation
1073
deprecation(4102, 'precision argument is deprecated; algorithm '
1074
'argument is currently deprecated, but will be '
1075
'available as a named keyword in the future')
1076
return _Bessel(*args, **kwds)
1077
1078
# check for type inconsistency
1079
if _type is not None and 'typ' in kwds and _type != kwds['typ']:
1080
raise ValueError("inconsistent types given")
1081
# record the function type
1082
if _type is None:
1083
if 'typ' in kwds:
1084
_type = kwds['typ']
1085
else:
1086
_type = 'J'
1087
if not (_type in ['I', 'J', 'K', 'Y']):
1088
raise ValueError("type must be one of I, J, K, Y")
1089
# record the numerical evaluation system
1090
if 'algorithm' in kwds:
1091
_system = kwds['algorithm']
1092
else:
1093
_system = 'mpmath'
1094
1095
# return the function
1096
_f = bessel_type_dict[_type]
1097
if _nargs == 1:
1098
return lambda x: _f(_order, x)
1099
else:
1100
return _f
1101
1102
####################################################
1103
### to be removed after the deprecation period ###
1104
####################################################
1105
1106
1107
def _bessel_I(nu,z,algorithm = "pari",prec=53):
1108
r"""
1109
Implements the "I-Bessel function", or "modified Bessel function,
1110
1st kind", with index (or "order") nu and argument z.
1111
1112
INPUT:
1113
1114
1115
- ``nu`` - a real (or complex, for pari) number
1116
1117
- ``z`` - a real (positive) algorithm - "pari" or
1118
"maxima" or "scipy" prec - real precision (for PARI only)
1119
1120
1121
DEFINITION::
1122
1123
Maxima:
1124
inf
1125
==== - nu - 2 k nu + 2 k
1126
\ 2 z
1127
> -------------------
1128
/ k! Gamma(nu + k + 1)
1129
====
1130
k = 0
1131
1132
PARI:
1133
1134
inf
1135
==== - 2 k 2 k
1136
\ 2 z Gamma(nu + 1)
1137
> -----------------------
1138
/ k! Gamma(nu + k + 1)
1139
====
1140
k = 0
1141
1142
1143
1144
Sometimes ``bessel_I(nu,z)`` is denoted
1145
``I_nu(z)`` in the literature.
1146
1147
.. warning::
1148
1149
In Maxima (the manual says) i0 is deprecated but
1150
``bessel_i(0,*)`` is broken. (Was fixed in recent CVS patch
1151
though.)
1152
1153
EXAMPLES::
1154
1155
sage: from sage.functions.bessel import _bessel_I
1156
sage: _bessel_I(1,1,"pari",500)
1157
0.565159103992485027207696027609863307328899621621092009480294489479255640964371134092664997766814410064677886055526302676857637684917179812041131208121
1158
sage: _bessel_I(1,1)
1159
0.565159103992485
1160
sage: _bessel_I(2,1.1,"maxima")
1161
0.16708949925104...
1162
sage: _bessel_I(0,1.1,"maxima")
1163
1.32616018371265...
1164
sage: _bessel_I(0,1,"maxima")
1165
1.2660658777520...
1166
sage: _bessel_I(1,1,"scipy")
1167
0.565159103992...
1168
1169
Check whether the return value is real whenever the argument is real (#10251)::
1170
1171
sage: _bessel_I(5, 1.5, algorithm='scipy') in RR
1172
True
1173
1174
"""
1175
if algorithm=="pari":
1176
from sage.libs.pari.all import pari
1177
try:
1178
R = RealField(prec)
1179
nu = R(nu)
1180
z = R(z)
1181
except TypeError:
1182
C = ComplexField(prec)
1183
nu = C(nu)
1184
z = C(z)
1185
K = C
1186
K = z.parent()
1187
return K(pari(nu).besseli(z, precision=prec))
1188
elif algorithm=="scipy":
1189
if prec != 53:
1190
raise ValueError, "for the scipy algorithm the precision must be 53"
1191
import scipy.special
1192
ans = str(scipy.special.iv(float(nu),complex(real(z),imag(z))))
1193
ans = ans.replace("(","")
1194
ans = ans.replace(")","")
1195
ans = ans.replace("j","*I")
1196
ans = sage_eval(ans)
1197
return real(ans) if z in RR else ans # Return real value when arg is real
1198
elif algorithm == "maxima":
1199
if prec != 53:
1200
raise ValueError, "for the maxima algorithm the precision must be 53"
1201
return sage_eval(maxima.eval("bessel_i(%s,%s)"%(float(nu),float(z))))
1202
else:
1203
raise ValueError, "unknown algorithm '%s'"%algorithm
1204
1205
def _bessel_J(nu,z,algorithm="pari",prec=53):
1206
r"""
1207
Return value of the "J-Bessel function", or "Bessel function, 1st
1208
kind", with index (or "order") nu and argument z.
1209
1210
::
1211
1212
Defn:
1213
Maxima:
1214
inf
1215
==== - nu - 2 k nu + 2 k
1216
\ (-1)^k 2 z
1217
> -------------------------
1218
/ k! Gamma(nu + k + 1)
1219
====
1220
k = 0
1221
1222
PARI:
1223
1224
inf
1225
==== - 2k 2k
1226
\ (-1)^k 2 z Gamma(nu + 1)
1227
> ----------------------------
1228
/ k! Gamma(nu + k + 1)
1229
====
1230
k = 0
1231
1232
1233
Sometimes bessel_J(nu,z) is denoted J_nu(z) in the literature.
1234
1235
.. warning::
1236
1237
Inaccurate for small values of z.
1238
1239
EXAMPLES::
1240
1241
sage: from sage.functions.bessel import _bessel_J
1242
sage: _bessel_J(2,1.1)
1243
0.136564153956658
1244
sage: _bessel_J(0,1.1)
1245
0.719622018527511
1246
sage: _bessel_J(0,1)
1247
0.765197686557967
1248
sage: _bessel_J(0,0)
1249
1.00000000000000
1250
sage: _bessel_J(0.1,0.1)
1251
0.777264368097005
1252
1253
We check consistency of PARI and Maxima::
1254
1255
sage: n(_bessel_J(3,10,"maxima"))
1256
0.0583793793051...
1257
sage: n(_bessel_J(3,10,"pari"))
1258
0.0583793793051868
1259
sage: _bessel_J(3,10,"scipy")
1260
0.0583793793052...
1261
1262
Check whether the return value is real whenever the argument is real (#10251)::
1263
sage: _bessel_J(5, 1.5, algorithm='scipy') in RR
1264
True
1265
"""
1266
1267
if algorithm=="pari":
1268
from sage.libs.pari.all import pari
1269
try:
1270
R = RealField(prec)
1271
nu = R(nu)
1272
z = R(z)
1273
except TypeError:
1274
C = ComplexField(prec)
1275
nu = C(nu)
1276
z = C(z)
1277
K = C
1278
if nu == 0:
1279
nu = ZZ(0)
1280
K = z.parent()
1281
return K(pari(nu).besselj(z, precision=prec))
1282
elif algorithm=="scipy":
1283
if prec != 53:
1284
raise ValueError, "for the scipy algorithm the precision must be 53"
1285
import scipy.special
1286
ans = str(scipy.special.jv(float(nu),complex(real(z),imag(z))))
1287
ans = ans.replace("(","")
1288
ans = ans.replace(")","")
1289
ans = ans.replace("j","*I")
1290
ans = sage_eval(ans)
1291
return real(ans) if z in RR else ans
1292
elif algorithm == "maxima":
1293
if prec != 53:
1294
raise ValueError, "for the maxima algorithm the precision must be 53"
1295
f = maxima.function('n,z', 'bessel_j(n, z)')
1296
return f(nu, z)
1297
else:
1298
raise ValueError, "unknown algorithm '%s'"%algorithm
1299
1300
def _bessel_K(nu,z,algorithm="pari",prec=53):
1301
r"""
1302
Implements the "K-Bessel function", or "modified Bessel function,
1303
2nd kind", with index (or "order") nu and argument z. Defn::
1304
1305
pi*(bessel_I(-nu, z) - bessel_I(nu, z))
1306
----------------------------------------
1307
2*sin(pi*nu)
1308
1309
1310
if nu is not an integer and by taking a limit otherwise.
1311
1312
Sometimes bessel_K(nu,z) is denoted K_nu(z) in the literature. In
1313
PARI, nu can be complex and z must be real and positive.
1314
1315
EXAMPLES::
1316
1317
sage: from sage.functions.bessel import _bessel_K
1318
sage: _bessel_K(3,2,"scipy")
1319
0.64738539094...
1320
sage: _bessel_K(3,2)
1321
0.64738539094...
1322
sage: _bessel_K(1,1)
1323
0.60190723019...
1324
sage: _bessel_K(1,1,"pari",10)
1325
0.60
1326
sage: _bessel_K(1,1,"pari",100)
1327
0.60190723019723457473754000154
1328
1329
TESTS::
1330
1331
sage: _bessel_K(2,1.1, algorithm="maxima")
1332
Traceback (most recent call last):
1333
...
1334
NotImplementedError: The K-Bessel function is only implemented for the pari and scipy algorithms
1335
1336
Check whether the return value is real whenever the argument is real (#10251)::
1337
1338
sage: _bessel_K(5, 1.5, algorithm='scipy') in RR
1339
True
1340
1341
"""
1342
if algorithm=="scipy":
1343
if prec != 53:
1344
raise ValueError, "for the scipy algorithm the precision must be 53"
1345
import scipy.special
1346
ans = str(scipy.special.kv(float(nu),float(z)))
1347
ans = ans.replace("(","")
1348
ans = ans.replace(")","")
1349
ans = ans.replace("j","*I")
1350
ans = sage_eval(ans)
1351
return real(ans) if z in RR else ans
1352
elif algorithm == 'pari':
1353
from sage.libs.pari.all import pari
1354
try:
1355
R = RealField(prec)
1356
nu = R(nu)
1357
z = R(z)
1358
except TypeError:
1359
C = ComplexField(prec)
1360
nu = C(nu)
1361
z = C(z)
1362
K = C
1363
K = z.parent()
1364
return K(pari(nu).besselk(z, precision=prec))
1365
elif algorithm == 'maxima':
1366
raise NotImplementedError, "The K-Bessel function is only implemented for the pari and scipy algorithms"
1367
else:
1368
raise ValueError, "unknown algorithm '%s'"%algorithm
1369
1370
1371
def _bessel_Y(nu,z,algorithm="maxima", prec=53):
1372
r"""
1373
Implements the "Y-Bessel function", or "Bessel function of the 2nd
1374
kind", with index (or "order") nu and argument z.
1375
1376
.. note::
1377
1378
Currently only prec=53 is supported.
1379
1380
Defn::
1381
1382
cos(pi n)*bessel_J(nu, z) - bessel_J(-nu, z)
1383
-------------------------------------------------
1384
sin(nu*pi)
1385
1386
if nu is not an integer and by taking a limit otherwise.
1387
1388
Sometimes bessel_Y(n,z) is denoted Y_n(z) in the literature.
1389
1390
This is computed using Maxima by default.
1391
1392
EXAMPLES::
1393
1394
sage: from sage.functions.bessel import _bessel_Y
1395
sage: _bessel_Y(2,1.1,"scipy")
1396
-1.4314714939...
1397
sage: _bessel_Y(2,1.1)
1398
-1.4314714939590...
1399
sage: _bessel_Y(3.001,2.1)
1400
-1.0299574976424...
1401
1402
TESTS::
1403
1404
sage: _bessel_Y(2,1.1, algorithm="pari")
1405
Traceback (most recent call last):
1406
...
1407
NotImplementedError: The Y-Bessel function is only implemented for the maxima and scipy algorithms
1408
"""
1409
if algorithm=="scipy":
1410
if prec != 53:
1411
raise ValueError, "for the scipy algorithm the precision must be 53"
1412
import scipy.special
1413
ans = str(scipy.special.yv(float(nu),complex(real(z),imag(z))))
1414
ans = ans.replace("(","")
1415
ans = ans.replace(")","")
1416
ans = ans.replace("j","*I")
1417
ans = sage_eval(ans)
1418
return real(ans) if z in RR else ans
1419
elif algorithm == "maxima":
1420
if prec != 53:
1421
raise ValueError, "for the maxima algorithm the precision must be 53"
1422
return RR(maxima.eval("bessel_y(%s,%s)"%(float(nu),float(z))))
1423
elif algorithm == "pari":
1424
raise NotImplementedError, "The Y-Bessel function is only implemented for the maxima and scipy algorithms"
1425
else:
1426
raise ValueError, "unknown algorithm '%s'"%algorithm
1427
1428
class _Bessel():
1429
"""
1430
A class implementing the I, J, K, and Y Bessel functions.
1431
1432
EXAMPLES::
1433
1434
sage: from sage.functions.bessel import _Bessel
1435
sage: g = _Bessel(2); g
1436
J_{2}
1437
sage: print g
1438
J-Bessel function of order 2
1439
sage: g.plot(0,10)
1440
1441
::
1442
1443
sage: _Bessel(2, typ='I')(pi)
1444
2.61849485263445
1445
sage: _Bessel(2, typ='J')(pi)
1446
0.485433932631509
1447
sage: _Bessel(2, typ='K')(pi)
1448
0.0510986902537926
1449
sage: _Bessel(2, typ='Y')(pi)
1450
-0.0999007139289404
1451
"""
1452
def __init__(self, nu, typ = "J", algorithm = None, prec = 53):
1453
"""
1454
Initializes new instance of the Bessel class.
1455
1456
INPUT:
1457
1458
- ``typ`` -- (default: J) the type of Bessel function: 'I', 'J', 'K'
1459
or 'Y'.
1460
1461
- ``algorithm`` -- (default: maxima for type Y, pari for other types)
1462
algorithm to use to compute the Bessel function: 'pari', 'maxima' or
1463
'scipy'. Note that type K is not implemented in Maxima and type Y
1464
is not implemented in PARI.
1465
1466
- ``prec`` -- (default: 53) precision in bits of the Bessel function.
1467
Only supported for the PARI algorithm.
1468
1469
EXAMPLES::
1470
1471
sage: from sage.functions.bessel import _Bessel
1472
sage: g = _Bessel(2); g
1473
J_{2}
1474
sage: _Bessel(1,'I')
1475
I_{1}
1476
sage: _Bessel(6, prec=120)(pi)
1477
0.014545966982505560573660369604001804
1478
sage: _Bessel(6, algorithm="pari")(pi)
1479
0.0145459669825056
1480
1481
For the Bessel J-function, Maxima returns a symbolic result. For
1482
types I and Y, we always get a numeric result::
1483
1484
sage: b = _Bessel(6, algorithm="maxima")(pi); b
1485
bessel_j(6,pi)
1486
sage: b.n(53)
1487
0.0145459669825056
1488
sage: _Bessel(6, typ='I', algorithm="maxima")(pi)
1489
0.0294619840059568
1490
sage: _Bessel(6, typ='Y', algorithm="maxima")(pi)
1491
-4.33932818939038
1492
1493
SciPy usually gives less precise results::
1494
1495
sage: _Bessel(6, algorithm="scipy")(pi)
1496
0.0145459669825000...
1497
1498
TESTS::
1499
1500
sage: _Bessel(1,'Z')
1501
Traceback (most recent call last):
1502
...
1503
ValueError: typ must be one of I, J, K, Y
1504
"""
1505
if not (typ in ['I', 'J', 'K', 'Y']):
1506
raise ValueError, "typ must be one of I, J, K, Y"
1507
1508
# Did the user ask for the default algorithm?
1509
if algorithm is None:
1510
if typ == 'Y':
1511
algorithm = 'maxima'
1512
else:
1513
algorithm = 'pari'
1514
1515
self._system = algorithm
1516
self._order = nu
1517
self._type = typ
1518
prec = int(prec)
1519
if prec < 0:
1520
raise ValueError, "prec must be a positive integer"
1521
self._prec = int(prec)
1522
1523
def __str__(self):
1524
"""
1525
Returns a string representation of this Bessel object.
1526
1527
TEST::
1528
1529
sage: from sage.functions.bessel import _Bessel
1530
sage: a = _Bessel(1,'I')
1531
sage: str(a)
1532
'I-Bessel function of order 1'
1533
"""
1534
return self.type()+"-Bessel function of order "+str(self.order())
1535
1536
def __repr__(self):
1537
"""
1538
Returns a string representation of this Bessel object.
1539
1540
TESTS::
1541
1542
sage: from sage.functions.bessel import _Bessel
1543
sage: _Bessel(1,'I')
1544
I_{1}
1545
"""
1546
return self.type()+"_{"+str(self.order())+"}"
1547
1548
def type(self):
1549
"""
1550
Returns the type of this Bessel object.
1551
1552
TEST::
1553
1554
sage: from sage.functions.bessel import _Bessel
1555
sage: a = _Bessel(3,'K')
1556
sage: a.type()
1557
'K'
1558
"""
1559
return self._type
1560
1561
def prec(self):
1562
"""
1563
Returns the precision (in number of bits) used to represent this
1564
Bessel function.
1565
1566
TESTS::
1567
1568
sage: from sage.functions.bessel import _Bessel
1569
sage: a = _Bessel(3,'K')
1570
sage: a.prec()
1571
53
1572
sage: B = _Bessel(20,prec=100); B
1573
J_{20}
1574
sage: B.prec()
1575
100
1576
"""
1577
return self._prec
1578
1579
def order(self):
1580
"""
1581
Returns the order of this Bessel function.
1582
1583
TEST::
1584
1585
sage: from sage.functions.bessel import _Bessel
1586
sage: a = _Bessel(3,'K')
1587
sage: a.order()
1588
3
1589
"""
1590
return self._order
1591
1592
def system(self):
1593
"""
1594
Returns the package used, e.g. Maxima, PARI, or SciPy, to compute with
1595
this Bessel function.
1596
1597
TESTS::
1598
1599
sage: from sage.functions.bessel import _Bessel
1600
sage: _Bessel(20,algorithm='maxima').system()
1601
'maxima'
1602
sage: _Bessel(20,prec=100).system()
1603
'pari'
1604
"""
1605
return self._system
1606
1607
def __call__(self,z):
1608
"""
1609
Implements evaluation of all the Bessel functions directly
1610
from the Bessel class. This essentially allows a Bessel object to
1611
behave like a function that can be invoked.
1612
1613
TESTS::
1614
1615
sage: from sage.functions.bessel import _Bessel
1616
sage: _Bessel(3,'K')(5.0)
1617
0.00829176841523093
1618
sage: _Bessel(20,algorithm='maxima')(5.0)
1619
27.703300521289436e-12
1620
sage: _Bessel(20,prec=100)(5.0101010101010101)
1621
2.8809188227195382093062257967e-11
1622
sage: B = _Bessel(2,'Y',algorithm='scipy',prec=50)
1623
sage: B(2.0)
1624
Traceback (most recent call last):
1625
...
1626
ValueError: for the scipy algorithm the precision must be 53
1627
"""
1628
nu = self.order()
1629
t = self.type()
1630
s = self.system()
1631
p = self.prec()
1632
if t == "I":
1633
return _bessel_I(nu,z,algorithm=s,prec=p)
1634
if t == "J":
1635
return _bessel_J(nu,z,algorithm=s,prec=p)
1636
if t == "K":
1637
return _bessel_K(nu,z,algorithm=s,prec=p)
1638
if t == "Y":
1639
return _bessel_Y(nu,z,algorithm=s,prec=p)
1640
1641
def plot(self,a,b):
1642
"""
1643
Enables easy plotting of all the Bessel functions directly
1644
from the Bessel class.
1645
1646
TESTS::
1647
1648
sage: from sage.functions.bessel import _Bessel
1649
sage: plot(_Bessel(2),3,4)
1650
sage: _Bessel(2).plot(3,4)
1651
sage: P = _Bessel(2,'I').plot(1,5)
1652
sage: P += _Bessel(2,'J').plot(1,5)
1653
sage: P += _Bessel(2,'K').plot(1,5)
1654
sage: P += _Bessel(2,'Y').plot(1,5)
1655
sage: show(P)
1656
"""
1657
nu = self.order()
1658
s = self.system()
1659
t = self.type()
1660
if t == "I":
1661
f = lambda z: _bessel_I(nu,z,s)
1662
P = plot(f,a,b)
1663
if t == "J":
1664
f = lambda z: _bessel_J(nu,z,s)
1665
P = plot(f,a,b)
1666
if t == "K":
1667
f = lambda z: _bessel_K(nu,z,s)
1668
P = plot(f,a,b)
1669
if t == "Y":
1670
f = lambda z: _bessel_Y(nu,z,s)
1671
P = plot(f,a,b)
1672
return P
1673
1674