API Reference
multipoles.MultipoleExpansion
Bases: object
Perform a multipole expansion for a given charge or mass distribution.
Determines the spherical multipole moments of the given distribution and can calculate the solution of the electrostatic or gravitational potential based on the multipole expansion.
Attributes:
| Name | Type | Description |
|---|---|---|
l_max |
int
|
The maximum multipole moment of the expansion. |
exterior |
bool
|
Whether this is an exterior expansion. |
interior |
bool
|
Whether this is an interior expansion. |
center |
ndarray
|
The expansion center. |
center_of_charge |
ndarray
|
The center of charge, weighted by the absolute values of the charges. |
total_charge |
float
|
The total charge. |
validity_radius |
float
|
The exterior expansion converges outside, the interior expansion inside the sphere of this radius about the expansion center. |
multipole_moments |
dict
|
The multipole moments q_lm (exterior) or I_lm (interior), with keys (l, m). |
dipole_moment
property
The dipole moment vector p = Σ q (r - center), about the expansion center.
quadrupole_moment
property
The traceless quadrupole moment tensor, about the expansion center.
Q_ij = Σ q (3 x_i x_j - r^2 δ_ij), with x = r - center, so that the potential is Φ = q / r + p·x / r^3 + Σ_ij Q_ij x_i x_j / (2 r^5) + ...
multipole_moments_array
property
The multipole moments q_lm as array of shape (l_max + 1, 2 l_max + 1).
Index it as [l, m], with negative m wrapping around as usual in Python.
Entries with |m| > l are zero.
__init__(charge_dist, l_max, exterior=None, interior=None, center=None, charge_tol=1e-06)
Create a MultipoleExpansion object for a given charge or mass distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
charge_dist
|
dict
|
Description of the charge distribution. For discrete charge distributions (point charges) the dict must contain exactly the following items:
For continuous charge distributions (charge density) the dict must contain exactly the following items:
|
required |
l_max
|
int
|
The maximum multipole moment to consider (0 = monopole, 1 = dipole, etc.). |
required |
exterior
|
bool
|
Whether to perform an exterior expansion (default).
If |
None
|
interior
|
bool
|
Whether to perform an interior expansion. Alternative to
|
None
|
center
|
array_like
|
The point (x, y, z) about which to expand. Defaults to the center of charge, weighted by the absolute values of the charges. |
None
|
charge_tol
|
float
|
Fraction of the total absolute charge of a continuous
distribution that may be ignored when determining the region where
the expansion is valid (see |
1e-06
|
The exterior expansion converges only outside the smallest sphere about the
center that contains all charge, the interior expansion only inside the largest
sphere about the center that contains no charge. The radius of this sphere is
stored in validity_radius. Evaluating the expansion at points where it does
not converge emits an ExpansionValidityWarning. To turn these warnings into
errors, use warnings.simplefilter("error", ExpansionValidityWarning).
Raises:
| Type | Description |
|---|---|
InvalidChargeDistributionException
|
If |
InvalidExpansionException
|
If |
ValueError
|
If |
Examples:
A discrete charge distribution: two point charges with positive and negative unit charge located on the z-axis:
>>> from multipoles import MultipoleExpansion
>>> charge_dist = {
... 'discrete': True,
... 'charges': [
... {'q': 1, 'xyz': (0, 0, 1)},
... {'q': -1, 'xyz': (0, 0, -1)},
... ],
... }
>>> Phi = MultipoleExpansion(charge_dist, l_max=2)
A continuous charge distribution: the same charges, smeared out as gaussians on a cubic grid of edge length 16 centered at the origin:
>>> import numpy as np
>>> x, y, z = [np.linspace(-8, 8, 81)] * 3
>>> XYZ = np.meshgrid(x, y, z, indexing='ij')
>>> def gaussian(XYZ, xyz0, sigma):
... g = np.ones_like(XYZ[0])
... for k in range(3):
... g *= np.exp(-(XYZ[k] - xyz0[k])**2 / sigma**2)
... return g * (sigma**2 * np.pi)**-1.5
>>> rho = gaussian(XYZ, (0, 0, 1), 1.5) - gaussian(XYZ, (0, 0, -1), 1.5)
>>> Phi = MultipoleExpansion({'discrete': False, 'rho': rho, 'xyz': XYZ}, l_max=2)
Evaluate the potential at arbitrary points with Phi(x, y, z) or on the
grid points of a continuous distribution with Phi[...], and the field
with Phi.field(x, y, z). The examples of these methods use Phi and
gaussian from here.
__call__(*xyz, l_max=None)
Evaluate the multipole expansion at points with given coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*xyz
|
float | array_like
|
The x, y, z coordinates of the points where to evaluate the expansion. If three numbers are given, the expansion is evaluated at the single point (x, y, z). If arrays are given, it is evaluated at each point (x[i], y[i], z[i]). Arrays may have any shape; numbers and arrays are broadcast against each other. |
()
|
l_max
|
int
|
Only use contributions up to this angular momentum.
Defaults to the |
None
|
Returns:
| Type | Description |
|---|---|
float | ndarray
|
The value of the potential: a float for a single point, otherwise an array of the broadcast shape of the coordinates. |
Warns:
| Type | Description |
|---|---|
ExpansionValidityWarning
|
If some of the points lie where the expansion does not converge. |
Examples:
>>> value = Phi(30.5, 30.6, 30.7)
>>> value = Phi(30.5, 30.6, 30.7, l_max=1) # monopole and dipole only
>>> values = Phi(np.linspace(10, 20, 5), 0, 0) # 5 points on the x-axis
__getitem__(key)
Evaluate the multipole expansion on grid points of the charge distribution.
Only available for continuous charge distributions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
index expression | array_like
|
Slices, indices or a boolean mask
selecting the points of the grid |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The values of the multipole expansion, in the shape defined
by |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the charge distribution is discrete. |
Warns:
| Type | Description |
|---|---|
ExpansionValidityWarning
|
If some of the points lie where the expansion does not converge. |
Examples:
>>> x, y, z = [np.linspace(-8, 8, 81)] * 3
>>> X, Y, Z = np.meshgrid(x, y, z, indexing='ij')
>>> rho = gaussian((X, Y, Z), (0, 0, 0), 1.5)
>>> mpe = MultipoleExpansion({'discrete': False, 'rho': rho, 'xyz': (X, Y, Z)}, l_max=3)
Evaluate on the plane z = -8 (an 81x81 array):
>>> plane = mpe[:, :, 0]
Evaluate only on the boundary of the grid, using a boolean mask:
>>> mask = np.ones_like(rho, dtype=bool)
>>> mask[1:-1, 1:-1, 1:-1] = False
>>> boundary_values = np.zeros_like(rho)
>>> boundary_values[mask] = mpe[mask]
field(*xyz, l_max=None)
Evaluate the field E = -∇Φ of the multipole expansion.
The derivatives are computed analytically from the multipole moments.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*xyz
|
float | array_like
|
The x, y, z coordinates of the points, as for
|
()
|
l_max
|
int
|
Only use contributions up to this angular momentum,
as for |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
The field components (E_x, E_y, E_z), stacked along the first axis: shape (3,) for a single point, otherwise (3, *shape) where shape is the broadcast shape of the coordinates. |
Warns:
| Type | Description |
|---|---|
ExpansionValidityWarning
|
If some of the points lie where the expansion does not converge. |
Examples:
>>> Ex, Ey, Ez = Phi.field(30.5, 30.6, 30.7)
>>> E = Phi.field(np.linspace(10, 20, 5), 0, 0) # shape (3, 5)
is_valid(*xyz)
Check where the multipole expansion converges.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*xyz
|
float | array_like
|
The x, y, z coordinates of the points, as for
|
()
|
Returns:
| Type | Description |
|---|---|
bool | ndarray
|
Whether the expansion converges at each point, i.e.
whether the point lies outside (exterior expansion) or inside (interior
expansion) the sphere of radius |
Examples:
>>> X, Y, Z = Phi.external_coords
>>> valid = Phi.is_valid(X, Y, Z) # boolean mask of the grid
>>> values = np.full(valid.shape, np.nan)
>>> values[valid] = Phi[valid]
multipoles.ExpansionValidityWarning
Bases: UserWarning
Emitted when the expansion is evaluated at points where it does not converge.
multipoles.InvalidChargeDistributionException
Bases: Exception
Raised when the charge distribution is malformed or cannot be expanded, e.g. because keys are missing, its total absolute charge is zero, or the grid is invalid.
multipoles.InvalidExpansionException
Bases: Exception
Raised when the requested expansion is contradictory or impossible, e.g. an interior expansion with charge at the expansion center.