Utilities

While not usually the star of the show, the following utilities can be quite helpful for actually using the rest of the code.

Complex powers

One common task we find when working with spherical functions is the computation of a range of integer powers of some complex number β€” so much so that it can be best to pre-compute the powers and cache their values. While a naive approach is generally quite accurate, and reasonably fast, we can do a little better with a specialized routine.

SphericalFunctions.complex_powers! β€” Method
complex_powers!(zpowers, z)

Compute integer powers of z from z^0 through z^m, recursively, where m is one less than the length of the input zpowers vector.

Note that z is assumed to be normalized, with complex amplitude approximately 1.

See also: complex_powers

source
SphericalFunctions.complex_powers β€” Method
complex_powers(z, m)

Compute integer powers of z from z^0 through z^m, recursively.

Note that z is assumed to be normalized, with complex amplitude approximately 1.

This algorithm is mostly due to Stoer and Bulirsch in "Introduction to Numerical Analysis" (page 24) β€” with a little help from de Moivre's formula, which is essentially exp(iΞΈ)ⁿ = exp(inΞΈ), as well as my own alterations to deal with different behaviors in different quadrants.

There isn't usually a huge advantage to using this specialized function. If you just need a particular power, it will generally be far more efficient and just as accurate to compute either exp(iΞΈ)ⁿ or exp(inΞΈ) explicitly. However, if you need all powers from 0 to m, this function is about 10 or 5 times faster than those options, respectively, for large m. Like those options, this function is numerically stable, in the sense that its errors are usually smaller than m times the error from machine-precision errors in the input argument β€” or at worst about 50% larger, which occurs as the phase approaches multiples of Ο€/2.

See also: complex_powers!

source

Sizes of and indexing into $𝔇$, $d$, and $Y$ data

By $Y$ data, we mean anything indexed like $Y_{\ell, m}$ modes; by $D$ data, we mean anything indexed like Wigner's $\mathfrak{D}$ matrices, or special subsets of them, like the $H$ matrices.

SphericalFunctions.WignerDindex β€” Function
WignerDindex(β„“, mβ€², m, mβ€²β‚˜β‚β‚“=β„“)

Compute index into Wigner 𝔇 matrix

See also WignerDrange and WignerDsize.

Notes

This assumes that the Wigner 𝔇 matrix is arranged as

[
    𝔇(β„“, mβ€², m)
    for β„“ in range(β„“β‚˜α΅’β‚™, β„“β‚˜β‚β‚“+1)
    for mβ€² in range(-min(β„“, mβ€²β‚˜β‚β‚“), min(β„“, mβ€²β‚˜β‚β‚“)+1)
    for m in range(-β„“, β„“+1)
]
source
SphericalFunctions.WignerDrange β€” Function
WignerDrange(β„“β‚˜β‚β‚“, mβ€²β‚˜β‚β‚“=β„“β‚˜β‚β‚“)

Create an array of (β„“, m', m) indices as in 𝔇 array

See also WignerDsize and WignerDindex.

Notes

This assumes that the Wigner 𝔇 matrix is arranged as

[
    𝔇(β„“, mβ€², m)
    for β„“ in range(β„“β‚˜α΅’β‚™, β„“β‚˜β‚β‚“+1)
    for mβ€² in range(-min(β„“, mβ€²β‚˜β‚β‚“), min(β„“, mβ€²β‚˜β‚β‚“)+1)
    for m in range(-β„“, β„“+1)
]
source
SphericalFunctions.WignerDsize β€” Method
WignerDsize(β„“β‚˜β‚β‚“, mβ€²β‚˜β‚β‚“=β„“β‚˜β‚β‚“)

Compute total size of Wigner 𝔇 matrix

See also WignerDrange and WignerDindex.

Notes

This assumes that the Wigner 𝔇 matrix is arranged as

[
    𝔇(β„“, mβ€², m)
    for β„“ in β„“β‚˜α΅’β‚™:β„“β‚˜β‚β‚“
    for mβ€² in -min(β„“, mβ€²β‚˜β‚β‚“):min(β„“, mβ€²β‚˜β‚β‚“)
    for m in -β„“:β„“
]
source
SphericalFunctions.WignerHindex β€” Function
WignerHindex(β„“, mβ€², m, mβ€²β‚˜β‚β‚“)

Index to "wedge" arrays.

See also WignerHsize and WignerHrange.

Notes

Here, it is assumed that only data with mβ‰₯|m'| are stored, and only corresponding values are passed. We also assume |m|≀ℓ and |m'|≀ℓ. Neither of these are checked. The wedge array that this function indexes is ordered as

[
    H(β„“, mβ€², m) for β„“ in range(β„“β‚˜β‚β‚“+1)
    for mβ€² in range(-min(β„“, mβ€²β‚˜β‚β‚“), min(β„“, mβ€²β‚˜β‚β‚“)+1)
    for m in range(abs(mβ€²), β„“+1)
]
source
SphericalFunctions.WignerHrange β€” Function
WignerHrange(β„“β‚˜β‚β‚“, mβ€²β‚˜β‚β‚“=β„“β‚˜β‚β‚“)

Create an array of (β„“, m', m) indices as in H array

See also WignerHsize and WignerHindex

Notes

Here, it is assumed that only data with mβ‰₯|m'| are stored, and only corresponding values are passed. We also assume |m|≀ℓ and |m'|≀ℓ. Neither of these are checked. The wedge array that this function indexes is ordered as

[
    H(β„“, mβ€², m) for β„“ in range(β„“β‚˜β‚β‚“+1)
    for mβ€² in range(-min(β„“, mβ€²β‚˜β‚β‚“), min(β„“, mβ€²β‚˜β‚β‚“)+1)
    for m in range(abs(mβ€²), β„“+1)
]
source
SphericalFunctions.WignerHsize β€” Method
WignerHsize(β„“β‚˜β‚β‚“, mβ€²β‚˜β‚β‚“=β„“β‚˜β‚β‚“)

Total size of array of wedges of width mβ€²β‚˜β‚β‚“ up to β„“β‚˜β‚β‚“. If mβ€²β‚˜β‚β‚“ is not given, it defaults to β„“β‚˜β‚β‚“.

See also WignerHrange and WignerHindex.

Notes

Here, it is assumed that only data with mβ‰₯|mβ€²| are stored, and only corresponding values are passed. We also assume |m|≀ℓ and |mβ€²|≀ℓ. Neither of these are checked. The wedge array that this function indexes is ordered as

[
    H(β„“, mβ€², m) for β„“ in 0:β„“β‚˜β‚β‚“
    for mβ€² in -min(β„“, mβ€²β‚˜β‚β‚“):min(β„“, mβ€²β‚˜β‚β‚“)
    for m in abs(mβ€²):β„“
]
source
SphericalFunctions.Yindex β€” Function
Yindex(β„“, m, β„“β‚˜α΅’β‚™=0)

Compute index into array of mode weights

Parameters

β„“ : int Integer satisfying β„“β‚˜α΅’β‚™ <= β„“ <= β„“β‚˜β‚β‚“ m : int Integer satisfying -β„“ <= m <= β„“ β„“β‚˜α΅’β‚™ : int, optional Integer satisfying 0 <= β„“β‚˜α΅’β‚™. Defaults to 0.

Returns

i : int Index of a particular element of the mode-weight array as described below

See Also

Ysize : Total size of array of mode weights Yrange : Array of (β„“, m) indices corresponding to this array

Notes

This assumes that the modes are arranged (with fixed s value) as

[
    Y(s, β„“, m)
    for β„“ in range(β„“β‚˜α΅’β‚™, β„“β‚˜β‚β‚“+1)
    for m in range(-β„“, β„“+1)
]
source
SphericalFunctions.Yrange β€” Method
Yrange(β„“β‚˜α΅’β‚™, β„“β‚˜β‚β‚“)

Create an array of (β„“, m) indices as in Y array

Parameters

β„“β‚˜α΅’β‚™ : int Integer satisfying 0 <= β„“β‚˜α΅’β‚™ <= β„“β‚˜β‚β‚“ β„“β‚˜β‚β‚“ : int Integer satisfying 0 <= β„“β‚˜α΅’β‚™ <= β„“β‚˜β‚β‚“

Returns

i : int Total size of array of mode weights arranged as described below

See Also

Ysize : Total size of array of mode weights Yindex : Index of a particular element of the mode weight array

Notes

This assumes that the modes are arranged (with fixed s value) as

[
    Y(s, β„“, m)
    for β„“ in range(β„“β‚˜α΅’β‚™, β„“β‚˜β‚β‚“+1)
    for m in range(-β„“, β„“+1)
]
source
SphericalFunctions.Ysize β€” Method
Ysize(β„“β‚˜β‚β‚“)

Compute total size of array of mode weights

See Also

Yrange : Array of (β„“, m) indices corresponding to this array Yindex : Index of a particular element of the mode weight array

Notes

This assumes that the modes are arranged (with fixed s value) as

[
    Y(s, β„“, m)
    for β„“ in range(β„“β‚˜α΅’β‚™, β„“β‚˜β‚β‚“+1)
    for m in range(-β„“, β„“+1)
]
source
SphericalFunctions._WignerHindex β€” Method

WignerHindex(β„“, mβ€², m, mβ€²β‚˜β‚β‚“)

Helper function for WignerHindex, with more constraints.

This function assumes that m β‰₯ |mβ€²|. The main WignerHindex function uses symmetries of the H array to account for cases that violate this assumption. (But note that both that function and this one assume that |m| ≀ β„“ and |mβ€²| ≀ β„“.)

source
SphericalFunctions.deduce_limits β€” Function
deduce_limits(ysize, [β„“min])

Deduce the value of (β„“min, β„“max) that produces $Y$ arrays of the given size.

If β„“min is not given, it is assumed to be 0. If it is set to nothing, the smallest possible value of β„“min will be used. However, note that this is not a well-posed problem; multiple combinations of (β„“min, β„“max) can give rise to $Y$ arrays of the same size.

See also Ysize

source
SphericalFunctions.theta_phi β€” Method
theta_phi(NΞΈ, NΟ•, [T=Float64])

Construct (theta, phi) grid in spinsfast order.

Note that this order is different from the one assumed by this package; use phi_theta for the opposite ordering.

source

Combinatorics

Spherical functions frequently involve binomial coefficients and similar terms, with arguments proportional to $β„“$, which we aim to allow to be very large β€” of order 1,000 or more. Unfortunately, due to combinatorical explosions, this is frequently infeasible with naive methods. Here, we collect any specialized methods that help us beat the limits.

SphericalFunctions.sqrtbinomial β€” Method
sqrtbinomial(n, k, [T])

Evaluate the square-root of the binomial coefficient binomial(n,k) for large coefficients.

Ordinarily, when n and k are standard Int arguments, the built-in binomial function will overflow around n=66, because it results in Ints. We need much larger values. This function, which is based on a related one in SpecialFunctions.jl, returns reasonably accurate results up to n β‰ˆ 1026 when k β‰ˆ n/2 (which is the case of interest in many applications in this package).

Computations are carried out (and returned) in type T, which defaults to Float64.

source