What sphericart computes#

In the most basic form, spherical harmonics are defined as complex-valued functions of the polar coordinates \((\theta,\phi)\)

\[Y^m_l(\theta,\phi) \propto P^m_l(\cos \theta) e^{\mathrm{i} m \phi}\]

where \(P^m_l(x)\) are the associated Legendre polynomials. There are multiple conventions for choosing normalization and phases, and it is possible to reformulate the spherical harmonics in a real-valued form, which leads to even further ambiguity in the definitions.

Within sphericart we take an opinionated stance: we compute only real-valued harmonics, we express them as a function of the full Cartesian coordinates of a point in three dimensions \((x,y,z)\) and compute by default “scaled” versions \(\tilde{Y}^m_l(x, y, z)\) which correspond to homogeneous polynomials of the Cartesian coordinates:

\[\begin{split}\tilde{Y}_l^m(x, y, z) = r^l\,{Y}_l^m(x, y, z) = F_l^{|m|} Q_l^{|m|}(z, r) \times \begin{cases} s_{|m|}(x, y) & \text{if $m < 0$}\\ 1/\sqrt{2} & \text{if $m = 0$}\\ c_m(x, y) & \text{if $m > 0$} \end{cases}\end{split}\]

where

\[\begin{split}r =& \, \sqrt{x^2+y^2+z^2}, \quad r_{xy} = \sqrt{x^2+y^2}, \quad \\ s_m =& \, r_{xy}^m \, \sin{(m \arctan(x/r,y/r))}, \quad \\ c_m = & \, r_{xy}^m \, \cos{(m\arctan(x/r,y/r))},\label{eq:define-q}\quad \\ Q_l^m(z,r) =&\, r^l r_{xy}^{-m} \, P_l^m(z/r), \quad \\ F_l^m = &\, (-1)^m \sqrt{\frac{2l+1}{2\pi}\frac{(l-m)!}{(l+m)!}}.\end{split}\]

If we neglect some constant normalization factors, these correspond to the regular solid harmonics. See also the reference paper for further implementation details.

The radially normalized version of the spherical harmonics can also be computed by providing the appropriate flag when creating the sphericart calculators. These correspond to the real spherical harmonics as defined in the corresponding Wikipedia article. However, we recommend using the scaled versions, which are slightly faster and provide a more natural scaling if used together with a radial expansion.

The \(\tilde{Y}^m_l(x)\) are stored contiguously in memory, e.g. as \(\{ (l,m)=(0,0), (1,-1), (1,0), (1,1), (2,-2), \ldots \}\). With zero-based indexing of the arrays, the (l,m) term is stored at position l(l+1)+m.