codexstefan-boltzmann-gross-and-net-power.py
stefan-boltzmann-gross-and-net-power.py
"""Plot emitted exitance and two-way enclosure exchange.
Run from _media; writes stefan-boltzmann-gross-and-net-power.png to CWD.
Tested with Python 3.14, matplotlib 3.10.7 and numpy 2.3.5.
All curves use stipulated model parameters, not experimental data.
"""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
SIGMA = 5.670374419e-8 # Approximate SI value, W m^-2 K^-4.
EPSILON, AREA, WALL_T = 0.8, 0.01, 300.0
def main():
plt.rcParams.update({"font.size": 11, "axes.spines.top": False,
"axes.spines.right": False, "figure.facecolor": "white",
"axes.facecolor": "white"})
temperature = np.linspace(200, 650, 451)
exitance = SIGMA * temperature**4
emitted = EPSILON * AREA * exitance
absorbed = EPSILON * AREA * SIGMA * WALL_T**4
net = emitted - absorbed
fig, (ax, bx) = plt.subplots(1, 2, figsize=(10.8, 4.8))
fig.subplots_adjust(left=0.085, right=0.98, bottom=0.21, top=0.82, wspace=0.30)
fig.suptitle("Emission grows as T⁴; net exchange subtracts absorbed power", fontsize=15, y=0.97)
ax.plot(temperature, exitance / 1000, color="#b35415", lw=2.5)
ax.set(title="Blackbody: total outward hemisphere",
xlabel="Absolute surface temperature T (K)",
ylabel="Radiant exitance Mᵦ (kW / m²)", xlim=(200, 650), ylim=(0, 10.5))
for t, xytext in [(300, (255, 2.0)), (600, (440, 8.4))]:
m = SIGMA * t**4 / 1000
ax.scatter(t, m, color="#b35415", zorder=4, s=35)
ax.annotate(f"{t} K: {m:.3f} kW / m²", xy=(t, m), xytext=xytext,
arrowprops={"arrowstyle": "->", "color": "#555555"}, fontsize=10)
ax.text(0.05, 0.95, "300 → 600 K: ×16 emission", transform=ax.transAxes, va="top", fontsize=10)
bx.plot(temperature, emitted, label="Emitted: εσAT⁴", color="#b35415", lw=2.5)
bx.axhline(absorbed, label="Absorbed: εσATₛ⁴", color="#24689d", lw=2, ls="--")
bx.plot(temperature, net, label="Net outward: εσA(T⁴ − Tₛ⁴)", color="#6c4292", lw=2.5)
bx.axhline(0, color="#777777", lw=0.8)
bx.axvline(WALL_T, color="#777777", lw=0.8, ls=":")
bx.scatter([WALL_T, 500], [0, EPSILON * AREA * SIGMA * (500**4 - WALL_T**4)],
color="#6c4292", zorder=5, s=35)
bx.annotate("Equal temperatures:\nnet = 0", xy=(300, 0), xytext=(335, 14),
arrowprops={"arrowstyle": "->", "color": "#555555"}, fontsize=10)
bx.annotate("500 K: net 24.68 W", xy=(500, EPSILON * AREA * SIGMA * (500**4 - WALL_T**4)),
xytext=(380, 38), arrowprops={"arrowstyle": "->", "color": "#555555"}, fontsize=10)
bx.set(title="Grey surface in black walls at Tₛ = 300 K",
xlabel="Absolute surface temperature T (K)", ylabel="Power (W)",
xlim=(200, 650), ylim=(-6, 85))
bx.legend(loc="upper left", frameon=False, fontsize=9)
for axis in (ax, bx):
axis.grid(alpha=0.18)
fig.text(0.5, 0.035, "Model curves • ε = 0.8, emitting area A = 0.01 m² • Full view of black isothermal walls",
ha="center", fontsize=10, color="#444444")
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=120,
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()