| |
| r""" |
| 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] '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] 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] 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) |
| .. [Homeier96] 'Some Properties of the Coupling Coefficients of Real |
| Spherical Harmonics and Their Relation to Gaunt Coefficients', |
| H. H. H. Homeier and E. O. Steinborn J. Mol. Struct., Volume 368, |
| pp. 31-37 (1996) |
| |
| Credits and Copyright |
| ===================== |
| |
| This code was taken from Sage with the permission of all authors: |
| |
| https://groups.google.com/forum/#!topic/sage-devel/M4NZdu-7O38 |
| |
| 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 |
| |
| - Phil Adam LeMaitre (2022-09-19): added real Gaunt coefficient |
| |
| Copyright (C) 2008 Jens Rasch <jyr2000@gmail.com> |
| |
| """ |
| from sympy.concrete.summations import Sum |
| from sympy.core.add import Add |
| from sympy.core.numbers import int_valued |
| from sympy.core.function import Function |
| from sympy.core.numbers import (Float, I, Integer, pi, Rational) |
| from sympy.core.singleton import S |
| from sympy.core.symbol import Dummy |
| from sympy.core.sympify import sympify |
| from sympy.functions.combinatorial.factorials import (binomial, factorial) |
| from sympy.functions.elementary.complexes import re |
| from sympy.functions.elementary.exponential import exp |
| from sympy.functions.elementary.miscellaneous import sqrt |
| from sympy.functions.elementary.trigonometric import (cos, sin) |
| from sympy.functions.special.spherical_harmonics import Ynm |
| from sympy.matrices.dense import zeros |
| from sympy.matrices.immutable import ImmutableMatrix |
| from sympy.utilities.misc import as_int |
|
|
| |
| |
| _Factlist = [1] |
|
|
|
|
| def _calc_factlist(nn): |
| r""" |
| Function calculates a list of precomputed factorials in order to |
| massively accelerate future calculations of the various |
| coefficients. |
| |
| Parameters |
| ========== |
| |
| nn : integer |
| Highest factorial to be computed. |
| |
| Returns |
| ======= |
| |
| list of integers : |
| The list of precomputed factorials. |
| |
| Examples |
| ======== |
| |
| Calculate list of factorials:: |
| |
| sage: from sage.functions.wigner import _calc_factlist |
| sage: _calc_factlist(10) |
| [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800] |
| """ |
| if nn >= len(_Factlist): |
| for ii in range(len(_Factlist), int(nn + 1)): |
| _Factlist.append(_Factlist[ii - 1] * ii) |
| return _Factlist[:int(nn) + 1] |
|
|
|
|
| def _int_or_halfint(value): |
| """return Python int unless value is half-int (then return float)""" |
| if isinstance(value, int): |
| return value |
| elif type(value) is float: |
| if value.is_integer(): |
| return int(value) |
| if (2*value).is_integer(): |
| return value |
| elif isinstance(value, Rational): |
| if value.q == 2: |
| return value.p/value.q |
| elif value.q == 1: |
| return value.p |
| elif isinstance(value, Float): |
| return _int_or_halfint(float(value)) |
| raise ValueError("expecting integer or half-integer, got %s" % value) |
|
|
|
|
| def wigner_3j(j_1, j_2, j_3, m_1, m_2, m_3): |
| r""" |
| 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`): |
| |
| .. math:: |
| |
| \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} |
| |
| - invariant under space inflection, i.e. |
| |
| .. math:: |
| |
| \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 |
| `m_1 \in \{-|j_1|, \ldots, |j_1|\}`, |
| `m_2 \in \{-|j_2|, \ldots, |j_2|\}`, |
| `m_3 \in \{-|j_3|, \ldots, |j_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 |
| """ |
|
|
| j_1, j_2, j_3, m_1, m_2, m_3 = \ |
| map(_int_or_halfint, map(sympify, |
| [j_1, j_2, j_3, m_1, m_2, m_3])) |
|
|
| if m_1 + m_2 + m_3 != 0: |
| return S.Zero |
| a1 = j_1 + j_2 - j_3 |
| if a1 < 0: |
| return S.Zero |
| a2 = j_1 - j_2 + j_3 |
| if a2 < 0: |
| return S.Zero |
| a3 = -j_1 + j_2 + j_3 |
| if a3 < 0: |
| return S.Zero |
| if (abs(m_1) > j_1) or (abs(m_2) > j_2) or (abs(m_3) > j_3): |
| return S.Zero |
| if not (int_valued(j_1 - m_1) and \ |
| int_valued(j_2 - m_2) and \ |
| int_valued(j_3 - m_3)): |
| return S.Zero |
|
|
| maxfact = max(j_1 + j_2 + j_3 + 1, j_1 + abs(m_1), j_2 + abs(m_2), |
| j_3 + abs(m_3)) |
| _calc_factlist(int(maxfact)) |
|
|
| argsqrt = Integer(_Factlist[int(j_1 + j_2 - j_3)] * |
| _Factlist[int(j_1 - j_2 + j_3)] * |
| _Factlist[int(-j_1 + j_2 + j_3)] * |
| _Factlist[int(j_1 - m_1)] * |
| _Factlist[int(j_1 + m_1)] * |
| _Factlist[int(j_2 - m_2)] * |
| _Factlist[int(j_2 + m_2)] * |
| _Factlist[int(j_3 - m_3)] * |
| _Factlist[int(j_3 + m_3)]) / \ |
| _Factlist[int(j_1 + j_2 + j_3 + 1)] |
|
|
| ressqrt = sqrt(argsqrt) |
| if ressqrt.is_complex or ressqrt.is_infinite: |
| ressqrt = ressqrt.as_real_imag()[0] |
|
|
| imin = max(-j_3 + j_1 + m_2, -j_3 + j_2 - m_1, 0) |
| imax = min(j_2 + m_2, j_1 - m_1, j_1 + j_2 - j_3) |
| sumres = 0 |
| for ii in range(int(imin), int(imax) + 1): |
| den = _Factlist[ii] * \ |
| _Factlist[int(ii + j_3 - j_1 - m_2)] * \ |
| _Factlist[int(j_2 + m_2 - ii)] * \ |
| _Factlist[int(j_1 - ii - m_1)] * \ |
| _Factlist[int(ii + j_3 - j_2 + m_1)] * \ |
| _Factlist[int(j_1 + j_2 - j_3 - ii)] |
| sumres = sumres + Integer((-1) ** ii) / den |
|
|
| prefid = Integer((-1) ** int(j_1 - j_2 - m_3)) |
| res = ressqrt * sumres * prefid |
| return res |
|
|
|
|
| def clebsch_gordan(j_1, j_2, j_3, m_1, m_2, m_3): |
| r""" |
| 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: |
| |
| .. math:: |
| |
| \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 |
| """ |
| j_1 = sympify(j_1) |
| j_2 = sympify(j_2) |
| j_3 = sympify(j_3) |
| m_1 = sympify(m_1) |
| m_2 = sympify(m_2) |
| m_3 = sympify(m_3) |
|
|
| w = wigner_3j(j_1, j_2, j_3, m_1, m_2, -m_3) |
|
|
| return (-1) ** (j_1 - j_2 + m_3) * sqrt(2 * j_3 + 1) * w |
|
|
|
|
| def _big_delta_coeff(aa, bb, cc, prec=None): |
| r""" |
| Calculates the Delta coefficient of the 3 angular momenta for |
| Racah symbols. Also checks that the differences are of integer |
| value. |
| |
| Parameters |
| ========== |
| |
| aa : |
| First angular momentum, integer or half integer. |
| bb : |
| Second angular momentum, integer or half integer. |
| cc : |
| Third angular momentum, integer or half integer. |
| prec : |
| Precision of the ``sqrt()`` calculation. |
| |
| Returns |
| ======= |
| |
| double : Value of the Delta coefficient. |
| |
| Examples |
| ======== |
| |
| sage: from sage.functions.wigner import _big_delta_coeff |
| sage: _big_delta_coeff(1,1,1) |
| 1/2*sqrt(1/6) |
| """ |
|
|
| |
| |
| if not int_valued(aa + bb - cc): |
| raise ValueError("j values must be integer or half integer and fulfill the triangle relation") |
| if not int_valued(aa + cc - bb): |
| raise ValueError("j values must be integer or half integer and fulfill the triangle relation") |
| if not int_valued(bb + cc - aa): |
| raise ValueError("j values must be integer or half integer and fulfill the triangle relation") |
| if (aa + bb - cc) < 0: |
| return S.Zero |
| if (aa + cc - bb) < 0: |
| return S.Zero |
| if (bb + cc - aa) < 0: |
| return S.Zero |
|
|
| maxfact = max(aa + bb - cc, aa + cc - bb, bb + cc - aa, aa + bb + cc + 1) |
| _calc_factlist(maxfact) |
|
|
| argsqrt = Integer(_Factlist[int(aa + bb - cc)] * |
| _Factlist[int(aa + cc - bb)] * |
| _Factlist[int(bb + cc - aa)]) / \ |
| Integer(_Factlist[int(aa + bb + cc + 1)]) |
|
|
| ressqrt = sqrt(argsqrt) |
| if prec: |
| ressqrt = ressqrt.evalf(prec).as_real_imag()[0] |
| return ressqrt |
|
|
|
|
| def racah(aa, bb, cc, dd, ee, ff, prec=None): |
| r""" |
| 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: |
| |
| .. math:: |
| |
| \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 |
| """ |
| prefac = _big_delta_coeff(aa, bb, ee, prec) * \ |
| _big_delta_coeff(cc, dd, ee, prec) * \ |
| _big_delta_coeff(aa, cc, ff, prec) * \ |
| _big_delta_coeff(bb, dd, ff, prec) |
| if prefac == 0: |
| return S.Zero |
| imin = max(aa + bb + ee, cc + dd + ee, aa + cc + ff, bb + dd + ff) |
| imax = min(aa + bb + cc + dd, aa + dd + ee + ff, bb + cc + ee + ff) |
|
|
| maxfact = max(imax + 1, aa + bb + cc + dd, aa + dd + ee + ff, |
| bb + cc + ee + ff) |
| _calc_factlist(maxfact) |
|
|
| sumres = 0 |
| for kk in range(int(imin), int(imax) + 1): |
| den = _Factlist[int(kk - aa - bb - ee)] * \ |
| _Factlist[int(kk - cc - dd - ee)] * \ |
| _Factlist[int(kk - aa - cc - ff)] * \ |
| _Factlist[int(kk - bb - dd - ff)] * \ |
| _Factlist[int(aa + bb + cc + dd - kk)] * \ |
| _Factlist[int(aa + dd + ee + ff - kk)] * \ |
| _Factlist[int(bb + cc + ee + ff - kk)] |
| sumres = sumres + Integer((-1) ** kk * _Factlist[kk + 1]) / den |
|
|
| res = prefac * sumres * (-1) ** int(aa + bb + cc + dd) |
| return res |
|
|
|
|
| def wigner_6j(j_1, j_2, j_3, j_4, j_5, j_6, prec=None): |
| r""" |
| 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. |
| |
| .. math:: |
| |
| \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: |
| |
| .. math:: |
| |
| \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} |
| |
| - They are invariant under the exchange of the upper and lower |
| arguments in each of any two columns, i.e. |
| |
| .. math:: |
| |
| \begin{aligned} |
| \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) |
| \end{aligned} |
| |
| - 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]_. |
| |
| """ |
| j_1, j_2, j_3, j_4, j_5, j_6 = map(sympify, \ |
| [j_1, j_2, j_3, j_4, j_5, j_6]) |
| res = (-1) ** int(j_1 + j_2 + j_4 + j_5) * \ |
| racah(j_1, j_2, j_5, j_4, j_3, j_6, prec) |
| return res |
|
|
|
|
| def wigner_9j(j_1, j_2, j_3, j_4, j_5, j_6, j_7, j_8, j_9, prec=None): |
| r""" |
| 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) |
| 0.05555555555555555555555555555555555555555555555555555555555555555 |
| |
| >>> wigner_9j(1/2,1/2,0, 1/2,3/2,1, 0,1,1, prec=64) |
| 0.1666666666666666666666666666666666666666666666666666666666666667 |
| |
| 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]_. |
| """ |
| j_1, j_2, j_3, j_4, j_5, j_6, j_7, j_8, j_9 = map(sympify, \ |
| [j_1, j_2, j_3, j_4, j_5, j_6, j_7, j_8, j_9]) |
| imax = int(min(j_1 + j_9, j_2 + j_6, j_4 + j_8) * 2) |
| imin = imax % 2 |
| sumres = 0 |
| for kk in range(imin, int(imax) + 1, 2): |
| sumres = sumres + (kk + 1) * \ |
| racah(j_1, j_2, j_9, j_6, j_3, kk / 2, prec) * \ |
| racah(j_4, j_6, j_8, j_2, j_5, kk / 2, prec) * \ |
| racah(j_1, j_4, j_9, j_8, j_7, kk / 2, prec) |
| return sumres |
|
|
|
|
| def gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None): |
| r""" |
| Calculate the Gaunt coefficient. |
| |
| Explanation |
| =========== |
| |
| The Gaunt coefficient is defined as the integral over three |
| spherical harmonics: |
| |
| .. math:: |
| |
| \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} |
| |
| 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. |
| |
| 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.006895004219221134484332976156744208248842039317638217822322799675 |
| |
| 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 |
| |
| .. math:: |
| \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} |
| |
| - invariant under space inflection, i.e. |
| |
| .. math:: |
| 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. |
| """ |
| l_1, l_2, l_3, m_1, m_2, m_3 = [ |
| as_int(i) for i in (l_1, l_2, l_3, m_1, m_2, m_3)] |
|
|
| if l_1 + l_2 - l_3 < 0: |
| return S.Zero |
| if l_1 - l_2 + l_3 < 0: |
| return S.Zero |
| if -l_1 + l_2 + l_3 < 0: |
| return S.Zero |
| if (m_1 + m_2 + m_3) != 0: |
| return S.Zero |
| if (abs(m_1) > l_1) or (abs(m_2) > l_2) or (abs(m_3) > l_3): |
| return S.Zero |
| bigL, remL = divmod(l_1 + l_2 + l_3, 2) |
| if remL % 2: |
| return S.Zero |
|
|
| imin = max(-l_3 + l_1 + m_2, -l_3 + l_2 - m_1, 0) |
| imax = min(l_2 + m_2, l_1 - m_1, l_1 + l_2 - l_3) |
|
|
| _calc_factlist(max(l_1 + l_2 + l_3 + 1, imax + 1)) |
|
|
| ressqrt = sqrt((2 * l_1 + 1) * (2 * l_2 + 1) * (2 * l_3 + 1) * \ |
| _Factlist[l_1 - m_1] * _Factlist[l_1 + m_1] * _Factlist[l_2 - m_2] * \ |
| _Factlist[l_2 + m_2] * _Factlist[l_3 - m_3] * _Factlist[l_3 + m_3] / \ |
| (4*pi)) |
|
|
| prefac = Integer(_Factlist[bigL] * _Factlist[l_2 - l_1 + l_3] * |
| _Factlist[l_1 - l_2 + l_3] * _Factlist[l_1 + l_2 - l_3])/ \ |
| _Factlist[2 * bigL + 1]/ \ |
| (_Factlist[bigL - l_1] * |
| _Factlist[bigL - l_2] * _Factlist[bigL - l_3]) |
|
|
| sumres = 0 |
| for ii in range(int(imin), int(imax) + 1): |
| den = _Factlist[ii] * _Factlist[ii + l_3 - l_1 - m_2] * \ |
| _Factlist[l_2 + m_2 - ii] * _Factlist[l_1 - ii - m_1] * \ |
| _Factlist[ii + l_3 - l_2 + m_1] * _Factlist[l_1 + l_2 - l_3 - ii] |
| sumres = sumres + Integer((-1) ** ii) / den |
|
|
| res = ressqrt * prefac * sumres * Integer((-1) ** (bigL + l_3 + m_1 - m_2)) |
| if prec is not None: |
| res = res.n(prec) |
| return res |
|
|
|
|
| def real_gaunt(l_1, l_2, l_3, mu_1, mu_2, mu_3, prec=None): |
| r""" |
| Calculate the real Gaunt coefficient. |
| |
| Explanation |
| =========== |
| |
| The real Gaunt coefficient is defined as the integral over three |
| real spherical harmonics: |
| |
| .. math:: |
| \begin{aligned} |
| \operatorname{RealGaunt}(l_1,l_2,l_3,\mu_1,\mu_2,\mu_3) |
| &=\int Z^{\mu_1}_{l_1}(\Omega) |
| Z^{\mu_2}_{l_2}(\Omega) Z^{\mu_3}_{l_3}(\Omega) \,d\Omega \\ |
| \end{aligned} |
| |
| Alternatively, it can be defined in terms of the standard Gaunt |
| coefficient by relating the real spherical harmonics to the standard |
| spherical harmonics via a unitary transformation `U`, i.e. |
| `Z^{\mu}_{l}(\Omega)=\sum_{m'}U^{\mu}_{m'}Y^{m'}_{l}(\Omega)` [Homeier96]_. |
| The real Gaunt coefficient is then defined as |
| |
| .. math:: |
| \begin{aligned} |
| \operatorname{RealGaunt}(l_1,l_2,l_3,\mu_1,\mu_2,\mu_3) |
| &=\int Z^{\mu_1}_{l_1}(\Omega) |
| Z^{\mu_2}_{l_2}(\Omega) Z^{\mu_3}_{l_3}(\Omega) \,d\Omega \\ |
| &=\sum_{m'_1 m'_2 m'_3} U^{\mu_1}_{m'_1}U^{\mu_2}_{m'_2}U^{\mu_3}_{m'_3} |
| \operatorname{Gaunt}(l_1,l_2,l_3,m'_1,m'_2,m'_3) |
| \end{aligned} |
| |
| The unitary matrix `U` has components |
| |
| .. math:: |
| \begin{aligned} |
| U^\mu_{m} = \delta_{|\mu||m|}*(\delta_{m0}\delta_{\mu 0} + \frac{1}{\sqrt{2}}\big[\Theta(\mu)\big(\delta_{m\mu}+(-1)^{m}\delta_{m-\mu}\big) |
| +i \Theta(-\mu)\big((-1)^{m}\delta_{m\mu}-\delta_{m-\mu}\big)\big]) |
| \end{aligned} |
| |
| |
| where `\delta_{ij}` is the Kronecker delta symbol and `\Theta` is a step |
| function defined as |
| |
| .. math:: |
| \begin{aligned} |
| \Theta(x) = \begin{cases} 1 \,\text{for}\, x > 0 \\ 0 \,\text{for}\, x \leq 0 \end{cases} |
| \end{aligned} |
| |
| Parameters |
| ========== |
| |
| l_1, l_2, l_3, mu_1, mu_2, mu_3 : |
| Integer degree and order |
| |
| prec - precision, default: ``None``. |
| Providing a precision can |
| drastically speed up the calculation. |
| |
| Returns |
| ======= |
| |
| Rational number times the square root of a rational number. |
| |
| Examples |
| ======== |
| >>> from sympy.physics.wigner import real_gaunt |
| >>> real_gaunt(1,1,2,-1,1,-2) |
| sqrt(15)/(10*sqrt(pi)) |
| >>> real_gaunt(10,10,20,-9,-9,0,prec=64) |
| -0.00002480019791932209313156167176797577821140084216297395518482071448 |
| |
| It is an error to use non-integer values for `l` and `\mu`:: |
| real_gaunt(2.8,0.5,1.3,0,0,0) |
| Traceback (most recent call last): |
| ... |
| ValueError: l values must be integer |
| |
| real_gaunt(2,2,4,0.7,1,-3.4) |
| Traceback (most recent call last): |
| ... |
| ValueError: mu values must be integer |
| |
| Notes |
| ===== |
| |
| The real Gaunt coefficient inherits from the standard Gaunt coefficient, |
| the invariance under any permutation of the pairs `(l_i, \mu_i)` and the |
| requirement that the sum of the `l_i` be even to yield a non-zero value. |
| It also obeys the following symmetry rules: |
| |
| - zero for `l_1`, `l_2`, `l_3` not fulfilling the condition |
| `l_1 \in \{l_{\text{max}}, l_{\text{max}}-2, \ldots, l_{\text{min}}\}`, |
| where `l_{\text{max}} = l_2+l_3`, |
| |
| .. math:: |
| \begin{aligned} |
| l_{\text{min}} = \begin{cases} \kappa(l_2, l_3, \mu_2, \mu_3) & \text{if}\, |
| \kappa(l_2, l_3, \mu_2, \mu_3) + l_{\text{max}}\, \text{is even} \\ |
| \kappa(l_2, l_3, \mu_2, \mu_3)+1 & \text{if}\, \kappa(l_2, l_3, \mu_2, \mu_3) + |
| l_{\text{max}}\, \text{is odd}\end{cases} |
| \end{aligned} |
| |
| and `\kappa(l_2, l_3, \mu_2, \mu_3) = \max{\big(|l_2-l_3|, \min{\big(|\mu_2+\mu_3|, |
| |\mu_2-\mu_3|\big)}\big)}` |
| |
| - zero for an odd number of negative `\mu_i` |
| |
| Algorithms |
| ========== |
| |
| This function uses the algorithms of [Homeier96]_ and [Rasch03]_ to |
| calculate the value of the real Gaunt coefficient exactly. Note that |
| the formula used in [Rasch03]_ contains alternating sums over large |
| factorials and is therefore unsuitable for finite precision arithmetic |
| and only useful for a computer algebra system [Rasch03]_. However, this |
| function can in principle use any algorithm that computes the Gaunt |
| coefficient, so it is suitable for finite precision arithmetic in so far |
| as the algorithm which computes the Gaunt coefficient is. |
| """ |
| l_1, l_2, l_3, mu_1, mu_2, mu_3 = [ |
| as_int(i) for i in (l_1, l_2, l_3, mu_1, mu_2, mu_3)] |
|
|
| |
| if sum(1 for i in (mu_1, mu_2, mu_3) if i < 0) % 2: |
| return S.Zero |
| if (l_1 + l_2 + l_3) % 2: |
| return S.Zero |
| lmax = l_2 + l_3 |
| lmin = max(abs(l_2 - l_3), min(abs(mu_2 + mu_3), abs(mu_2 - mu_3))) |
| if (lmin + lmax) % 2: |
| lmin += 1 |
| if lmin not in range(lmax, lmin - 2, -2): |
| return S.Zero |
|
|
| kron_del = lambda i, j: 1 if i == j else 0 |
| s = lambda e: -1 if e % 2 else 1 |
|
|
| t = lambda x: 1 if x > 0 else 0 |
| A = lambda mu, m: t(-mu) * (s(m) * kron_del(m, mu) - kron_del(m, -mu)) |
| B = lambda mu, m: t(mu) * (kron_del(m, mu) + s(m) * kron_del(m, -mu)) |
| U = lambda mu, m: kron_del(abs(mu), abs(m)) * (kron_del(mu, 0) * kron_del(m, 0) + (B(mu, m) + I * A(mu, m))/sqrt(2)) |
|
|
| ugnt = 0 |
| for m1 in range(-l_1, l_1+1): |
| U1 = U(mu_1, m1) |
| for m2 in range(-l_2, l_2+1): |
| U2 = U(mu_2, m2) |
| U3 = U(mu_3,-m1-m2) |
| ugnt = ugnt + re(U1*U2*U3)*gaunt(l_1, l_2, l_3, m1, m2, -m1 - m2, prec=prec) |
|
|
| return ugnt |
|
|
|
|
| class Wigner3j(Function): |
|
|
| def doit(self, **hints): |
| if all(obj.is_number for obj in self.args): |
| return wigner_3j(*self.args) |
| else: |
| return self |
|
|
| def dot_rot_grad_Ynm(j, p, l, m, theta, phi): |
| r""" |
| Returns dot product of rotational gradients of spherical harmonics. |
| |
| Explanation |
| =========== |
| |
| This function returns the right hand side of the following expression: |
| |
| .. math :: |
| \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)) |
| |
| """ |
| j = sympify(j) |
| p = sympify(p) |
| l = sympify(l) |
| m = sympify(m) |
| theta = sympify(theta) |
| phi = sympify(phi) |
| k = Dummy("k") |
|
|
| def alpha(l,m,j,p,k): |
| return sqrt((2*l+1)*(2*j+1)*(2*k+1)/(4*pi)) * \ |
| Wigner3j(j, l, k, S.Zero, S.Zero, S.Zero) * \ |
| Wigner3j(j, l, k, p, m, -m-p) |
|
|
| return (S.NegativeOne)**(m+p) * Sum(Ynm(k, m+p, theta, phi) * alpha(l,m,j,p,k) / 2 \ |
| *(k**2-j**2-l**2+k-j-l), (k, abs(l-j), l+j)) |
|
|
|
|
| def wigner_d_small(J, beta): |
| """Return the small Wigner d matrix for angular momentum J. |
| |
| Explanation |
| =========== |
| |
| J : An integer, half-integer, or SymPy symbol for the total angular |
| momentum of the angular momentum space being rotated. |
| beta : A real number representing the Euler angle of rotation about |
| the so-called line of nodes. See [Edmonds74]_. |
| |
| Returns |
| ======= |
| |
| A matrix representing the corresponding Euler angle rotation( in the basis |
| of eigenvectors of `J_z`). |
| |
| .. math :: |
| \\mathcal{d}_{\\beta} = \\exp\\big( \\frac{i\\beta}{\\hbar} J_y\\big) |
| |
| such that |
| |
| .. math :: |
| d^{(J)}_{m',m}(\\beta) = \\mathtt{wigner\\_d\\_small(J,beta)[J-mprime,J-m]} |
| |
| The components are calculated using the general form [Edmonds74]_, |
| equation 4.1.15. |
| |
| 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 β¦ |
| |
| """ |
| M = [J-i for i in range(2*J+1)] |
| d = zeros(2*J+1) |
|
|
| |
| for i, Mi in enumerate(M): |
| for j, Mj in enumerate(M): |
|
|
| |
| sigmamax = min([J-Mi, J-Mj]) |
| sigmamin = max([0, -Mi-Mj]) |
|
|
| dij = sqrt(factorial(J+Mi)*factorial(J-Mi) / |
| factorial(J+Mj)/factorial(J-Mj)) |
| terms = [(-1)**(J-Mi-s) * |
| binomial(J+Mj, J-Mi-s) * |
| binomial(J-Mj, s) * |
| cos(beta/2)**(2*s+Mi+Mj) * |
| sin(beta/2)**(2*J-2*s-Mj-Mi) |
| for s in range(sigmamin, sigmamax+1)] |
|
|
| d[i, j] = dij*Add(*terms) |
|
|
| return ImmutableMatrix(d) |
|
|
|
|
| def wigner_d(J, alpha, beta, gamma): |
| """Return the Wigner D matrix for angular momentum J. |
| |
| 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 figure axis, line of nodes, |
| and vertical. See [Edmonds74]_, however note that the symbols alpha |
| and gamma are swapped in this implementation. |
| |
| Returns |
| ======= |
| |
| A matrix representing the corresponding Euler angle rotation (in the basis |
| of eigenvectors of `J_z`). |
| |
| .. math :: |
| \\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) |
| |
| such that |
| |
| .. math :: |
| \\mathcal{D}^{(J)}_{m',m}(\\alpha, \\beta, \\gamma) = |
| \\mathtt{wigner_d(J, alpha, beta, gamma)[J-mprime,J-m]} |
| |
| The components are calculated using the general form [Edmonds74]_, |
| equation 4.1.12, however note that the angles alpha and gamma are swapped |
| in this implementation. |
| |
| 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β β¦ |
| |
| """ |
| d = wigner_d_small(J, beta) |
| M = [J-i for i in range(2*J+1)] |
| |
| D = [[exp(I*Mi*alpha)*d[i, j]*exp(I*Mj*gamma) |
| for j, Mj in enumerate(M)] for i, Mi in enumerate(M)] |
| return ImmutableMatrix(D) |
|
|