Wigner's $๐$ and $d$ matrices
Wigner's $๐$ matrices โ and to a lesser extent, the related $d$ matrices โ are extremely important in the theory of rotations. Each element is, itself, a special function of the rotation group: in particular, an eigenfunction of the left- and right-Lie derivatives, and thus a spin-weighted spherical function. Collectively, they describe how spin-weighted spherical functions transform under rotation. But their accurate and efficient computation is surprisingly subtle. This package implements the current state-of-the-art techniques for their fast and accurate computation, based on the $H$ recursion.
The actual computations can be done with the D_matrices
function:
using Quaternionic
using SphericalFunctions
R = randn(RotorF64)
โโโโ = 8
๐ = D_matrices(R, โโโโ)
However, the matrices can take up a lot of memory. So for maximum efficiency when calling this function repeatedly with different R
values, it is best to pre-allocate the necessary memory with the D_prep
function, and the pass that in as an argument to D_matrices!
:
D_storage = D_prep(โโโโ)
๐ = D_matrices!(D_storage, R)
(Beware that, as noted in the documentation for D_matrices!
, the output ๐
is just a reference to part of the D_storage
object, so you should not reuse D_storage
until you have copied or otherwise finished using ๐
.)
The output ๐
is a (linear!) vector of Complex
numbers with the same base type as R
. The ordering of the elements is described in the documentation for D_matrices
. It is also possible to efficiently view slices of this vector as a series of individual matrices using a D_iterator
:
for (โ, Dหก) in zip(0:โโโโ, D_iterator(๐, โโโโ))
# Do something with the matrix Dหก[โ+mโฒ+1, โ+m+1]
end
For the $d$ matrices, we have almost the same interface, except that instead of the input quaternion R
we only need the angle ฮฒ
(or its complex angle expiฮฒ
, which can be computed directly in some cases), and the output is real-valued:
using Quaternionic
using SphericalFunctions
ฮฒ = ฯ * rand(Float64)
โโโโ = 8
d = d_matrices(ฮฒ, โโโโ)
Again, for repeated calls, it is best to pre-allocate storage:
d_storage = d_prep(โโโโ)
d = d_matrices!(d_storage, ฮฒ)
The output d
is a vector of numbers of the same type as ฮฒ
, ordered in the same way as the output of D_matrices
. And similarly, we can iterate over the individual matrices using a d_iterator
.
Docstrings
SphericalFunctions.D_matrices
โ FunctionD_matrices(R, โโโโ)
D_matrices(ฮฑ, ฮฒ, ฮณ, โโโโ)
Compute Wigner's ๐ matrices $\mathfrak{D}^{(\ell)}_{m',m}(\beta)$ for all $\ell \leq \ell_\mathrm{max}$.
See D_matrices!
for details about the input and output values.
This function only appropriate when you need to evaluate the matrices for a single value of R
or ฮฑ, ฮฒ, ฮณ
because it allocates large arrays and performs many calculations that could be reused. If you need to evaluate the matrices for many values of R
or ฮฑ, ฮฒ, ฮณ
, you should pre-allocate the storage with D_prep
, and then call D_matrices!
with the result instead.
SphericalFunctions.D_matrices!
โ FunctionD_matrices!(D_storage, R)
D_matrices!(D_storage, ฮฑ, ฮฒ, ฮณ)
D_matrices!(D, R, โโโโ)
D_matrices!(D, ฮฑ, ฮฒ, ฮณ, โโโโ)
Compute Wigner's ๐ matrices $\mathfrak{D}^{(\ell)}_{m',m}(\beta)$ for all $\ell \leq \ell_\mathrm{max}$.
In all cases, the result is returned in a 1-dimensional array ordered as
[
๐หกโโ,โ(R)
for โ โ 0:โโโโ
for mp โ -โ:โ
for m โ -โ:โ
]
When the first argument is D
, it will be modified, so it must be at least as large as that array. When the first argument is D_storage
, it should be the quantity returned by D_prep
, and the result will be written into the D
field of that tuple. Both of these options โ especially the latter โ reduce the number of allocations needed on each call to the corresponding functions, which should increase the speed significantly. Note that the D
or D_storage
arguments must have types compatible with the type of R
or ฮฑ, ฮฒ, ฮณ
.
When using the D_storage
argument (which is recommended), the returned quantity D
will be an alias of D_storage[1]
. If you want to retain that data after the next call to D_matrices!
, you should copy it with copy(D)
.
The ฮฑ, ฮฒ, ฮณ
arguments are Euler angles as described in the documentation of Quaternionic.from_euler_angles
.
See also D_matrices
for a simpler function call when you only need to evaluate the matrices for a single value of R
or ฮฑ, ฮฒ, ฮณ
.
Examples
using Quaternionic, SphericalFunctions
โโโโ = 8
T = Float64
R = Rotor{T}(1, 2, 3, 4) # Will be normalized automatically
D_storage = D_prep(โโโโ, T)
D = D_matrices!(D_storage, R)
SphericalFunctions.D_prep
โ FunctionD_prep(โโโโ, [T=Float64])
Construct storage space and pre-compute recursion coefficients to compute Wigner's $\mathfrak{D}$ matrix in place.
This returns the D_storage
arguments needed by D_matrices!
.
SphericalFunctions.D_iterator
โ TypeD_iterator(D, โโโโ, [โโแตขโ])
Construct an Iterator that returns sub-matrices of D
, each of which consists of elements $(โ,-โ,-โ)$ through $(โ,โ,โ)$, for $โ$ from โโแตขโ
through โโโโ
. By default, โโแตขโ
is 0.
Note that the returned objects are views into the original D
data โ meaning that you may alter their values.
Because the result is a matrix restricted to a particular $โ$ value, you can index the $(โ, mโฒ, m)$ element as [โ+mโฒ+1, โ+m+1]
. For example, you might use this as something like
for (โ, Dหก) in zip(โโแตขโ:โโโโ, D_iterator(D, โโโโ))
for mโฒ in -โ:โ
for m in -โ:โ
Dหก[โ+mโฒ+1, โ+m+1] = <...>
end
end
end
Also note that no bounds checking is done, either at instantiation time or during iteration. You are responsible for ensuring that the size of D
and the values of โโโโ
and โโแตขโ
make sense.
SphericalFunctions.d_matrices
โ Functiond_matrices(ฮฒ, โโโโ)
d_matrices(expiฮฒ, โโโโ)
Compute Wigner's $d^{(\ell)}$ matrices with elements $d^{(\ell)}_{m',m}(\beta)$ for all $\ell \leq \ell_\mathrm{max}$. The $d$ matrices are sometimes called the "reduced" Wigner matrices, in contrast to the full $\mathfrak{D}$ matrices.
See d_matrices!
for details about the input and output values.
This function only appropriate when you need to evaluate the matrices for a single value of ฮฒ
or expiฮฒ
because it allocates large arrays and performs many calculations that could be reused. If you need to evaluate the matrices for many values of ฮฒ
or expiฮฒ
, you should pre-allocate the storage with d_prep
, and then call d_matrices!
with the result instead.
SphericalFunctions.d_matrices!
โ Functiond_matrices!(d_storage, ฮฒ)
d_matrices!(d_storage, expiฮฒ)
d_matrices!(d, ฮฒ, โโโโ)
d_matrices!(d, expiฮฒ, โโโโ)
Compute Wigner's $d^{(\ell)}$ matrices with elements $d^{(\ell)}_{m',m}(\beta)$ for all $\ell \leq \ell_\mathrm{max}$. The $d$ matrices are sometimes called the "reduced" Wigner matrices, in contrast to the full $\mathfrak{D}$ matrices.
In all cases, the result is returned in a 1-dimensional array ordered as
[
dหกโโ,โ(ฮฒ)
for โ โ 0:โโโโ
for mp โ -โ:โ
for m โ -โ:โ
]
When the first argument is d
, it will be modified, so it must be at least as large as that array. When the first argument is d_storage
, it should be the quantity returned by d_prep
, and the result will be written into the d
field of that tuple. Both of these options โ especially the latter โ reduce the number of allocations needed on each call to the corresponding functions, which should increase the speed significantly.
When using the d_storage
argument (which is recommended), the returned quantity d
will be an alias of d_storage[1]
. If you want to retain that data after the next call to d_matrices!
, you should copy it with copy(d)
.
See also d_matrices
for a simpler function call when you only need to evaluate the matrices for a single value of ฮฒ
or expiฮฒ
.
Examples
using SphericalFunctions
โโโโ = 8
T = Float64
ฮฒ = T(1)/8
d_storage = d_prep(โโโโ, T)
d = d_matrices!(d_storage, ฮฒ)
SphericalFunctions.d_prep
โ Functiond_prep(โโโโ, [T=Float64])
Construct space and pre-compute recursion coefficients to compute Wigner's $d$ matrix in place.
This returns the d_storage
arguments needed by d_matrices!
.
SphericalFunctions.d_iterator
โ Typed_iterator(d, โโโโ, [โโแตขโ])
Construct an Iterator that returns sub-matrices of d
, each of which consists of elements $(โ,-โ,-โ)$ through $(โ,โ,โ)$, for $โ$ from โโแตขโ
through โโโโ
. By default, โโแตขโ
is 0.
Note that the returned objects are views into the original d
data โ meaning that you may alter their values.
Because the result is a matrix restricted to a particular $โ$ value, you can index the $(โ, mโฒ, m)$ element as [โ+mโฒ+1, โ+m+1]
. For example, you might use this as something like
for (โ, dหก) in zip(โโแตขโ:โโโโ, d_iterator(d, โโโโ))
for mโฒ in -โ:โ
for m in -โ:โ
dหก[โ+mโฒ+1, โ+m+1] = <...>
end
end
end
Also note that no bounds checking is done, either at instantiation time or during iteration. You are responsible for ensuring that the size of d
and the values of โโโโ
and โโแตขโ
make sense.