tree_d_3d.strip
Line charges between two grounded plates, by conformal mapping and the FMM.
Charges are infinite line charges along z (2D Cartesian electrostatics) in the
strip 0 < x < L between grounded plates at x = 0 and x = L, which
extend to infinity in y. The map
zeta = exp(i pi z / L), z = x + i y,sends the strip onto the upper half-plane and both plates onto the real axis. There, a grounded boundary needs a single image per charge, at the complex conjugate point with the opposite charge, so the strip’s Green’s function is
phi(z) = -2 k_e sum_j q_j ln| (zeta - zeta_j) / (zeta - conj(zeta_j)) |.That is one free-space line-charge sum over 2N sources, which
:meth:FlatQuadtree.fmm evaluates in O(N). The field follows from the
complex derivative, E_x - i E_y = 2 k_e W'(zeta) (i pi / L) zeta with
W = sum q log(zeta - zeta_j) - sum q log(zeta - conj(zeta_j)). Every
charge feels the field of all other charges and of all images, including its
own: the image force of the plates. In the mapped plane a charge’s own term
log(zeta - zeta_i) is not purely a self-interaction: it differs from
log(z - z_i) by a smooth part whose gradient, i pi / 2L, is added back.
The map compresses distances by |d zeta / dz| = pi |zeta| / L, which
changes by exp(pi Delta y / L) across the strip, so a softening length in
the physical plane has no fixed counterpart in the mapped plane. Softening is
therefore applied in the physical plane as a local correction: the strip’s
Green’s function is the free-space kernel plus a smooth harmonic part, and
softening only changes the free-space kernel near the charge, so pairs closer
than cutoff * softening get the difference between the softened and the
bare free-space interaction (the remainder beyond the cutoff is below 3% of
one pair’s field there). Coincident charges are an error either way.
Classes
| Name | Description |
|---|---|
GroundedStripField | Field and potential of line charges between plates at x = 0 and x = L. |
GroundedStripFieldclass#
class GroundedStripField(width: float, *, order: int = 14, theta: float = 0.5, leaf_capacity: int = 32, k_e: float = K_E, method: str = 'fmm', softening: float = 0.0, cutoff: float = 6.0)Field and potential of line charges between plates at x = 0 and x = L.
cutoffattributeinstance attribute#
cutoff = float(cutoff)k_eattributeinstance attribute#
k_e = float(k_e)leaf_capacityattributeinstance attribute#
leaf_capacity = int(leaf_capacity)methodattributeinstance attribute#
method = methodorderattributeinstance attribute#
order = int(order)softeningattributeinstance attribute#
softening = float(softening)thetaattributeinstance attribute#
theta = float(theta)widthattributeinstance attribute#
width = float(width)field_at_chargesmethod#
def field_at_charges(positions, charges, *, potential: bool = True) -> tuple[np.ndarray, np.ndarray]Potential (V) and field (V/m, shape (2, N)) acting on every charge.
positions has shape (2, N); charges are line charges per unit
length (C/m). With
potential=False only the field is computed (the potential is
returned as zeros), which is cheaper.
potentialmethod#
def potential(positions, charges, points) -> np.ndarrayPotential (V) at arbitrary points strictly between the plates.
probemethod#
def probe(positions, charges, points) -> tuple[np.ndarray, np.ndarray]Potential (V) and field (V/m, shape (2, M)) at points (2, M).
The points must lie strictly between the plates; they are probes, not charges, so no self term applies.
to_planemethod#
def to_plane(positions) -> np.ndarrayZeta = exp(i pi z / L), as a complex array; positions is (2, N).