Annus Mirabilis · Interactive critical edition in preparation
Charge and current density
Boost a current-carrying wire and see a charge density appear.
Special relativity §9
Charge and current density in moving frames
Static worked example
Model note
- Charge density (stationary system) (
chargeDensityStationary), Charge density (moving system) (chargeDensityMoving), Current density (stationary system) (currentDensityStationary) and Current density (moving system) (currentDensityMoving): Host calculation, by the site's own reference code. Computed infields.transformChargeCurrent. - Four-current invariant (cρ)² − |J|² (
fourCurrentInvariant) and Four-current invariant (cρ)² − |J|², normalized (fourCurrentInvariantNormalized): Host calculation, by the site's own reference code. Computed infields.fourCurrentInvariants. - Lorentz factor (
lorentzFactor): Host calculation, by the site's own reference code. Computed inkinematics.gamma. - Continuity residual ∂ρ/∂t + div J in K (
continuityResidualStationary) and Continuity residual ∂ρ/∂t + div J in k (continuityResidualMoving): Host calculation, by the site's own reference code. Computed infields.gaussianPulseContinuity. - Charge on the loop's top leg (+x), in k (
loopLegChargePositive), Charge on the loop's bottom leg (−x), in k (loopLegChargeNegative) and Total charge on the loop, in k (loopTotalCharge): Host calculation, by the site's own reference code. Computed infields.currentLoopCharges. - Total charge on the sphere, Q, in K (
sphereTotalChargeStationary) and Total charge on the sphere, Q, in k (sphereTotalChargeMoving): Host calculation, by the site's own reference code. Computed infields.sphereTotalCharge. - Computed from the settings last applied (settings revision 1, result 1).
- Not modeled: microscopic lattice dynamics and thermal vibrations; self-inductance and transient current startup; radiation reaction from accelerated charges; material resistance and Joule heating; finite wire thickness effects; gravitational fields and general relativistic curvature.
Predict before the numbers
A neutral wire in the laboratory carries a current in the +x direction. Described from a frame moving in the +x direction at 0.6c, is the wire still electrically neutral?
The result appears when you choose, say you have one in mind, or skip.
A neutral wire carrying a current
v = 0.60c, γ = 1.25
Laboratory frame K
ρ = 0 C/m³, Jx = 1 A/m²
Ions and electrons are equally spaced, so the wire is neutral. The electrons drift left, which is a current to the right.
Frame k, moving at v = 0.60c
ρ′ = −2.5017 × 10⁻⁹ C/m³, J′x = 1.25 A/m²
Seen from k, the whole wire moves left and both rows close up by γ = 1.25. The electrons close up very slightly more than the ions, so the wire carries a net negative charge. The drawing exaggerates the difference to one electron; at a real drift speed it is far smaller.
Worked example: in the laboratory the charge density is 0 C/m³ (neutral); described from the frame moving at 0.6c it is −2.5 × 10⁻⁹ C/m³ (negatively charged).
| Quantity | Stationary frame (K) | Moving frame (k) | Unit | Lorentz transformation law |
|---|---|---|---|---|
| Charge density ρ | 0 | −2.5017 × 10⁻⁹ | C/m³ | ρ′ = γ(ρ − vJx/c²) |
| Current density Jx | (1, 0, 0) | (1.25, 0, 0) | A/m² | J′x = γ(Jx − vρ) |
| Lorentz factor γ | 1.25 | 1 | 1 / √(1 − v²/c²) | |
| Four-current invariant (cρ)² − |J|² | −1 | A²/m⁴ | Exact scalar invariant across all frames | |
A wire carrying a current, with no net charge for an observer standing beside it, has a net charge for an observer moving along it. Charge and current mix under a change of frame, while the total charge of a body stays the same.
§9 takes the Maxwell–Hertz equations with convection currents, in which ρ is 4π times the density of electricity and (ux, uy, uz) its velocity. For charges bound to small rigid bodies, ions and electrons, these equations are the foundation of Lorentz's electrodynamics of moving bodies. Transforming them by §3 and §6, Einstein finds the same equations in k, provided the velocity of the charges transforms by the addition theorem of §5 and the density by ρ′ = β(1 − v ux/V²)ρ. So Lorentz's foundation agrees with the principle of relativity, and a charged body whose charge does not change in its own frame keeps a constant charge seen from K as well. The lab's default is a neutral conductor carrying 1 A/m² along x, seen from a frame moving at 0.6c along the current. In that frame the current density is 1.25 A/m², and the conductor carries a net charge density of −2.50 × 10−9 C/m³ where the stationary observer found none. For a rectangular loop carrying 1 A, 1 m long, the two legs parallel to the motion pick up ±2.00 × 10−9 C, and the loop's total stays zero. The lab also checks two things the paper does not state in this form: (cρ)² − |J|² is −1 A²/m⁴ in both frames, and charge conservation, ∂ρ/∂t + div J = 0, holds in both.
Take γ = 1.25 at v = 0.6c. The conductor holds two kinds of charge: carriers that make up the current, and an equal and opposite charge at rest. Say the carriers move at 0.5c, as in the lab's default. For a current density of 1 A/m² their charge density is J/u = 1/(0.5 × 2.998 × 108) = 6.67 × 10−9 C/m³, and the charge at rest is −6.67 × 10−9 C/m³, so the sum in K is zero. Now apply §9's ρ′ = γ(1 − v ux/c²)ρ to each. For the charge at rest, ux = 0, so ρ′ = 1.25 × (−6.67 × 10−9) = −8.34 × 10−9 C/m³. For the carriers, v ux/c² = 0.6 × 0.5 = 0.3, so ρ′ = 1.25 × 0.7 × 6.67 × 10−9 = 5.84 × 10−9 C/m³. The sum is −2.50 × 10−9 C/m³. The two densities change differently because each depends on that charge's own velocity, through the factor 1 − v ux/c². The carrier speed cancels from the sum: in general the net density is −γvJ/c² = −1.25 × 0.6c × 1/c² = −0.75/c, the same −2.50 × 10−9 C/m³ whatever speed the carriers have. The current density becomes J′ = γ(J − vρ) = 1.25 × (1 − 0) = 1.25 A/m². Check the invariant: in K, (cρ)² − J² = 0 − 1 = −1; in k, (c × (−0.75/c))² − 1.25² = 0.5625 − 1.5625 = −1. Last, the loop. Its two legs along x carry the current in opposite directions. In k, a leg carrying +1 A has a charge per unit length of −γvI/c² and is shortened to 1/γ of its length, so its charge is −vIL/c² = −0.6c × 1 × 1/c² = −0.6/c = −2.00 × 10−9 C. The leg carrying the current the other way has +2.00 × 10−9 C, and the sum is zero, as §9's constancy of charge requires for a loop that is neutral in its own frame.
Modern qualifications
§9 writes ρ for 4π times the density of electricity and (ux, uy, uz) for its velocity, in the units of §6. It proves only that the transformed equations keep their form, with charge density and velocity transformed as stated, and draws from them the constancy of a body's charge; it does not write a four-current or an invariant, and it does not discuss the continuity equation. Joining charge and current density into one four-vector, with (cρ)² − |J|² unchanged, is the later language of Poincaré and Minkowski. That a wire carrying a current appears charged to a moving observer is a standard modern consequence, often used to explain magnetism from electrostatics and relativity, and the paper does not discuss it.
Show the code
The site’s own reference code for this law, in TypeScript. It computes the numbers above when the page runs it, and it is what the page uses wherever a FrankenSim result is not available.
evaluateSr12 · src/physics/reference/fields.ts · this site’s source, as built · sha256:2456d6085eed656243ff791b623bb875b6b857f37d0460ec80a5545dc81b1e9a
This function computes the listed outputs when it runs.
In words
It transforms the four-current, computes its invariant, evaluates the continuity residual in each frame, and totals the charge on a sphere and around a current loop. The heart of it is that charge is invariant while charge DENSITY is not: a sphere carries the same total charge in both descriptions, and the function returns the two totals separately so a reader can see them agree rather than being told they do.
Implementation
export function evaluateSr12(input: Sr12Input): Sr12Snapshot {
const c = C_SI;
const v = input.boost;
const eventId = "event-charge-current-0";
const packScalar = (
key: keyof typeof SR12_ROWS,
make: (id: string, unit: string, kind: string, owner: string) => ScientificResult,
) => {
const r = SR12_ROWS[key];
return make(r[0], r[1], r[2], r[3]);
};
const valScalar = (key: keyof typeof SR12_ROWS, num: number) =>
packScalar(key, (id, unit, kind, owner) => asValue(id, unit, kind, owner, num));
const valVector = (key: keyof typeof SR12_ROWS, vec: Vec3) =>
packScalar(key, (id, unit, kind, owner) => asVectorValue(id, unit, kind, owner, vec));
const refuseAll = (reason: string, condition: string): Sr12Snapshot => {
const out = (key: keyof typeof SR12_ROWS) =>
packScalar(key, (id, unit, kind, owner) =>
asOutside(id, unit, kind, owner, condition, reason),
);
return Object.freeze({
beta: v / c,
gamma: Number.NaN,
chargeDensityStationary: out("rhoM"),
chargeDensityMoving: out("rhoC"),
currentDensityStationary: out("JM"),
currentDensityMoving: out("JC"),
fourCurrentInvariant: out("inv"),
fourCurrentInvariantNormalized: out("invNorm"),
lorentzFactor: out("gamma"),
continuityResidualStationary: out("contM"),
continuityResidualMoving: out("contC"),
loopLegChargePositive: out("legPos"),
loopLegChargeNegative: out("legNeg"),
loopTotalCharge: out("loopTotal"),
sphereTotalChargeStationary: out("sphereM"),
sphereTotalChargeMoving: out("sphereC"),
eventId,
});
};
if (
![
input.boost,
input.chargeDensity,
input.currentDensity.x,
input.currentDensity.y,
input.currentDensity.z,
input.carrierVelocity.x,
input.carrierVelocity.y,
input.carrierVelocity.z,
input.sphereRadius,
input.sphereCharge,
input.loopCurrent,
input.loopLengthX,
input.loopLengthY,
input.pulseWidth,
input.pulseAmplitude,
].every(Number.isFinite)
) {
return refuseAll(
"All density, current, velocity and boost inputs must be finite numbers.",
"finite inputs",
);
}
const beta = v / c;
if (Math.abs(beta) > 0.95) {
return refuseAll("Observer boost speed must satisfy |v| <= 0.95c.", "|v| <= 0.95c");
}
const g = gamma(beta);
if (g.status !== "value") {
return refuseAll("Lorentz factor could not be evaluated.", "|v| < c");
}
const γ = g.value;
const rho0 = input.chargeDensity;
let J0: Vec3 = input.currentDensity;
if (input.mode === "convection") {
const uMagSq =
input.carrierVelocity.x ** 2 + input.carrierVelocity.y ** 2 + input.carrierVelocity.z ** 2;
if (uMagSq >= c * c) {
return refuseAll("Carrier velocity must satisfy |u| < c.", "|u| < c");
}
J0 = Object.freeze({
x: rho0 * input.carrierVelocity.x,
y: rho0 * input.carrierVelocity.y,
z: rho0 * input.carrierVelocity.z,
});
}
const transformed = transformChargeCurrent({ rho: rho0, J: J0, boost: v, c });
const invs = fourCurrentInvariants(rho0, J0, c);
// Mode-specific calculations
const loop = currentLoopCharges(input.loopCurrent, input.loopLengthX, input.loopLengthY, v, c);
const sphereQ0 = sphereTotalCharge(input.sphereRadius, rho0);
const sphereQPrime = sphereQ0; // Exact charge invariance
const pulse = gaussianPulseContinuity(
input.pulseAmplitude,
input.carrierVelocity.x,
input.pulseWidth,
0,
0,
v,
c,
);
return Object.freeze({
beta,
gamma: γ,
chargeDensityStationary: valScalar("rhoM", rho0),
chargeDensityMoving: valScalar("rhoC", transformed.rho),
currentDensityStationary: valVector("JM", J0),
currentDensityMoving: valVector("JC", transformed.J),
fourCurrentInvariant: valScalar("inv", invs.si),
fourCurrentInvariantNormalized: valScalar(
"invNorm",
(c * rho0) ** 2 / (c * c) - (J0.x ** 2 + J0.y ** 2 + J0.z ** 2) / (c * c),
),
lorentzFactor: valScalar("gamma", γ),
continuityResidualStationary: valScalar("contM", pulse.stationaryResidual || 0),
continuityResidualMoving: valScalar("contC", pulse.movingResidual || 0),
loopLegChargePositive: valScalar("legPos", loop.legChargePositive),
loopLegChargeNegative: valScalar("legNeg", loop.legChargeNegative),
loopTotalCharge: valScalar("loopTotal", loop.totalCharge),
sphereTotalChargeStationary: valScalar("sphereM", sphereQ0),
sphereTotalChargeMoving: valScalar("sphereC", sphereQPrime),
eventId,
});
}The site’s own reference code for this law, in TypeScript. It computes the numbers above when the page runs it, and it is what the page uses wherever a FrankenSim result is not available.
transformChargeCurrent · src/physics/reference/fields.ts · this site’s source, as built · sha256:4efbed0926134abf4e2db73308635313f2cfefb0971f46939053c1346f13dfad
This function computes the listed outputs when it runs.
In words
The transformed density is gamma times the density less the current along the boost over c squared; the transformed current along the boost is gamma times the current less the density times the velocity. The components across the boost pass through. Written side by side with the coordinate transformation the pattern is the same, which is the point of showing this function next to that one: a density and a current form a four-vector in the same way a time and a position do.
Implementation
export function transformChargeCurrent(input: {
rho: number;
J: Vec3;
boost: number;
c?: number;
}): Readonly<{
rho: number;
J: Vec3;
beta: number;
gamma: number;
}> {
const c = input.c ?? C_SI;
const v = input.boost;
const beta = v / c;
const g = gamma(beta);
if (g.status !== "value") {
return Object.freeze({
rho: Number.NaN,
J: Object.freeze({ x: Number.NaN, y: Number.NaN, z: Number.NaN }),
beta,
gamma: Number.NaN,
});
}
const γ = g.value;
const { rho, J } = input;
const rhoPrime = γ * (rho - (v * J.x) / (c * c));
const JprimeX = γ * (J.x - v * rho);
return Object.freeze({
rho: rhoPrime,
J: Object.freeze({
x: JprimeX,
y: J.y,
z: J.z,
}),
beta,
gamma: γ,
});
}The explanation
Full explanation
Charge density and current density transform together, as time and position do. A wire that is neutral in its own frame carries a charge density in a frame moving along it, and the lab shows how much.
Show every step of the investigation
Set the charge density, the current density and the boost, and read the transformed pair. Check the combination that every frame agrees on, then try a current whose carriers would need to move at light speed, which the lab refuses.
An explanatory model, not an observation of nature. This embed starts from the laboratory’s worked defaults, not a saved run. Presentation options change the surrounding guide, never the numerical inputs.