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.
evaluateSr11 · src/physics/reference/waves.ts · this site’s source, as built · sha256:1e4cadb9104f65489aad06ebe337527cec8d5de1ebd7919441142cbee73f8bcc
This function computes the listed outputs when it runs.
In words
The laboratory's evaluator for § 8's moving mirror. It takes the mirror's speed, the angle of incidence, the incident energy density and the mirror's area, and returns the frequency ratio, the cosine and degrees of the reflected angle, the amplitude ratio, the radiation pressure and force, the incident and reflected powers, the rate at which the light does work on the mirror, and the residual by which the energy account fails to balance. In the mirror's own rest frame it reports no work and equal powers, which is the check that the two descriptions agree.
Implementation
export function evaluateSr11(input: Sr11Input): Sr11EvaluationResult {
const beta = input.beta;
const phiDeg = input.incidentAngleDeg;
const phiRad = (phiDeg * Math.PI) / 180;
const u = input.incidentEnergyDensity ?? 1.0;
const Am = input.mirrorArea ?? 1.0;
const frame = input.frame ?? "lab";
const unitLayer = input.unitLayer ?? "si";
const c = C_SI; // the powers are published in W, so c is in m/s, not 1
if (!Number.isFinite(beta) || Math.abs(beta) >= 1) {
const reason = "Mirror speed beta must be in (-1, 1).";
const outside = (quantityId: string, unit: string, semanticKind: string): ScientificResult =>
Object.freeze({
quantityId,
unit,
semanticKind,
ownerId: OWNER_ID,
status: "outside-domain" as const,
condition: "superluminal-speed",
domainKind: "physical" as const,
reason,
boundary: { parameterId: "beta", value: 0.95 },
});
return Object.freeze({
beta,
incidentAngleDeg: phiDeg,
incidentAngleRad: phiRad,
incidentEnergyDensity: u,
mirrorArea: Am,
frame,
unitLayer,
frequencyRatio: Number.NaN,
cosPhiReflected: Number.NaN,
phiReflectedRad: Number.NaN,
phiReflectedDeg: Number.NaN,
amplitudeRatio: Number.NaN,
radiationPressure: Number.NaN,
radiationForce: Number.NaN,
incidentPower: Number.NaN,
reflectedPower: Number.NaN,
workRate: Number.NaN,
energyBalanceResidual: Number.NaN,
explanation: reason,
results: [
outside("frequencyRatio", "1", "ratio"),
outside("cosPhiReflected", "1", "cosine"),
outside("phiReflectedDeg", "deg", "angle"),
outside("amplitudeRatio", "1", "ratio"),
outside("radiationPressure", "Pa", "pressure"),
outside("radiationForce", "N", "force"),
outside("incidentPower", "W", "power"),
outside("reflectedPower", "W", "power"),
outside("workRate", "W", "power"),
outside("energyBalanceResidual", "W", "power"),
],
status: "outside-domain" as const,
reason,
});
}
const mmRes = movingMirror(beta, phiRad, { u, c, Am });
if (mmRes.status !== "value") {
const reason = mmRes.reason;
const makeStatusResult = (
quantityId: string,
unit: string,
semanticKind: string,
): ScientificResult => {
if (mmRes.status === "outside-domain") {
return Object.freeze({
quantityId,
unit,
semanticKind,
ownerId: OWNER_ID,
status: "outside-domain" as const,
condition: mmRes.condition,
domainKind: mmRes.domainKind,
reason,
boundary: { parameterId: "beta", value: 0.95 },
});
}
return Object.freeze({
quantityId,
unit,
semanticKind,
ownerId: OWNER_ID,
status: "not-applicable" as const,
reason,
});
};
return Object.freeze({
beta,
incidentAngleDeg: phiDeg,
incidentAngleRad: phiRad,
incidentEnergyDensity: u,
mirrorArea: Am,
frame,
unitLayer,
frequencyRatio: Number.NaN,
cosPhiReflected: Number.NaN,
phiReflectedRad: Number.NaN,
phiReflectedDeg: Number.NaN,
amplitudeRatio: Number.NaN,
radiationPressure: Number.NaN,
radiationForce: Number.NaN,
incidentPower: Number.NaN,
reflectedPower: Number.NaN,
workRate: Number.NaN,
energyBalanceResidual: Number.NaN,
explanation: reason,
results: [
makeStatusResult("frequencyRatio", "1", "ratio"),
makeStatusResult("cosPhiReflected", "1", "cosine"),
makeStatusResult("phiReflectedDeg", "deg", "angle"),
makeStatusResult("amplitudeRatio", "1", "ratio"),
makeStatusResult("radiationPressure", "Pa", "pressure"),
makeStatusResult("radiationForce", "N", "force"),
makeStatusResult("incidentPower", "W", "power"),
makeStatusResult("reflectedPower", "W", "power"),
makeStatusResult("workRate", "W", "power"),
makeStatusResult("energyBalanceResidual", "W", "power"),
],
status: mmRes.status,
reason,
});
}
let frequencyRatio: number;
let cosPhiReflected: number;
let phiReflectedRad: number;
let amplitudeRatio: number;
let radiationPressure: number;
let radiationForce: number;
let incidentPower: number;
let reflectedPower: number;
let workRate: number;
let energyBalanceResidual: number;
let explanation: string;
if (frame === "mirror") {
const ledger = mirrorFrameLedger(beta, phiRad, { I: u * c, Am, c }); // I is intensity, u·c
frequencyRatio = ledger.frequencyFactor;
cosPhiReflected = ledger.cosPhiPrime;
phiReflectedRad = ledger.phiPrimeRad;
amplitudeRatio = ledger.frequencyFactor;
radiationPressure = ledger.forcePrime / Am;
radiationForce = ledger.forcePrime;
incidentPower = ledger.incidentPower;
reflectedPower = ledger.reflectedPower;
workRate = 0;
energyBalanceResidual = 0;
explanation =
"In the mirror rest frame, reflection does no mechanical work and incident power equals reflected power.";
} else {
frequencyRatio = mmRes.frequencyRatio;
cosPhiReflected = mmRes.cosPhiReflected;
phiReflectedRad = mmRes.phiReflectedRad;
amplitudeRatio = mmRes.amplitudeRatio;
radiationPressure = mmRes.radiationPressure;
radiationForce = mmRes.radiationForce;
incidentPower = mmRes.incidentPower;
reflectedPower = mmRes.reflectedPower;
workRate = mmRes.workRate;
energyBalanceResidual = mmRes.energyBalanceResidual;
explanation = mmRes.explanation ?? "";
}
const phiReflectedDeg = (phiReflectedRad * 180) / Math.PI;
const val = (
quantityId: string,
unit: string,
semanticKind: string,
v: number,
): ScientificResult =>
Object.freeze({
quantityId,
unit,
semanticKind,
ownerId: OWNER_ID,
status: "value" as const,
value: v,
});
const results: ScientificResult[] = [
val("frequencyRatio", "1", "ratio", frequencyRatio),
val("cosPhiReflected", "1", "cosine", cosPhiReflected),
val("phiReflectedDeg", "deg", "angle", phiReflectedDeg),
val("amplitudeRatio", "1", "ratio", amplitudeRatio),
val("radiationPressure", "Pa", "pressure", radiationPressure),
val("radiationForce", "N", "force", radiationForce),
val("incidentPower", "W", "power", incidentPower),
val("reflectedPower", "W", "power", reflectedPower),
val("workRate", "W", "power", workRate),
val("energyBalanceResidual", "W", "power", energyBalanceResidual),
];
return Object.freeze({
beta,
incidentAngleDeg: phiDeg,
incidentAngleRad: phiRad,
incidentEnergyDensity: u,
mirrorArea: Am,
frame,
unitLayer,
frequencyRatio,
cosPhiReflected,
phiReflectedRad,
phiReflectedDeg,
amplitudeRatio,
radiationPressure,
radiationForce,
incidentPower,
reflectedPower,
workRate,
energyBalanceResidual,
explanation,
results,
status: "value" as const,
});
}