PolyhedronHarmonics#

class PolyhedronHarmonics(vertices: ndarray, faces: ndarray)#

Bases: object

Spherical harmonic coefficients of a constant-density polyhedron.

Werner’s exact recursion [1], summed over the tetrahedra each facet forms with the origin: exact for the polyhedron at every degree, so the only error is the truncation and the mesh itself. The mesh is validated and stored at construction; compute() runs the recursion.

For a constant density the fully normalized coefficients of reference radius \(R\) are volume integrals of the solid harmonics

\[\bar{c}_{nm} + i\,\bar{s}_{nm} = \frac{1}{2n+1} \left(\frac{r}{R}\right)^{n} \bar{P}_{nm}(\sin\phi)\, e^{i m \lambda}, \qquad \bar{C}_{nm} + i\,\bar{S}_{nm} = \frac{1}{V} \int_V \left(\bar{c}_{nm} + i\,\bar{s}_{nm}\right) dV.\]

Each \(\bar{c}_{nm}, \bar{s}_{nm}\) is a homogeneous polynomial of degree \(n\) in \((x, y, z)/R\), generated from \(\bar{c}_{00} = 1\) by

\[\begin{split}\bar{c}_{mm} + i\,\bar{s}_{mm} &= d_m\, (x + i y) \left(\bar{c}_{m-1,m-1} + i\,\bar{s}_{m-1,m-1}\right), \\ \bar{c}_{m+1,m} &= e_{m+1}\, z\, \bar{c}_{mm}, \\ \bar{c}_{nm} &= f_{nm}\, z\, \bar{c}_{n-1,m} - g_{nm}\, r^2\, \bar{c}_{n-2,m},\end{split}\]

and the same for \(\bar{s}_{nm}\), with \(d_1 = 1/\sqrt{3}\) and

\[d_m = \frac{2m-1}{\sqrt{2m(2m+1)}}, \quad e_n = \frac{2n-1}{\sqrt{2n+1}}, \quad f_{nm} = (2n-1) \sqrt{\frac{2n-1}{(2n+1)(n+m)(n-m)}}, \quad g_{nm} = \sqrt{\frac{(2n-3)(n+m-1)(n-m-1)}{(2n+1)(n+m)(n-m)}}.\]

The body is split into the tetrahedra \((\mathbf{0}, \mathbf{v}_0, \mathbf{v}_1, \mathbf{v}_2)\) on its facets. Inside one, \(\mathbf{r} = \alpha\mathbf{v}_0 + \beta\mathbf{v}_1 + \gamma\mathbf{v}_2\) and \(dV = \det[\mathbf{v}_0\ \mathbf{v}_1\ \mathbf{v}_2]\, d\alpha\, d\beta\, d\gamma\), so the recursion runs on polynomials in \((\alpha, \beta, \gamma)\) and each monomial integrates exactly over the unit simplex:

\[\int_{\alpha+\beta+\gamma \le 1} \alpha^i \beta^j \gamma^k\, d\alpha\, d\beta\, d\gamma = \frac{i!\, j!\, k!}{(i+j+k+3)!}.\]

compute() returns the sum without the \(1/V\), so \(\bar{C}_{00} = V\).

Parameters:
verticesnp.ndarray

(N, 3) body-fixed coordinates in km, centred on the centre of mass.

facesnp.ndarray

(M, 3) zero-based triangular facet indices.

Methods

compute(n_degree, ref_radius[, normalized])

Coefficients up to n_degree.

References

[1]

R. A. Werner, “Spherical harmonic coefficients for the potential of a constant-density polyhedron,” Computers & Geosciences, vol. 23, no. 10, pp. 1071-1077, 1997.

compute(n_degree: int, ref_radius: float, normalized: bool = True) → tuple#

Coefficients up to n_degree.

The returned coefficients still carry the body’s volume — C[0][0] is that volume — so divide the set by it for the conventional C00 = 1. ShapeHarmonics does this, along with the file I/O.

Parameters:
n_degreeint

Maximum degree and order.

ref_radiusfloat

Normalising radius, km.

normalizedbool

Fully normalised coefficients when True, raw when False.

Returns:
tuple

(Cnm, Snm), each a flattened (n_degree + 1)**2 row-major list.

n_facets: int#
n_vertices: int#