Skip to content
Projects

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

NameDescription
GroundedStripFieldField 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 = method

orderattributeinstance 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.ndarray

Potential (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.ndarray

Zeta = exp(i pi z / L), as a complex array; positions is (2, N).