Wigner Symbols#

Wigner, Clebsch-Gordan, Racah, and Gaunt coefficients

Collection of functions for calculating Wigner 3j, 6j, 9j, Clebsch-Gordan, Racah as well as Gaunt coefficients exactly, all evaluating to a rational number times the square root of a rational number [Rasch03].

Please see the description of the individual functions for further details and examples.

References#

[Regge58] (1,2)

‘Symmetry Properties of Clebsch-Gordan Coefficients’, T. Regge, Nuovo Cimento, Volume 10, pp. 544 (1958)

[Regge59]

‘Symmetry Properties of Racah Coefficients’, T. Regge, Nuovo Cimento, Volume 11, pp. 116 (1959)

[Edmonds74] (1,2,3,4,5,6,7,8,9,10)

A. R. Edmonds. Angular momentum in quantum mechanics. Investigations in physics, 4.; Investigations in physics, no. 4. Princeton, N.J., Princeton University Press, 1957.

[Rasch03] (1,2,3,4,5,6)

J. Rasch and A. C. H. Yu, ‘Efficient Storage Scheme for Pre-calculated Wigner 3j, 6j and Gaunt Coefficients’, SIAM J. Sci. Comput. Volume 25, Issue 4, pp. 1416-1428 (2003)

[Liberatodebrito82]

‘FORTRAN program for the integral of three spherical harmonics’, A. Liberato de Brito, Comput. Phys. Commun., Volume 25, pp. 81-85 (1982)

Authors#

  • Jens Rasch (2009-03-24): initial version for Sage

  • Jens Rasch (2009-05-31): updated to sage-4.0

  • Oscar Gerardo Lazo Arjona (2017-06-18): added Wigner D matrices

Copyright (C) 2008 Jens Rasch <jyr2000@gmail.com>

sympy.physics.wigner.clebsch_gordan(j_1, j_2, j_3, m_1, m_2, m_3)[source]#

Calculates the Clebsch-Gordan coefficient. \(\left\langle j_1 m_1 \; j_2 m_2 | j_3 m_3 \right\rangle\).

The reference for this function is [Edmonds74].

Parameters:

j_1, j_2, j_3, m_1, m_2, m_3 :

Integer or half integer.

Returns:

Rational number times the square root of a rational number.

Examples

>>> from sympy import S
>>> from sympy.physics.wigner import clebsch_gordan
>>> clebsch_gordan(S(3)/2, S(1)/2, 2, S(3)/2, S(1)/2, 2)
1
>>> clebsch_gordan(S(3)/2, S(1)/2, 1, S(3)/2, -S(1)/2, 1)
sqrt(3)/2
>>> clebsch_gordan(S(3)/2, S(1)/2, 1, -S(1)/2, S(1)/2, 0)
-sqrt(2)/2

Notes

The Clebsch-Gordan coefficient will be evaluated via its relation to Wigner 3j symbols:

\[\left\langle j_1 m_1 \; j_2 m_2 | j_3 m_3 \right\rangle =(-1)^{j_1-j_2+m_3} \sqrt{2j_3+1} \operatorname{Wigner3j}(j_1,j_2,j_3,m_1,m_2,-m_3)\]

See also the documentation on Wigner 3j symbols which exhibit much higher symmetry relations than the Clebsch-Gordan coefficient.

Authors

  • Jens Rasch (2009-03-24): initial version

sympy.physics.wigner.dot_rot_grad_Ynm(j, p, l, m, theta, phi)[source]#

Returns dot product of rotational gradients of spherical harmonics.

Explanation

This function returns the right hand side of the following expression:

\[\vec{R}Y{_j^{p}} \cdot \vec{R}Y{_l^{m}} = (-1)^{m+p} \sum\limits_{k=|l-j|}^{l+j}Y{_k^{m+p}} * \alpha_{l,m,j,p,k} * \frac{1}{2} (k^2-j^2-l^2+k-j-l)\]

Arguments

j, p, l, m …. indices in spherical harmonics (expressions or integers) theta, phi …. angle arguments in spherical harmonics

Example

>>> from sympy import symbols
>>> from sympy.physics.wigner import dot_rot_grad_Ynm
>>> theta, phi = symbols("theta phi")
>>> dot_rot_grad_Ynm(3, 2, 2, 0, theta, phi).doit()
3*sqrt(55)*Ynm(5, 2, theta, phi)/(11*sqrt(pi))
sympy.physics.wigner.gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None)[source]#

Calculate the Gaunt coefficient.

Parameters:

l_1, l_2, l_3, m_1, m_2, m_3 :

Integer.

prec - precision, default: ``None``.

Providing a precision can drastically speed up the calculation.

Returns:

Rational number times the square root of a rational number

(if prec=None), or real number if a precision is given.

Explanation

The Gaunt coefficient is defined as the integral over three spherical harmonics:

\[\begin{split}\begin{aligned} \operatorname{Gaunt}(l_1,l_2,l_3,m_1,m_2,m_3) &=\int Y_{l_1,m_1}(\Omega) Y_{l_2,m_2}(\Omega) Y_{l_3,m_3}(\Omega) \,d\Omega \\ &=\sqrt{\frac{(2l_1+1)(2l_2+1)(2l_3+1)}{4\pi}} \operatorname{Wigner3j}(l_1,l_2,l_3,0,0,0) \operatorname{Wigner3j}(l_1,l_2,l_3,m_1,m_2,m_3) \end{aligned}\end{split}\]

Examples

>>> from sympy.physics.wigner import gaunt
>>> gaunt(1,0,1,1,0,-1)
-1/(2*sqrt(pi))
>>> gaunt(1000,1000,1200,9,3,-12).n(64)
0.00689500421922113448...

It is an error to use non-integer values for \(l\) and \(m\):

sage: gaunt(1.2,0,1.2,0,0,0)
Traceback (most recent call last):
...
ValueError: l values must be integer
sage: gaunt(1,0,1,1.1,0,-1.1)
Traceback (most recent call last):
...
ValueError: m values must be integer

Notes

The Gaunt coefficient obeys the following symmetry rules:

  • invariant under any permutation of the columns

    \[\begin{split}\begin{aligned} Y(l_1,l_2,l_3,m_1,m_2,m_3) &=Y(l_3,l_1,l_2,m_3,m_1,m_2) \\ &=Y(l_2,l_3,l_1,m_2,m_3,m_1) \\ &=Y(l_3,l_2,l_1,m_3,m_2,m_1) \\ &=Y(l_1,l_3,l_2,m_1,m_3,m_2) \\ &=Y(l_2,l_1,l_3,m_2,m_1,m_3) \end{aligned}\end{split}\]
  • invariant under space inflection, i.e.

    \[Y(l_1,l_2,l_3,m_1,m_2,m_3) =Y(l_1,l_2,l_3,-m_1,-m_2,-m_3)\]
  • symmetric with respect to the 72 Regge symmetries as inherited for the \(3j\) symbols [Regge58]

  • zero for \(l_1\), \(l_2\), \(l_3\) not fulfilling triangle relation

  • zero for violating any one of the conditions: \(l_1 \ge |m_1|\), \(l_2 \ge |m_2|\), \(l_3 \ge |m_3|\)

  • non-zero only for an even sum of the \(l_i\), i.e. \(L = l_1 + l_2 + l_3 = 2n\) for \(n\) in \(\mathbb{N}\)

Algorithms

This function uses the algorithm of [Liberatodebrito82] to calculate the value of the Gaunt coefficient exactly. Note that the formula contains alternating sums over large factorials and is therefore unsuitable for finite precision arithmetic and only useful for a computer algebra system [Rasch03].

Authors

Jens Rasch (2009-03-24): initial version for Sage.

sympy.physics.wigner.racah(aa, bb, cc, dd, ee, ff, prec=None)[source]#

Calculate the Racah symbol \(W(a,b,c,d;e,f)\).

Parameters:

a, …, f :

Integer or half integer.

prec :

Precision, default: None. Providing a precision can drastically speed up the calculation.

Returns:

Rational number times the square root of a rational number

(if prec=None), or real number if a precision is given.

Examples

>>> from sympy.physics.wigner import racah
>>> racah(3,3,3,3,3,3)
-1/14

Notes

The Racah symbol is related to the Wigner 6j symbol:

\[\operatorname{Wigner6j}(j_1,j_2,j_3,j_4,j_5,j_6) =(-1)^{j_1+j_2+j_4+j_5} W(j_1,j_2,j_5,j_4,j_3,j_6)\]

Please see the 6j symbol for its much richer symmetries and for additional properties.

Algorithm

This function uses the algorithm of [Edmonds74] to calculate the value of the 6j symbol exactly. Note that the formula contains alternating sums over large factorials and is therefore unsuitable for finite precision arithmetic and only useful for a computer algebra system [Rasch03].

Authors

  • Jens Rasch (2009-03-24): initial version

sympy.physics.wigner.wigner_3j(j_1, j_2, j_3, m_1, m_2, m_3)[source]#

Calculate the Wigner 3j symbol \(\operatorname{Wigner3j}(j_1,j_2,j_3,m_1,m_2,m_3)\).

Parameters:

j_1, j_2, j_3, m_1, m_2, m_3 :

Integer or half integer.

Returns:

Rational number times the square root of a rational number.

Examples

>>> from sympy.physics.wigner import wigner_3j
>>> wigner_3j(2, 6, 4, 0, 0, 0)
sqrt(715)/143
>>> wigner_3j(2, 6, 4, 0, 0, 1)
0

It is an error to have arguments that are not integer or half integer values:

sage: wigner_3j(2.1, 6, 4, 0, 0, 0)
Traceback (most recent call last):
...
ValueError: j values must be integer or half integer
sage: wigner_3j(2, 6, 4, 1, 0, -1.1)
Traceback (most recent call last):
...
ValueError: m values must be integer or half integer

Notes

The Wigner 3j symbol obeys the following symmetry rules:

  • invariant under any permutation of the columns (with the exception of a sign change where \(J:=j_1+j_2+j_3\)):

    \[\begin{split}\begin{aligned} \operatorname{Wigner3j}(j_1,j_2,j_3,m_1,m_2,m_3) &=\operatorname{Wigner3j}(j_3,j_1,j_2,m_3,m_1,m_2) \\ &=\operatorname{Wigner3j}(j_2,j_3,j_1,m_2,m_3,m_1) \\ &=(-1)^J \operatorname{Wigner3j}(j_3,j_2,j_1,m_3,m_2,m_1) \\ &=(-1)^J \operatorname{Wigner3j}(j_1,j_3,j_2,m_1,m_3,m_2) \\ &=(-1)^J \operatorname{Wigner3j}(j_2,j_1,j_3,m_2,m_1,m_3) \end{aligned}\end{split}\]
  • invariant under space inflection, i.e.

    \[\operatorname{Wigner3j}(j_1,j_2,j_3,m_1,m_2,m_3) =(-1)^J \operatorname{Wigner3j}(j_1,j_2,j_3,-m_1,-m_2,-m_3)\]
  • symmetric with respect to the 72 additional symmetries based on the work by [Regge58]

  • zero for \(j_1\), \(j_2\), \(j_3\) not fulfilling triangle relation

  • zero for \(m_1 + m_2 + m_3 \neq 0\)

  • zero for violating any one of the conditions \(j_1 \ge |m_1|\), \(j_2 \ge |m_2|\), \(j_3 \ge |m_3|\)

Algorithm

This function uses the algorithm of [Edmonds74] to calculate the value of the 3j symbol exactly. Note that the formula contains alternating sums over large factorials and is therefore unsuitable for finite precision arithmetic and only useful for a computer algebra system [Rasch03].

Authors

  • Jens Rasch (2009-03-24): initial version

sympy.physics.wigner.wigner_6j(j_1, j_2, j_3, j_4, j_5, j_6, prec=None)[source]#

Calculate the Wigner 6j symbol \(\operatorname{Wigner6j}(j_1,j_2,j_3,j_4,j_5,j_6)\).

Parameters:

j_1, …, j_6 :

Integer or half integer.

prec :

Precision, default: None. Providing a precision can drastically speed up the calculation.

Returns:

Rational number times the square root of a rational number

(if prec=None), or real number if a precision is given.

Examples

>>> from sympy.physics.wigner import wigner_6j
>>> wigner_6j(3,3,3,3,3,3)
-1/14
>>> wigner_6j(5,5,5,5,5,5)
1/52

It is an error to have arguments that are not integer or half integer values or do not fulfill the triangle relation:

sage: wigner_6j(2.5,2.5,2.5,2.5,2.5,2.5)
Traceback (most recent call last):
...
ValueError: j values must be integer or half integer and fulfill the triangle relation
sage: wigner_6j(0.5,0.5,1.1,0.5,0.5,1.1)
Traceback (most recent call last):
...
ValueError: j values must be integer or half integer and fulfill the triangle relation

Notes

The Wigner 6j symbol is related to the Racah symbol but exhibits more symmetries as detailed below.

\[\operatorname{Wigner6j}(j_1,j_2,j_3,j_4,j_5,j_6) =(-1)^{j_1+j_2+j_4+j_5} W(j_1,j_2,j_5,j_4,j_3,j_6)\]

The Wigner 6j symbol obeys the following symmetry rules:

  • Wigner 6j symbols are left invariant under any permutation of the columns:

    \[\begin{split}\begin{aligned} \operatorname{Wigner6j}(j_1,j_2,j_3,j_4,j_5,j_6) &=\operatorname{Wigner6j}(j_3,j_1,j_2,j_6,j_4,j_5) \\ &=\operatorname{Wigner6j}(j_2,j_3,j_1,j_5,j_6,j_4) \\ &=\operatorname{Wigner6j}(j_3,j_2,j_1,j_6,j_5,j_4) \\ &=\operatorname{Wigner6j}(j_1,j_3,j_2,j_4,j_6,j_5) \\ &=\operatorname{Wigner6j}(j_2,j_1,j_3,j_5,j_4,j_6) \end{aligned}\end{split}\]
  • They are invariant under the exchange of the upper and lower arguments in each of any two columns, i.e.

    \[\operatorname{Wigner6j}(j_1,j_2,j_3,j_4,j_5,j_6) =\operatorname{Wigner6j}(j_1,j_5,j_6,j_4,j_2,j_3) =\operatorname{Wigner6j}(j_4,j_2,j_6,j_1,j_5,j_3) =\operatorname{Wigner6j}(j_4,j_5,j_3,j_1,j_2,j_6)\]
  • additional 6 symmetries [Regge59] giving rise to 144 symmetries in total

  • only non-zero if any triple of \(j\)’s fulfill a triangle relation

Algorithm

This function uses the algorithm of [Edmonds74] to calculate the value of the 6j symbol exactly. Note that the formula contains alternating sums over large factorials and is therefore unsuitable for finite precision arithmetic and only useful for a computer algebra system [Rasch03].

sympy.physics.wigner.wigner_9j(j_1, j_2, j_3, j_4, j_5, j_6, j_7, j_8, j_9, prec=None)[source]#

Calculate the Wigner 9j symbol \(\operatorname{Wigner9j}(j_1,j_2,j_3,j_4,j_5,j_6,j_7,j_8,j_9)\).

Parameters:

j_1, …, j_9 :

Integer or half integer.

prec : precision, default

None. Providing a precision can drastically speed up the calculation.

Returns:

Rational number times the square root of a rational number

(if prec=None), or real number if a precision is given.

Examples

>>> from sympy.physics.wigner import wigner_9j
>>> wigner_9j(1,1,1, 1,1,1, 1,1,0, prec=64) # ==1/18
0.05555555...
>>> wigner_9j(1/2,1/2,0, 1/2,3/2,1, 0,1,1, prec=64) # ==1/6
0.1666666...

It is an error to have arguments that are not integer or half integer values or do not fulfill the triangle relation:

sage: wigner_9j(0.5,0.5,0.5, 0.5,0.5,0.5, 0.5,0.5,0.5,prec=64)
Traceback (most recent call last):
...
ValueError: j values must be integer or half integer and fulfill the triangle relation
sage: wigner_9j(1,1,1, 0.5,1,1.5, 0.5,1,2.5,prec=64)
Traceback (most recent call last):
...
ValueError: j values must be integer or half integer and fulfill the triangle relation

Algorithm

This function uses the algorithm of [Edmonds74] to calculate the value of the 3j symbol exactly. Note that the formula contains alternating sums over large factorials and is therefore unsuitable for finite precision arithmetic and only useful for a computer algebra system [Rasch03].

sympy.physics.wigner.wigner_d(J, alpha, beta, gamma)[source]#

Return the Wigner D matrix for angular momentum J.

Returns:

A matrix representing the corresponding Euler angle rotation( in the basis

of eigenvectors of \(J_z\)).

\[\mathcal{D}_{\alpha \beta \gamma} = \exp\big( \frac{i\alpha}{\hbar} J_z\big) \exp\big( \frac{i\beta}{\hbar} J_y\big) \exp\big( \frac{i\gamma}{\hbar} J_z\big)\]

The components are calculated using the general form [Edmonds74],

equation 4.1.12.

Explanation

J :

An integer, half-integer, or SymPy symbol for the total angular momentum of the angular momentum space being rotated.

alpha, beta, gamma - Real numbers representing the Euler.

Angles of rotation about the so-called vertical, line of nodes, and figure axes. See [Edmonds74].

Examples

The simplest possible example:

>>> from sympy.physics.wigner import wigner_d
>>> from sympy import Integer, symbols, pprint
>>> half = 1/Integer(2)
>>> alpha, beta, gamma = symbols("alpha, beta, gamma", real=True)
>>> pprint(wigner_d(half, alpha, beta, gamma), use_unicode=True)
⎡  ⅈ⋅α  ⅈ⋅γ             ⅈ⋅α  -ⅈ⋅γ         ⎤
⎢  ───  ───             ───  ─────        ⎥
⎢   2    2     ⎛β⎞       2     2      ⎛β⎞ ⎥
⎢ ℯ   ⋅ℯ   ⋅cos⎜─⎟     ℯ   ⋅ℯ     ⋅sin⎜─⎟ ⎥
⎢              ⎝2⎠                    ⎝2⎠ ⎥
⎢                                         ⎥
⎢  -ⅈ⋅α   ⅈ⋅γ          -ⅈ⋅α   -ⅈ⋅γ        ⎥
⎢  ─────  ───          ─────  ─────       ⎥
⎢    2     2     ⎛β⎞     2      2      ⎛β⎞⎥
⎢-ℯ     ⋅ℯ   ⋅sin⎜─⎟  ℯ     ⋅ℯ     ⋅cos⎜─⎟⎥
⎣                ⎝2⎠                   ⎝2⎠⎦
sympy.physics.wigner.wigner_d_small(J, beta)[source]#

Return the small Wigner d matrix for angular momentum J.

Returns:

A matrix representing the corresponding Euler angle rotation( in the basis

of eigenvectors of \(J_z\)).

\[\mathcal{d}_{\beta} = \exp\big( \frac{i\beta}{\hbar} J_y\big)\]

The components are calculated using the general form [Edmonds74],

equation 4.1.15.

Explanation

JAn integer, half-integer, or SymPy symbol for the total angular

momentum of the angular momentum space being rotated.

betaA real number representing the Euler angle of rotation about

the so-called line of nodes. See [Edmonds74].

Examples

>>> from sympy import Integer, symbols, pi, pprint
>>> from sympy.physics.wigner import wigner_d_small
>>> half = 1/Integer(2)
>>> beta = symbols("beta", real=True)
>>> pprint(wigner_d_small(half, beta), use_unicode=True)
⎡   ⎛β⎞      ⎛β⎞⎤
⎢cos⎜─⎟   sin⎜─⎟⎥
⎢   ⎝2⎠      ⎝2⎠⎥
⎢               ⎥
⎢    ⎛β⎞     ⎛β⎞⎥
⎢-sin⎜─⎟  cos⎜─⎟⎥
⎣    ⎝2⎠     ⎝2⎠⎦
>>> pprint(wigner_d_small(2*half, beta), use_unicode=True)
⎡        2⎛β⎞              ⎛β⎞    ⎛β⎞           2⎛β⎞     ⎤
⎢     cos ⎜─⎟        √2⋅sin⎜─⎟⋅cos⎜─⎟        sin ⎜─⎟     ⎥
⎢         ⎝2⎠              ⎝2⎠    ⎝2⎠            ⎝2⎠     ⎥
⎢                                                        ⎥
⎢       ⎛β⎞    ⎛β⎞       2⎛β⎞      2⎛β⎞        ⎛β⎞    ⎛β⎞⎥
⎢-√2⋅sin⎜─⎟⋅cos⎜─⎟  - sin ⎜─⎟ + cos ⎜─⎟  √2⋅sin⎜─⎟⋅cos⎜─⎟⎥
⎢       ⎝2⎠    ⎝2⎠        ⎝2⎠       ⎝2⎠        ⎝2⎠    ⎝2⎠⎥
⎢                                                        ⎥
⎢        2⎛β⎞               ⎛β⎞    ⎛β⎞          2⎛β⎞     ⎥
⎢     sin ⎜─⎟        -√2⋅sin⎜─⎟⋅cos⎜─⎟       cos ⎜─⎟     ⎥
⎣         ⎝2⎠               ⎝2⎠    ⎝2⎠           ⎝2⎠     ⎦

From table 4 in [Edmonds74]

>>> pprint(wigner_d_small(half, beta).subs({beta:pi/2}), use_unicode=True)
⎡ √2   √2⎤
⎢ ──   ──⎥
⎢ 2    2 ⎥
⎢        ⎥
⎢-√2   √2⎥
⎢────  ──⎥
⎣ 2    2 ⎦
>>> pprint(wigner_d_small(2*half, beta).subs({beta:pi/2}),
... use_unicode=True)
⎡       √2      ⎤
⎢1/2    ──   1/2⎥
⎢       2       ⎥
⎢               ⎥
⎢-√2         √2 ⎥
⎢────   0    ── ⎥
⎢ 2          2  ⎥
⎢               ⎥
⎢      -√2      ⎥
⎢1/2   ────  1/2⎥
⎣       2       ⎦
>>> pprint(wigner_d_small(3*half, beta).subs({beta:pi/2}),
... use_unicode=True)
⎡ √2    √6    √6   √2⎤
⎢ ──    ──    ──   ──⎥
⎢ 4     4     4    4 ⎥
⎢                    ⎥
⎢-√6   -√2    √2   √6⎥
⎢────  ────   ──   ──⎥
⎢ 4     4     4    4 ⎥
⎢                    ⎥
⎢ √6   -√2   -√2   √6⎥
⎢ ──   ────  ────  ──⎥
⎢ 4     4     4    4 ⎥
⎢                    ⎥
⎢-√2    √6   -√6   √2⎥
⎢────   ──   ────  ──⎥
⎣ 4     4     4    4 ⎦
>>> pprint(wigner_d_small(4*half, beta).subs({beta:pi/2}),
... use_unicode=True)
⎡             √6            ⎤
⎢1/4   1/2    ──   1/2   1/4⎥
⎢             4             ⎥
⎢                           ⎥
⎢-1/2  -1/2   0    1/2   1/2⎥
⎢                           ⎥
⎢ √6                     √6 ⎥
⎢ ──    0    -1/2   0    ── ⎥
⎢ 4                      4  ⎥
⎢                           ⎥
⎢-1/2  1/2    0    -1/2  1/2⎥
⎢                           ⎥
⎢             √6            ⎥
⎢1/4   -1/2   ──   -1/2  1/4⎥
⎣             4             ⎦