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.
evaluateSr08 · src/physics/reference/fields.ts · this site’s source, as built · sha256:43dfe57d5385e4353a8cd2585d794915b8880066aaea05223810c6c3b3daf7e0
This function computes the listed outputs when it runs.
In words
It transforms the fields, transforms the charge's velocity, and computes the Lorentz force in both descriptions, alongside the two field invariants that must come out the same in each. Everything a reader sees on this page comes from one call: the stationary and moving fields, the stationary and moving velocities, the transverse force in the laboratory and in the comoving frame, and the Lorentz factor that relates them.
Implementation
export function evaluateSr08(input: Sr08Input): Sr08Snapshot {
const c = C_SI;
const v = input.boost;
const eventId = "event-test-charge-0";
const packScalar = (
key: keyof typeof SR08_ROWS,
make: (id: string, unit: string, kind: string, owner: string) => ScientificResult,
) => {
const r = SR08_ROWS[key];
return make(r[0], r[1], r[2], r[3]);
};
const refuseAll = (reason: string, condition: string): Sr08Snapshot => {
const out = (key: keyof typeof SR08_ROWS) =>
packScalar(key, (id, unit, kind, owner) =>
asOutside(id, unit, kind, owner, condition, reason),
);
return Object.freeze({
beta: v / c,
gamma: Number.NaN,
electricFieldStationary: out("Em"),
electricFieldMoving: out("Ec"),
magneticFieldStationary: out("Bm"),
magneticFieldMoving: out("Bc"),
fieldInvariantEDotB: out("id"),
fieldInvariantE2MinusC2B2: out("iv"),
lorentzFactor: out("g"),
chargeVelocityStationary: out("um"),
chargeVelocityMoving: out("uc"),
transverseForceLaboratory: out("Fm"),
transverseForceComoving: out("Fc"),
eventId,
});
};
const inputsValid = [
input.electricField.x,
input.electricField.y,
input.electricField.z,
input.magneticField.x,
input.magneticField.y,
input.magneticField.z,
input.chargeVelocity.x,
input.chargeVelocity.y,
input.chargeVelocity.z,
input.boost,
input.testCharge,
].every(Number.isFinite);
if (!inputsValid) {
return refuseAll(
"All field, velocity, boost, and charge inputs must be finite numbers.",
"finite inputs",
);
}
if (Math.abs(v) >= c) {
return refuseAll("Observer boost speed must satisfy |v| < c.", "|v| < c");
}
const uSpeed2 =
input.chargeVelocity.x * input.chargeVelocity.x +
input.chargeVelocity.y * input.chargeVelocity.y +
input.chargeVelocity.z * input.chargeVelocity.z;
if (uSpeed2 >= c * c) {
return refuseAll("Test charge speed must satisfy |u| < c.", "|u| < c");
}
const beta = v / c;
const g = gamma(beta);
if (g.status !== "value") {
return refuseAll("Lorentz factor undefined for |v| >= c.", "|v| < c");
}
const γ = g.value;
const E0 = input.electricField;
const B0 = input.magneticField;
const u0 = input.chargeVelocity;
const q = input.testCharge;
// Transformed fields under boost v along x
const transformedSI = transformSI({ E: E0, B: B0, boost: v, c });
const Eprime = transformedSI.E;
const Bprime = transformedSI.B;
// Invariants
const inv0 = fieldInvariants(E0, B0, c);
// Transformed velocity of test charge
const uprime = transformVelocity3D(u0, v, c);
// Forces
const F_lab = lorentzForce(q, E0, B0, u0);
const F_comoving = lorentzForce(q, Eprime, Bprime, uprime);
const valScalar = (key: keyof typeof SR08_ROWS, val: number) =>
packScalar(key, (id, unit, kind, owner) => asValue(id, unit, kind, owner, val));
const valVec = (key: keyof typeof SR08_ROWS, vec: Vec3) =>
packScalar(key, (id, unit, kind, owner) => asVectorValue(id, unit, kind, owner, vec));
return Object.freeze({
beta,
gamma: γ,
electricFieldStationary: valVec("Em", E0),
electricFieldMoving: valVec("Ec", Eprime),
magneticFieldStationary: valVec("Bm", B0),
magneticFieldMoving: valVec("Bc", Bprime),
fieldInvariantEDotB: valScalar("id", inv0.eDotB),
fieldInvariantE2MinusC2B2: valScalar("iv", inv0.e2MinusC2B2),
lorentzFactor: valScalar("g", γ),
chargeVelocityStationary: valVec("um", u0),
chargeVelocityMoving: valVec("uc", uprime),
transverseForceLaboratory: valVec("Fm", F_lab),
transverseForceComoving: valVec("Fc", F_comoving),
eventId,
});
}