This module implements the 12 Jacobi elliptic functions, along with their inverses and the Jacobi amplitude function.
Jacobi elliptic functions can be thought of as generalizations of both ordinary and hyperbolic trig functions. There are twelve Jacobian elliptic functions. Each of the twelve corresponds to an arrow drawn from one corner of a rectangle to another.
n ------------------- d
| |
| |
| |
s ------------------- c
Each of the corners of the rectangle are labeled, by convention, s, c, d, and n. The rectangle is understood to be lying on the complex plane, so that s is at the origin, c is on the real axis, and n is on the imaginary axis. The twelve Jacobian elliptic functions are then \(\operatorname{pq}(x)\), where p and q are one of the letters s, c, d, n.
The Jacobian elliptic functions are then the unique doubly-periodic, meromorphic functions satisfying the following three properties:
We can write
where p, q, and r are any of the letters s, c, d, n, with the understanding that \(\mathrm{ss} = \mathrm{cc} = \mathrm{dd} = \mathrm{nn} = 1\).
Let
then the Jacobi elliptic function \(\operatorname{sn}(u)\) is given by
and \(\operatorname{cn}(u)\) is given by
and
To emphasize the dependence on \(m\), one can write \(\operatorname{sn}(u|m)\) for example (and similarly for \(\mathrm{cn}\) and \(\mathrm{dn}\)). This is the notation used below.
For a given \(k\) with \(0 < k < 1\) they therefore are solutions to the following nonlinear ordinary differential equations:
\(\operatorname{sn}\,(x;k)\) solves the differential equations
\(\operatorname{cn}(x;k)\) solves the differential equations
\(\operatorname{dn}(x;k)\) solves the differential equations
If \(K(m)\) denotes the complete elliptic integral of the first kind (named elliptic_kc in Sage), the elliptic functions \(\operatorname{sn}(x|m)\) and \(\operatorname{cn}(x|m)\) have real periods \(4K(m)\), whereas \(\operatorname{dn}(x|m)\) has a period \(2K(m)\). The limit \(m \rightarrow 0\) gives \(K(0) = \pi/2\) and trigonometric functions: \(\operatorname{sn}(x|0) = \sin{x}\), \(\operatorname{cn}(x|0) = \cos{x}\), \(\operatorname{dn}(x|0) = 1\). The limit \(m \rightarrow 1\) gives \(K(1) \rightarrow \infty\) and hyperbolic functions: \(\operatorname{sn}(x|1) = \tanh{x}\), \(\operatorname{cn}(x|1) = \operatorname{sech}{x}\), \(\operatorname{dn}(x|1) = \operatorname{sech}{x}\).
REFERENCES:
| [KhaSuk04] | A. Khare and U. Sukhatme. “Cyclic Identities Involving Jacobi Elliptic Functions”. Arxiv math-ph/0201004 |
AUTHORS:
Bases: sage.symbolic.function.BuiltinFunction
Base class for the inverse Jacobi elliptic functions.
Bases: sage.symbolic.function.BuiltinFunction
Base class for the Jacobi elliptic functions.
Bases: sage.symbolic.function.BuiltinFunction
The Jacobi amplitude function \(\operatorname{am}(x|m) = \int_0^x \operatorname{dn}(t|m) dt\) for \(-K(m) \leq x \leq K(m)\), \(F(\operatorname{am}(x|m)|m) = x\).
The inverses of the 12 Jacobi elliptic functions. They have the property that
INPUT:
EXAMPLES:
sage: jacobi('dn', inverse_jacobi('dn', 3, 0.4), 0.4)
3.00000000000000
sage: inverse_jacobi('dn', 10, 1/10).n(digits=50)
2.4777736267904273296523691232988240759001423661683*I
sage: inverse_jacobi_dn(x, 1)
arcsech(x)
sage: inverse_jacobi_dn(1, 3)
0
sage: m = var('m')
sage: z = inverse_jacobi_dn(x, m).series(x, 4).subs(x=0.1, m=0.7)
sage: jacobi_dn(z, 0.7)
0.0999892750039819...
sage: inverse_jacobi_nd(x, 1)
arccosh(x)
sage: inverse_jacobi_nd(1, 2)
0
sage: inverse_jacobi_ns(10^-5, 3).n()
5.77350269202456e-6 + 1.17142008414677*I
sage: jacobi('sn', 1/2, 1/2)
jacobi_sn(1/2, 1/2)
sage: jacobi('sn', 1/2, 1/2).n()
0.470750473655657
sage: inverse_jacobi('sn', 0.47, 1/2)
0.499098231322220
sage: inverse_jacobi('sn', 0.4707504, 0.5)
0.499999911466555
sage: P = plot(inverse_jacobi('sn', x, 0.5), 0, 1)
Internal function for numerical evaluation of a continous complex branch of each inverse Jacobi function, as described in [Tee97]. Only accepts real arguments.
REFERENCES:
| [Tee97] | Tee, Garry J. “Continuous branches of inverses of the 12 Jacobi elliptic functions for real argument”. 1997. https://researchspace.auckland.ac.nz/bitstream/handle/2292/5042/390.pdf. |
TESTS:
sage: from mpmath import ellipfun, chop
sage: from sage.functions.jacobi import inverse_jacobi_f
sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0.6, 0), 0))
mpf('0.59999999999999998')
sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0.6, 1), 1))
mpf('0.59999999999999998')
sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0, -3), -3))
mpf('0.0')
sage: chop(ellipfun('sn', inverse_jacobi_f('sn', -1, 4), 4))
mpf('-1.0')
sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0.3, 4), 4))
mpf('0.29999999999999999')
sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0.8, 4), 4))
mpf('0.80000000000000004')
sage: chop(ellipfun('ns', inverse_jacobi_f('ns', 0.8, 0), 0))
mpf('0.80000000000000004')
sage: chop(ellipfun('ns', inverse_jacobi_f('ns', -0.7, 1), 1))
mpf('-0.69999999999999996')
sage: chop(ellipfun('ns', inverse_jacobi_f('ns', 0.01, 2), 2))
mpf('0.01')
sage: chop(ellipfun('ns', inverse_jacobi_f('ns', 0, 2), 2))
mpf('0.0')
sage: chop(ellipfun('ns', inverse_jacobi_f('ns', -10, 6), 6))
mpf('-10.0')
sage: chop(ellipfun('cn', inverse_jacobi_f('cn', -10, 0), 0))
mpf('-9.9999999999999982')
sage: chop(ellipfun('cn', inverse_jacobi_f('cn', 50, 1), 1))
mpf('50.000000000000071')
sage: chop(ellipfun('cn', inverse_jacobi_f('cn', 1, 5), 5))
mpf('1.0')
sage: chop(ellipfun('cn', inverse_jacobi_f('cn', 0.5, -5), -5))
mpf('0.5')
sage: chop(ellipfun('cn', inverse_jacobi_f('cn', -0.75, -15), -15))
mpf('-0.75000000000000022')
sage: chop(ellipfun('cn', inverse_jacobi_f('cn', 10, 0.8), 0.8))
mpf('9.9999999999999982')
sage: chop(ellipfun('cn', inverse_jacobi_f('cn', -2, 0.9), 0.9))
mpf('-2.0')
sage: chop(ellipfun('nc', inverse_jacobi_f('nc', -4, 0), 0))
mpf('-3.9999999999999987')
sage: chop(ellipfun('nc', inverse_jacobi_f('nc', 7, 1), 1))
mpf('7.0000000000000009')
sage: chop(ellipfun('nc', inverse_jacobi_f('nc', 7, 3), 3))
mpf('7.0')
sage: chop(ellipfun('nc', inverse_jacobi_f('nc', 0, 2), 2))
mpf('0.0')
sage: chop(ellipfun('nc', inverse_jacobi_f('nc', -18, -4), -4))
mpf('-17.999999999999925')
sage: chop(ellipfun('dn', inverse_jacobi_f('dn', -0.3, 1), 1))
mpf('-0.29999999999999999')
sage: chop(ellipfun('dn', inverse_jacobi_f('dn', 1, -1), -1))
mpf('1.0')
sage: chop(ellipfun('dn', inverse_jacobi_f('dn', 0.8, 0.5), 0.5))
mpf('0.80000000000000004')
sage: chop(ellipfun('dn', inverse_jacobi_f('dn', 5, -4), -4))
mpf('5.0')
sage: chop(ellipfun('dn', inverse_jacobi_f('dn', 0.4, 0.5), 0.5))
mpf('0.40000000000000002')
sage: chop(ellipfun('dn', inverse_jacobi_f('dn', -0.4, 0.5), 0.5))
mpf('-0.40000000000000002')
sage: chop(ellipfun('dn', inverse_jacobi_f('dn', -0.9, 0.5), 0.5))
mpf('-0.90000000000000002')
sage: chop(ellipfun('dn', inverse_jacobi_f('dn', -1.9, 0.2), 0.2))
mpf('-1.8999999999999999')
sage: chop(ellipfun('nd', inverse_jacobi_f('nd', -1.9, 1), 1))
mpf('-1.8999999999999999')
sage: chop(ellipfun('nd', inverse_jacobi_f('nd', 1, -1), -1))
mpf('1.0')
sage: chop(ellipfun('nd', inverse_jacobi_f('nd', 11, -6), -6))
mpf('11.0')
sage: chop(ellipfun('nd', inverse_jacobi_f('nd', 0, 8), 8))
mpf('0.0')
sage: chop(ellipfun('nd', inverse_jacobi_f('nd', -3, 0.8), 0.8))
mpf('-2.9999999999999996')
sage: chop(ellipfun('sc', inverse_jacobi_f('sc', -3, 0), 0))
mpf('-3.0')
sage: chop(ellipfun('sc', inverse_jacobi_f('sc', 2, 1), 1))
mpf('2.0')
sage: chop(ellipfun('sc', inverse_jacobi_f('sc', 0, 9), 9))
mpf('0.0')
sage: chop(ellipfun('sc', inverse_jacobi_f('sc', -7, 3), 3))
mpf('-7.0')
sage: chop(ellipfun('cs', inverse_jacobi_f('cs', -7, 0), 0))
mpf('-6.9999999999999991')
sage: chop(ellipfun('cs', inverse_jacobi_f('cs', 8, 1), 1))
mpf('8.0')
sage: chop(ellipfun('cs', inverse_jacobi_f('cs', 2, 6), 6))
mpf('2.0')
sage: chop(ellipfun('cs', inverse_jacobi_f('cs', 0, 4), 4))
mpf('0.0')
sage: chop(ellipfun('cs', inverse_jacobi_f('cs', -6, 8), 8))
mpf('-6.0000000000000018')
sage: chop(ellipfun('cd', inverse_jacobi_f('cd', -6, 0), 0))
mpf('-6.0000000000000009')
sage: chop(ellipfun('cd', inverse_jacobi_f('cd', 1, 3), 3))
mpf('1.0')
sage: chop(ellipfun('cd', inverse_jacobi_f('cd', 6, 8), 8))
mpf('6.0000000000000027')
sage: chop(ellipfun('dc', inverse_jacobi_f('dc', 5, 0), 0))
mpf('5.0000000000000018')
sage: chop(ellipfun('dc', inverse_jacobi_f('dc', -4, 2), 2))
mpf('-4.0000000000000018')
sage: chop(ellipfun('sd', inverse_jacobi_f('sd', -4, 0), 0))
mpf('-3.9999999999999991')
sage: chop(ellipfun('sd', inverse_jacobi_f('sd', 7, 1), 1))
mpf('7.0')
sage: chop(ellipfun('sd', inverse_jacobi_f('sd', 0, 9), 9))
mpf('0.0')
sage: chop(ellipfun('sd', inverse_jacobi_f('sd', 8, 0.8), 0.8))
mpf('7.9999999999999991')
sage: chop(ellipfun('ds', inverse_jacobi_f('ds', 4, 0.25), 0.25))
mpf('4.0')
The 12 Jacobi elliptic functions.
INPUT:
EXAMPLES:
sage: jacobi('sn', 1, 1)
tanh(1)
sage: jacobi('cd', 1, 1/2)
jacobi_cd(1, 1/2)
sage: RDF(jacobi('cd', 1, 1/2))
0.7240097216593705
sage: (RDF(jacobi('cn', 1, 1/2)), RDF(jacobi('dn', 1, 1/2)),
....: RDF(jacobi('cn', 1, 1/2) / jacobi('dn', 1, 1/2)))
(0.5959765676721407, 0.8231610016315962, 0.7240097216593705)
sage: jsn = jacobi('sn', x, 1)
sage: P = plot(jsn, 0, 1)
Internal function for numeric evaluation of the Jacobi amplitude function for real arguments. Procedure described in [Ehrhardt13].
REFERENCES:
| [Ehrhardt13] | Ehrhardt, Wolfgang. “The AMath and DAMath Special Functions: Reference Manual and Implementation Notes, Version 1.3”. 2013. http://www.wolfgang-ehrhardt.de/specialfunctions.pdf. |
TESTS:
sage: from mpmath import ellipf
sage: from sage.functions.jacobi import jacobi_am_f
sage: ellipf(jacobi_am_f(0.5, 1), 1)
mpf('0.5')
sage: ellipf(jacobi_am(3, 0.3), 0.3)
mpf('3.0')
sage: ellipf(jacobi_am_f(2, -0.5), -0.5)
mpf('2.0')
sage: jacobi_am_f(2, -0.5)
mpf('2.2680930777934176')
sage: jacobi_am_f(-2, -0.5)
mpf('-2.2680930777934176')
sage: jacobi_am_f(-3, 2)
mpf('0.36067407399586108')