Mathematical tools
All examples use ordinary numeric arguments. Add precision=:quad for quad precision.
Expansion coefficients and connection factors
d = dmn(1, 2, 1.25) # angular expansion coefficients
K = kmn(1, 2, 1.25) # joining factor
A = amn(1, 2, 1.25) # radial factor, also accepts negative orderdmn returns degrees, coefficients, the coefficient derivatives, and convergence metadata. The coefficients expand smn in the Ferrers basis:
\[S_{mn}(c,\eta)=\sum_l d_l\,\mathsf P_l^m(\eta).\]
The basis includes the Condon-Shortley phase. normalize matches smn. In DLMF 30.8.1, $d_l=(-1)^k a_{n,k}^m$ for $l=n+2k$.
amn returns $A_n^m(\sigma c^2)$ from DLMF 30.11.4, accepting $-n\le m\le n$. Here $\sigma=1$ for prolate and $\sigma=-1$ for oblate. It uses Meixner-Schäfke normalization. Positive order includes the finite coefficient extension below degree $m$.
kmn supplies the exterior angular-radial connection DLMF 30.11.8:
\[S_n^{m(1)}(z,\gamma)=K_n^m(\gamma)\,\mathrm{Ps}_n^m(z,\gamma^2).\]
Use $\gamma=c$, $z=x$ for prolate and $\gamma=ic$, $z=-ix$ for oblate. The exterior Legendre branch uses $[z\sqrt{1-z^{-2}}]^m$ without the Ferrers phase. Oblate joining factors are complex. normalize=true gives the factor for a unit-normalized angular expansion.
All three support real or complex parameters, both geometries and precisions. By default at c=0, amn is one and kmn is zero except for $(m,n)=(0,0)$, where it is one. Radial calls at c=0 require normalization=:static. rtol and max_terms control coefficient convergence, not relative accuracy of every small coefficient.
Eigenvalue operators
eigenvalue(m, n, c; operator=:separation) selects:
operator | Result | form |
|---|---|---|
:separation (default) | Separation constant λₘₙ(c) | :value |
:concentration | Concentration eigenvalue Λₙ(c) | :value, :log, :complement |
:fourier | Finite Fourier eigenvalue μₙ(c) | :value |
Separation constant
The angular and radial equations share λₘₙ(c), with λₘₙ(0) = n(n+1). Both geometries and real or complex parameters are supported.
eigenvalue(1, 2, 1.25; precision=:quad)
eigenvalue(1, 2, 1.25; spheroid=:oblate, precision=:quad)Concentration and finite Fourier eigenvalues
For the first-kind angular mode Sₙ = S₀ₙ on [-1,1]:
\[\int_{-1}^{1}\frac{\sin(c(x-t))}{\pi(x-t)}S_n(t)\,dt =\Lambda_n(c)S_n(x), \qquad \int_{-1}^{1}e^{-icxt}S_n(t)\,dt=\mu_n(c)S_n(x).\]
The sinc kernel is c/π at x=t. For c>0,
\[0<\Lambda_n<1,\qquad \mu_n=(-i)^n\sqrt{\frac{2\pi\Lambda_n}{c}}.\]
These conventions follow DLMF 30.15 with the interval scaled to [-1,1].
eigenvalue(0, 2, 1.0; operator=:concentration, precision=:quad)
eigenvalue(0, 2, 1.0; operator=:fourier, precision=:quad)
eigenvalue(0, 0, 50.0; operator=:concentration,
form=:complement, precision=:quad)Requires m=0, n≥0, spheroid=:prolate, and finite real c≥0. At c=0, all Λₙ=0; μ₀=2 and μₙ=0 for n>0.
form=:log returns log(Λₙ); form=:complement returns 1-Λₙ. Use these directly when Λₙ rounds to zero or one. At c=0, they return -Inf and 1, respectively.
Parameter derivatives
The Jacobians differentiate with respect to c; coordinate derivatives are returned by smn and rmn.
| Call | Result for real c |
|---|---|
jacobian_eigen(m,n,c) | dλ/dc |
jacobian_smn(m,n,c,eta) | dvalue_dc = ∂S/∂c, dderivative_dc = ∂²S/(∂c∂η) |
jacobian_rmn(m,n,c,x) | dvalue_dc = ∂R/∂c, dderivative_dc = ∂²R/(∂c∂x) |
jacobian_smn(1, 2, 1.25, [0.3]; kind=2, precision=:quad)
jacobian_rmn(1, 2, 1.25, [2.0]; kind=2, precision=:quad)
jacobian_eigen(0, 2, 1.0; operator=:concentration, precision=:quad)
jacobian_eigen(0, 2, 1.0; operator=:fourier, precision=:quad)
jacobian_smn(1, 2, 1.25, [0.3]; order=2, diagnostics=true)order=2 selects second parameter derivatives. Wave results use d2value_dc2 and d2derivative_dc2. Complex results use suffixes dcreal2, dcreal_dcimag, and dcimag2. These calculations difference analytic first derivatives with fourth-order stencils. h controls the step and diagnostics=true adds shared step-refinement diagnostics. Standard radial and positive-bandwidth integral stencils require 2h<abs(c).
jacobian_eigen accepts the same operators and forms as eigenvalue. For a real mode ψₙ with unit norm on [-1,1] and c>0:
\[\frac{d\Lambda_n}{dc}=\frac{|\mu_n|^2}{\pi}\psi_n(1)^2, \qquad \frac{d\log\Lambda_n}{dc}=\frac{2\psi_n(1)^2}{c}, \qquad \frac{d(1-\Lambda_n)}{dc}=-\frac{d\Lambda_n}{dc}.\]
For order 1 and complex c=a+ib, results contain real- and imaginary-direction partials (d_dcreal/d_dcimag for eigenvalues; dvalue_dcreal/dvalue_dcimag and dderivative_dcreal/dderivative_dcimag for functions). On a local analytic branch, ∂f/∂b = i ∂f/∂a.
First derivatives use analytic differentiation unless h is supplied. diagnostics=true adds convergence diagnostics, not error bounds. Angular kind=2 parameter derivatives return NaN at η=±1. Radial calls at c=0 require normalization=:static.
First derivatives are Λ₀′=2/π and μ₁′=-2im/3, otherwise zero. Second derivatives are μ₀″=-2/9 and μ₂″=-8/45, otherwise zero. form=:log returns Inf for order 1 and -Inf for order 2. Logarithmic derivatives at zero require h=nothing.
Inverse bandwidth
find_c_for_eigenvalue solves for real c within a supplied bracket:
\[\lambda_{mn}(c)=\lambda_{\mathrm{target}} \quad\text{or}\quad \Lambda_n(c)=\Lambda_{\mathrm{target}}.\]
target = eigenvalue(1, 2, 1.25; precision=:quad)
root = find_c_for_eigenvalue(1, 2, target;
bracket=(0.5, 2.0), precision=:quad)
root = find_c_for_eigenvalue(0, 0, 0.999;
operator=:concentration, bracket=(0.0, 10.0), precision=:quad)
root.c
root.converged
root.residualbracket=(c_lo,c_hi) is required: finite endpoints with c_lo<c_hi whose eigenvalues enclose the target. Concentration inversion also requires c_lo>=0. An endpoint matching within tolerance is returned immediately. maxiter=160 limits iterations; use_jacobian=true permits Newton steps. With false, separation inversion uses secant/bisection and concentration uses bisection.
| Result field | Meaning |
|---|---|
c | Estimated bandwidth |
converged | Whether the stopping criteria were met |
residual | Computed eigenvalue minus target, in the requested form |
iterations | Iterations performed, not evaluation count; zero for an endpoint match |
bracket | Remaining search interval at termination |
method | Final step: :newton, :secant, or :bisection; :endpoint for an endpoint match; :maxiter when the iteration limit is reached |
For concentration, form defines the target:
| Form | Target | Allowed range |
|---|---|---|
:value | Λₙ | [0,1) |
:complement | 1-Λₙ | (0,1] |
:log | log(Λₙ) | [-Inf,0) |
Check root.converged before using root.c; root.residual uses the requested form. Unit concentration has no finite bandwidth. Zero concentration requires a bracket containing zero. Fourier inversion is unsupported. Set atol and rtol explicitly for tighter separation-constant inversion.
See find_c_for_eigenvalue for tolerance defaults and stopping criteria.
Eigenvalue sweeps
sweep = eigenvalue_sweep(1, 2, [0.5, 1.0, 1.5]; precision=:quad)
sweep.lambda
path = ComplexF64[2, 2+3im, 3im, 0, 2]
continued = eigenvalue_sweep(0, 0, path; precision=:quad)
continued.selected_nSweeps track separation constants only. Real grids must be monotone; complex grids specify an ordered piecewise-linear path. selected_n records degree labels and switched_branch flags label changes. branch_lock=false evaluates the native label independently at each point.
| Keyword | Effect |
|---|---|
branch_lock=true | Continue by choosing among nearby degree labels; false keeps the original label |
branch_window=1 | Search half-width around the previously selected degree k; real grids search max(m,k-w):k+w, complex paths search same-parity neighbors k-2w, …, k+2w, clipped below at the lowest valid degree of that parity |
use_jacobian_predictor=true | Real grids only: predict the second point with dλ/dc; if disabled or unreliable, use the preceding value. Later points use the slope between the previous two results |
branch_window must be nonnegative; zero fixes the degree label. It has no effect with branch_lock=false. use_jacobian_predictor has no effect for complex paths, which use angular-profile matching. Both geometries and precision=:double/:quad are supported.
A closed path can exchange eigenmodes. Its final value need not equal its initial value. Nearly coalescing eigenvalues can make continuation and parameter derivatives ill-conditioned.
Multiple degrees
smn(1, 1:24, 1.25, [-0.7, 0.2, 0.8];
spheroid=:oblate, precision=:quad, normalize=true)
rmn(1, 1:24, 1.25, [0.4, 1.0, 3.0];
spheroid=:oblate, precision=:quad, kind=3, scaled=true)Rows correspond to coordinates; columns correspond to degrees. A scalar coordinate gives one row. Single-degree calls return vectors, including length-one vectors for scalar coordinates.
Scaled values and logarithmic derivatives
\[f=M\,10^E,\qquad \ell=\frac{f'}{f}.\]
s = smn(200, 200, 0.0, 0.3; scaled=true, logderivative=true)
s.value.mantissa
s.value.exponent
s.logderivative
r = rmn(1, 2, 1.25, 2.0;
kind=2, precision=:quad, scaled=true, logderivative=true)With scaled=true, value and derivative each contain mantissa and integer exponent arrays. For finite nonzero values, 1≤abs(mantissa)<10. Complex mantissas use a common exponent for both components; zeros and nonfinite values use exponent zero.
Scaling extends the representable magnitude, not the number of accurate digits. logderivative=true uses one-sided endpoint limits and returns NaN at other computed zeros. Unscaled values may overflow even when the logarithmic derivative remains finite.
Higher coordinate derivatives
For λ=λₘₙ(c) and σ=1 (prolate) or σ=-1 (oblate):
\[S''=\frac{2\eta S'- \left(\lambda-\sigma c^2\eta^2-\frac{m^2}{1-\eta^2}\right)S}{1-\eta^2},\]
\[R''=\frac{-2xR'- \left(c^2x^2-\lambda-\frac{\sigma m^2}{x^2-\sigma}\right)R}{x^2-\sigma}.\]
s = smn(1, 2, 1.25, 0.3; second_derivative=true, precision=:quad)
r = rmn(1, 2, 1.25, 2.0; second_derivative=true, precision=:quad)
s.second_derivative
r.second_derivativeBoth options also work with scaled outputs and degree ranges.
Use derivatives=3 or 4 to append third_derivative and fourth_derivative. Endpoint derivatives use one-sided limits. Oblate x=0 is supported. derivatives=2 is equivalent to second_derivative=true.
The formulas above apply away from singular endpoints. Regular endpoint derivatives use finite or infinite one-sided limits. Angular second-kind derivatives diverge at η=±1. Prolate radial kinds 2–4 at x=1 return NaN for real or complex parameters.
Radial Wronskians
For real c>0 and nonsingular radial coordinates:
\[W=R_1R_2'-R_1'R_2,\qquad \widehat W=c(x^2-\sigma)W=1,\qquad \varepsilon_W=|\widehat W-1|.\]
radial_wronskian form | Output |
|---|---|
:raw (default) | W |
:normalized | Ŵ |
:error | ε_W |
radial_wronskian(m,n,c,x; spheroid=:prolate, precision=:double, form=:raw) uses radial kinds 1 and 2 and their coordinate derivatives. m,n are integer order and degree with 0≤m≤n. Standard normalization requires finite c≠0. x is a real scalar or nonempty vector: use prolate x>1 or oblate x≥0. spheroid=:oblate selects σ=-1; precision=:quad selects quad precision. normalization=:static includes c=0, with $W=1/(x^2-\sigma)$ and normalized output $(x^2-\sigma)W$.
Every form returns a vector, including for scalar x. Raw and normalized entries are complex; error entries are real. Normalized forms preserve scaling in intermediate products. Complex c is accepted under the same conventions as rmn; the unit-normalization check stated above is for real c>0.
radial_wronskian(1, 2, 1.25, [1.5, 2.0, 4.0];
precision=:quad, form=:error)The prolate identity is DLMF 30.11.7; the oblate factor follows its radial equation and normalization.
Accuracy estimates
accuracy(m,n,c,arg; target=:radial, spheroid=:prolate, precision=:double, kind=1, normalize=false, normalization=:standard, diagnostics=false) returns one integer per coordinate.
| Argument / keyword | Meaning |
|---|---|
m, n | Integer order and degree, 0≤m≤n |
c | Finite real or complex parameter. Radial c=0 requires normalization=:static |
arg | Nonempty coordinate vector with the domain of smn or rmn. Use [x] for one point |
target=:radial | :radial estimates rmn values; :angular estimates smn values |
spheroid=:prolate | :prolate or :oblate geometry |
precision=:double | :double or :quad evaluation; results remain integer digit counts |
kind=1 | Angular 1 or 2; radial 1:4 |
normalize=false | Default angular normalization; true selects unit normalization for real first-kind angular functions and its analytic continuation for complex c. Invalid for angular kind 2; ignored for radial calls |
Positive entries estimate decimal digits; 0 reports no reliable digits and -1 means no estimate is available. Invalid inputs raise the corresponding wave-function errors; nonfinite values receive -1 when evaluation returns them.
For real coordinates, only radial kind=2 has a radial estimator, so the default radial call (kind=1) returns -1. Angular second-kind, endpoint, small-parameter (abs(c)≤1e-4), purely imaginary complex-parameter, and refined expansion evaluations and static radial normalization have no calibrated digit estimates. See accuracy.
accuracy(0, 1, 2.0, [1.5]; target=:radial, kind=2)
accuracy(0, 2, 1.0, [0.3]; target=:angular, normalize=true, precision=:quad)
accuracy(0, 2, 0.0, [0.3]; target=:angular) # [-1]Complex coordinates use higher precision and halved continuation steps to estimate convergence. Add diagnostics=true for per-point refinement changes, condition numbers, and convergence flags. Zeros, endpoints and unresolved estimates return -1.
a = accuracy(1, 2, 1.25, [0.3 + 0.2im]; target=:angular, diagnostics=true)
a.digits
a.diagnostics[1].conditioning_flag