Light quanta · Sections 3-4

A spectrum has an entropy. Compressing it costs the same way a gas does.

Within the regime where Wien's law holds, how does the entropy of monochromatic radiation depend on the volume it occupies, and what had to be fixed to get a definite answer?

Radiation entropy workbench

The radiation entropy workbench

Static worked example

Model note
  • Radiation energy (radiationEnergy): Host calculation, by the site's own reference code. Computed in lq04.acceptedInputs.
  • Temperature at the reference volume (initialTemperature), Temperature at the compared volume (finalTemperature), x = βν/T at the reference volume (initialX), x = βν/T at the compared volume (finalX), Spectral entropy density at the reference volume (initialSpectralEntropyDensity), Spectral entropy density at the compared volume (finalSpectralEntropyDensity), Radiation entropy (radiationEntropy), Radiation entropy change, summed from the entropy densities (radiationEntropyNumeric), Entropy-volume coefficient (entropyVolumeCoefficient), Entropy change with an unfixed constant C (a teaching comparison) (unfixedConstantDeltaS) and Extra entropy term from an unfixed constant C (unfixedConstantExtraTerm): Host calculation, by the site's own reference code. Computed in radiation.entropy.
  • Pointwise deviation of Wien's law at the reference volume (initialPointwiseDeviation) and Pointwise deviation of Wien's law at the compared volume (finalPointwiseDeviation): Host calculation, by the site's own reference code. Computed in radiation.spectra.
  • Effective independent count (effectiveIndependentCount): Host calculation, by the site's own reference code. Computed in lq04.derivedFromEnergyAndPlanckConstant.
  • Computed from the settings last applied (settings revision 1, result 1).
  • Not modeled: Radiation outside the Wien regime; Broad bands; How the constrained states are prepared; Walls, mirrors, adiabatic compression, or any mechanism that changes volume; Any interpretation of E/(hν) as a count of particles.

Within the regime where Wien's law holds, how does the entropy of monochromatic radiation depend on the volume it occupies, and what had to be fixed to get a definite answer?

Volume ratio V / V₀
Quick ratio presets
Experiment settings frequency, band width, reference volume and temperature, the dilute threshold
C(ν) teaching panel

Fixed energy E = 9.055615 × 10−9 J at ν = 6.00 × 1014 Hz in a 1.00 × 1012 Hz band.

ΔS = 0.000000 J/K (closed form); 0.000000 J/K (numerical S(V) − S(V₀)); coefficient E/(βν) = 3.144807 × 10−13 J/K; E/(hν) = 2.277774 × 1010 (never a count of particles).

Constrained-state comparison at fixed E, ν and dν
Reference (V₀)Compared (V)
Temperature T3000.000 K3000.000 K
x = βν / T9.5984869.598486
Pointwise deviation e−x6.783135 × 10−56.783135 × 10−5
Spectral entropy density sν3.333019 × 10−21 J/(m³ Hz K)3.333019 × 10−21 J/(m³ Hz K)

Not modeled: Radiation outside the Wien regime; Broad bands; How the constrained states are prepared; Walls, mirrors, adiabatic compression, or any mechanism that changes volume; Any interpretation of E/(hν) as a count of particles.

The same action without dragging, color, or a canvas

Every action here is typed text entry and a text result: choose half, same, or double, or type any volume ratio, and read the entropy-change sentence and the state table above. No control depends on color, drag gestures, or a canvas.

When faint light of one colour is given more room at the same energy, its entropy rises by the same logarithmic law as an ideal gas that expands. That shared law is the clue the paper follows next.

Section 3 turns a radiation law into an entropy: at fixed energy, the entropy S = v∫φ(ρ, ν)dν is a maximum, and with dS = dE/T this gives ∂φ/∂ρ = 1/T, where φ vanishes when the density ρ is zero. Section 4 takes Wien's law, ρ = αν³e−βν/T, which experiment had confirmed for large ν/T, solves it for 1/T and integrates. For radiation of energy E in a narrow band from ν to ν + dν filling a volume v, the dependence on volume is S − S0 = (E/βν) ln(v/v0). The instrument holds E, ν and dν fixed, lets you choose the volume ratio, and refuses a state dense enough for Wien's law to fail.

Modern qualifications

Einstein printed lg for the natural logarithm and used β for the constant in Wien's exponent, so his coefficient E/βν is, in modern notation, kBE/(hν), since β = h/kB. He said plainly that Wien's law is not exactly valid and that his results hold only within certain limits. The comparison with an ideal gas or a dilute solution is his own sentence at the end of Section 4; reading the coefficient in terms of independent energy quanta of size Rβν/N comes only in Section 6, after the probability argument of Section 5. Planck's formula of 1901 was already known, and Einstein works in its Wien limit on purpose.

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.

wienTemperatureFromDensity · src/physics/reference/radiation/entropy.ts · this site’s source, as built · sha256:f6372988e97fa21e082ae1348d5457c2d231c2b5c5d6b821e0a953164448a4d0

This function computes the listed outputs when it runs.

In words

Wien's law gives the density from the temperature; this inverts it. T = B nu / ln(A nu^3 / rho), with A = 8 pi h / c^3 and B = h / k_B, which are Einstein's printed alpha and beta written in modern constants. Fed back the density Wien's own law gives at 600 THz and 5800 K, it returns 5800 K. This inversion is what makes the entropy workbench possible: the entropy of radiation is defined through its temperature, and the temperature is not an input here but a reading.

Implementation

/** Wien temperature from spectral energy density: T = B*nu / ln(A*nu^3 / rho). */
export function wienTemperatureFromDensity(
  rho: number,
  nu: CyclicFrequency | number,
  setOrCoeffs?: ConstantSet | WienCoefficients,
): RadiationResult<number> {
  const quantityId = "temperature";
  const unit = "K";
  if (!Number.isFinite(rho) || rho <= 0) {
    return {
      status: "outside-domain",
      quantityId,
      unit,
      condition: "nonpositive-spectral-density",
      domainKind: "physical",
      reason: `Spectral density must be positive and finite (got ${rho}).`,
    };
  }
  if (!Number.isFinite(nu) || nu <= 0) {
    return {
      status: "outside-domain",
      quantityId,
      unit,
      condition: "nonpositive-frequency",
      domainKind: "physical",
      reason: `Frequency must be positive and finite (got ${nu}).`,
    };
  }

  const { A, B } = resolveCoefficients(setOrCoeffs);
  const maxDensity = A * nu ** 3;
  if (rho >= maxDensity) {
    return {
      status: "outside-domain",
      quantityId,
      unit,
      condition: "nonpositive-implied-temperature",
      domainKind: "model",
      reason: `Spectral density ${rho} exceeds Wien prefactor A*nu^3 (${maxDensity}), implying nonpositive temperature.`,
    };
  }

  const x = Math.log(maxDensity / rho);
  const T = (B * nu) / x;

  return {
    status: "value",
    quantityId,
    unit,
    value: T,
    linearRepresentable: true,
  };
}

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.

wienSpectralEntropyDensity · src/physics/reference/radiation/entropy.ts · this site’s source, as built · sha256:ae060f5f571edb75b002d62554511e795af409405e09c16441b29ab59964c00a

This function computes the listed outputs when it runs.

In words

s_nu = -(rho / (B nu)) times (ln(rho / (A nu^3)) - 1), which is what you get by integrating the inverse temperature of the line above with respect to the energy. It is the expression paragraph 4 arrives at, and the whole of paragraph 6 is what happens when its volume dependence is read as a probability. At 600 THz with the Wien density for 5800 K it returns 1.930 times 10^-19 J per cubic metre per hertz per kelvin.

Implementation

/**
 * Wien spectral entropy density s_nu = -(rho / (B*nu)) * [ln(rho / (A*nu^3)) - 1] in J m^-3 Hz^-1 K^-1.
 */
export function wienSpectralEntropyDensity(
  rho: number,
  nu: CyclicFrequency | number,
  setOrCoeffs?: ConstantSet | WienCoefficients,
): RadiationResult<number> {
  const quantityId = "spectralEntropyDensity";
  const unit = "J/(m^3 Hz K)";

  if (rho === 0) {
    return {
      status: "analytic-limit",
      quantityId,
      unit,
      value: 0,
      description: "Entropy density vanishes continuously at zero radiation density.",
      representation: { kind: "coefficient", value: 0 },
    };
  }

  if (!Number.isFinite(rho) || rho < 0) {
    return {
      status: "outside-domain",
      quantityId,
      unit,
      condition: "negative-spectral-density",
      domainKind: "physical",
      reason: `Spectral density must be non-negative (got ${rho}).`,
    };
  }
  if (!Number.isFinite(nu) || nu <= 0) {
    return {
      status: "outside-domain",
      quantityId,
      unit,
      condition: "nonpositive-frequency",
      domainKind: "physical",
      reason: `Frequency must be positive (got ${nu}).`,
    };
  }

  const { A, B } = resolveCoefficients(setOrCoeffs);
  const maxDensity = A * nu ** 3;
  if (rho >= maxDensity) {
    return {
      status: "outside-domain",
      quantityId,
      unit,
      condition: "outside-wien-regime",
      domainKind: "model",
      reason: `Spectral density ${rho} exceeds A*nu^3 (${maxDensity}), outside Wien domain.`,
    };
  }

  // s_nu = -(rho / (B*nu)) * (ln(rho / (A*nu^3)) - 1)
  const lnRatio = Math.log(rho / maxDensity);
  const sNu = -(rho / (B * nu)) * (lnRatio - 1);

  return {
    status: "value",
    quantityId,
    unit,
    value: sNu,
    linearRepresentable: true,
  };
}

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.

radiationEntropyVolumeChange · src/physics/reference/radiation/entropy.ts · this site’s source, as built · sha256:821c6127e12fddad3c4735dfa040ffea7a9c55b477e04b7b8ece97c9d01873b6

This function computes the listed outputs when it runs.

In words

Delta S = (E / (B nu)) times ln(V / V0). The shape is the whole argument: an entropy that depends on volume only through a logarithm, with a coefficient that does not depend on the volume at all. Alongside the change it returns the temperatures and the dimensionless x at both volumes, so a reader can see that expanding the box at fixed energy cools it. Measured for 1 nJ in a 1 THz band at 600 THz, doubling a cubic centimetre: Delta S = 2.407 times 10^-14 J/K, with the temperature falling from 5884 K to 5154 K.

Implementation

/**
 * Radiation entropy change upon volume expansion/compression at constant E and narrow band dNu.
 * Delta S = (E / (B * nu)) * ln(V / V0).
 */
export function radiationEntropyVolumeChange(
  params: RadiationEntropyVolumeChangeParams,
  setOrCoeffs?: ConstantSet | WienCoefficients,
  options: { epsilonW?: number; maxDeltaNuRatio?: number } = {},
): RadiationEntropyVolumeChangeResult {
  const { E, nu, dNu, V, V0 } = params;
  const quantityId = "radiationEntropy";
  const unit = "J/K";
  const maxDeltaNuRatio = options.maxDeltaNuRatio ?? 0.01;
  const epsilonW = options.epsilonW ?? 0.01;

  if (dNu / nu > maxDeltaNuRatio) {
    return {
      status: "outside-domain",
      quantityId,
      unit,
      condition: "band-not-narrow",
      domainKind: "model",
      reason:
        "the band is not narrow: the entropy law integrates over a narrow band at fixed frequency",
    };
  }

  if (E <= 0 || V <= 0 || V0 <= 0 || nu <= 0 || dNu <= 0) {
    return {
      status: "outside-domain",
      quantityId,
      unit,
      condition: "nonpositive-parameters",
      domainKind: "physical",
      reason: "Energy, volume, frequency, and bandwidth must be strictly positive.",
    };
  }

  const { A, B } = resolveCoefficients(setOrCoeffs);
  const maxDensity = A * nu ** 3;

  const rho0 = E / (V0 * dNu);
  const rho1 = E / (V * dNu);

  if (rho0 >= maxDensity || rho1 >= maxDensity) {
    return {
      status: "outside-domain",
      quantityId,
      unit,
      condition: "outside-wien-regime",
      domainKind: "model",
      reason: "Radiation density exceeds Wien approximation threshold; approximation fails.",
    };
  }

  const x0 = Math.log(maxDensity / rho0);
  const x1 = Math.log(maxDensity / rho1);

  if (Math.exp(-x0) > epsilonW || Math.exp(-x1) > epsilonW) {
    return {
      status: "outside-domain",
      quantityId,
      unit,
      condition: "outside-wien-regime",
      domainKind: "model",
      reason: `Relative error of Wien approximation (e^-x = ${Math.max(Math.exp(-x0), Math.exp(-x1)).toPrecision(3)}) exceeds tolerance ${epsilonW}.`,
    };
  }

  const T0 = (B * nu) / x0;
  const T1 = (B * nu) / x1;

  const volumeRatio = V / V0;
  const effectiveCount = E / (B * nu);
  const deltaS = effectiveCount * Math.log(volumeRatio);

  return {
    status: "value",
    quantityId: "radiationEntropy",
    unit: "J/K",
    deltaS,
    deltaSModern: deltaS,
    effectiveIndependentCount: effectiveCount,
    initialTemperature: T0,
    finalTemperature: T1,
    initialX: x0,
    finalX: x1,
    volumeRatio,
    maxDeltaNuRatio,
    wienTolerance: epsilonW,
    linearRepresentable: true,
  };
}

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.

entropyWithUnfixedConstant · src/physics/reference/radiation/entropy.ts · this site’s source, as built · sha256:a42ddd67d2512e13a098f27a5197b950ee973e796d7510b1a41621a9606ca5b7

This function computes the listed outputs when it runs.

In words

Integrating the inverse temperature to get an entropy leaves a constant of integration that may depend on the frequency but not on the energy. Paragraph 4 fixes it; this function does not, and adds the term it leaves behind, dNu times C times (V - V0), to the correct Delta S. It returns both numbers and labels itself an adversarial derivation variant, not a model of radiation.

Implementation

/**
 * Deliberately wrong derivation variant retaining an unfixed integration constant C(nu).
 * Adds dNu * C * (V - V0) to Delta S.
 */
export function entropyWithUnfixedConstant(
  params: RadiationEntropyVolumeChangeParams & { C: number },
  setOrCoeffs?: ConstantSet | WienCoefficients,
): Readonly<{
  status: "value";
  deltaS: number;
  deltaSWithC: number;
  extraTerm: number;
  historicalStatus: "adversarial-derivation-variant";
  modelNote: string;
}> {
  const { E, nu, dNu, V, V0, C } = params;
  const { B } = resolveCoefficients(setOrCoeffs);
  const deltaS = (E / (B * nu)) * Math.log(V / V0);
  const extraTerm = dNu * C * (V - V0);
  const deltaSWithC = deltaS + extraTerm;

  return {
    status: "value",
    deltaS,
    deltaSWithC,
    extraTerm,
    historicalStatus: "adversarial-derivation-variant",
    modelNote: "adversarial derivation variant, not a model of radiation",
  };
}

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.

regimeRelativeErrors · src/physics/reference/radiation/spectra.ts · this site’s source, as built · sha256:a4b44ec160f4721a8ce8233a6c39adb4e6b2dc061a427db51151d9bddaee5917

This function computes the listed outputs when it runs.

In words

Everything turns on one dimensionless number, x = h nu / (k_B T). Wien's relative error is e to the minus x, so Wien is good where x is large, which is high frequency or low temperature. The classical error is (e^x - 1)/x - 1, which vanishes where x is small. The function returns both errors, the regime they put you in, and the value of x at which each error reaches its tolerance, one per cent by default. Measured at 600 THz and 5800 K: x = 4.96, Wien runs 0.70 per cent below Planck, and the classical law is 27.7 times too large.

Implementation

/**
 * Relative error analysis comparing Wien and Rayleigh-Jeans approximations to Planck's exact law.
 */
export function regimeRelativeErrors(
  nu: CyclicFrequency | number,
  T: number,
  set: ConstantSet,
  options: { epsilonW?: number; epsilonRJ?: number } = {},
): RegimeReport {
  const { h, kB } = getBasePhysicsConstants(set);
  const epsilonW = options.epsilonW ?? 0.01;
  const epsilonRJ = options.epsilonRJ ?? 0.01;

  const x = (h * nu) / (kB * T);
  const wienRelativeError = Math.exp(-x);

  // The classical (Rayleigh-Jeans) relative error, measured against Planck like Wien's above:
  // (u_classical - u_Planck) / u_Planck = (e^x - 1)/x - 1. It was computed as 1 - x/(e^x - 1),
  // which divides by u_classical instead: the two agree to first order at small x, but at
  // x = 5.76 that read 0.98 while the classical law is 54.8 times Planck's value, and it put the
  // 1% boundary at x = 0.020067 where the owning bead specifies 0.0198678. Past x = 700, e^x
  // exceeds binary64 and the error is reported as Infinity, which callers must show in words.
  let rayleighJeansRelativeError: number;
  if (x < 1e-7) {
    rayleighJeansRelativeError = x / 2;
  } else if (x > 700) {
    rayleighJeansRelativeError = Number.POSITIVE_INFINITY;
  } else {
    rayleighJeansRelativeError = Math.expm1(x) / x - 1;
  }

  const wienBoundaryX = Math.log(1 / epsilonW);

  // Solve (e^x - 1)/x - 1 = epsilonRJ, that is e^x - 1 = (1 + epsilonRJ) x, by Newton's method.
  // For small epsilonRJ, x ~ 2 * epsilonRJ - (2/3) * epsilonRJ^2.
  let rjBoundaryX = 2 * epsilonRJ;
  for (let iter = 0; iter < 20; iter++) {
    const fVal = Math.expm1(rjBoundaryX) - (1 + epsilonRJ) * rjBoundaryX;
    const dfVal = Math.exp(rjBoundaryX) - (1 + epsilonRJ);
    const step = fVal / dfVal;
    rjBoundaryX -= step;
    if (Math.abs(step) < 1e-12) break;
  }

  const wienAdmitted = wienRelativeError <= epsilonW;
  const rayleighJeansAdmitted = rayleighJeansRelativeError <= epsilonRJ;

  let regime: "wien" | "rayleigh-jeans" | "intermediate";
  if (wienAdmitted) {
    regime = "wien";
  } else if (rayleighJeansAdmitted) {
    regime = "rayleigh-jeans";
  } else {
    regime = "intermediate";
  }

  return {
    x,
    wienRelativeError,
    rayleighJeansRelativeError,
    regime,
    wienAdmitted,
    rayleighJeansAdmitted,
    wienBoundaryX,
    rayleighJeansBoundaryX: rjBoundaryX,
  };
}

The physical argument

Wien's variational argument (§3)

Einstein attributes the entropy argument to Wien and uses it to fix the temperature dependence of the spectral entropy density φ\varphi. Maximizing S=v∫φ(ϱ,ν) dνS = v\int\varphi(\varrho,\nu)\,d\nu at fixed energy, together with dS=dE/TdS = dE/T, gives:

∂φ∂ϱ=1T\frac{\partial\varphi}{\partial\varrho} = \frac{1}{T}
Explain this equation

Section 3 closes with the condition that fixes the integration constant: the entropy density φ\varphi vanishes when the radiation density ϱ\varrho is zero.

The dilute, narrow-band limit (§4)

Section 4 restricts to dilute monochromatic radiation obeying Wien's law, inverts it for the temperature, integrates the entropy density using the zero-density condition above, and integrates over a narrow band. The result is that the entropy of radiation of energy EE in volume vv depends on volume exactly the way the entropy of an ideal gas or a dilute solution does:

S−S0=Eβνln⁡vv0(printed "lg" is thenatural logarithm)\begin{gathered}S - S_0 = \frac{E}{\beta\nu}\ln\frac{v}{v_0} \\ (\text{printed "lg" is the} \\ \text{natural logarithm})\end{gathered}
Explain this equation

Only after this volume law is established does identifying β=h/kB\beta = h/k_B give the modern form ΔS=kB Ehνln⁡VV0\Delta S = k_B\,\frac{E}{h\nu}\ln\frac{V}{V_0}. The coefficient E/(hν)E/(h\nu) emerges from an entropy calculation; the workbench above never rounds it to an integer or calls it a count of particles.

Why the fixing condition matters

Had the integration constant C(ν)C(\nu) been left unfixed rather than set to zero by the boundary condition, it would contribute an extra term proportional to (V−V0)(V - V_0) that does not cancel and does not reproduce the volume law. The workbench's teaching panel above makes this concrete with an illustrative nonzero C(ν)C(\nu).

Epistemic boundary: a regime-limited approximation

Wien's law is an admitted approximation to the true (Planck) spectrum, accurate only where the radiation is dilute relative to the frequency and temperature in question. A state dense enough that Wien's law fails is not silently computed with a wrong answer; the workbench refuses it and states why, rather than presenting a number outside the regime the argument actually covers.

Embed this laboratory on another page. It starts from its worked defaults, not your current settings.