codexjoule-heating-fixed-current-fixed-voltage.py
joule-heating-fixed-current-fixed-voltage.py
"""Compare two ideal resistor drives; Python 3.14 / matplotlib 3.10.7 / numpy 2.3.5.
Run from _media; the matching opaque PNG is written to the current directory.
"""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
def main():
plt.rcParams.update({"font.size": 12, "axes.titlesize": 14, "axes.labelsize": 12})
resistance = np.linspace(2.5, 15, 350)
current, voltage = 1.0, 5.0
fig, axes = plt.subplots(2, 2, figsize=(10, 6.4), sharex=True,
gridspec_kw={"height_ratios": [1.5, 1]}, layout="constrained")
fig.suptitle("Joule heating: state what the supply holds fixed", fontsize=17)
blue, orange = "#17638d", "#bb4e20"
axes[0, 0].plot(resistance, current**2 * resistance, color=blue, lw=2.8)
axes[0, 1].plot(resistance, voltage**2 / resistance, color=orange, lw=2.8)
axes[0, 0].set_title(r"Fixed current: $I_0=1\,\mathrm{A}$")
axes[0, 1].set_title(r"Fixed voltage: $V_0=5\,\mathrm{V}$")
axes[0, 0].text(0.04, 0.90, r"$P=I_0^2R$", transform=axes[0, 0].transAxes, fontsize=15)
axes[0, 1].text(0.53, 0.90, r"$P=V_0^2/R$", transform=axes[0, 1].transAxes, fontsize=15)
for ax, values, color in [(axes[0, 0], [5, 10], blue), (axes[0, 1], [5, 2.5], orange)]:
ax.scatter([5, 10], values, color=color, s=45, zorder=4)
for r, p in zip([5, 10], values):
ax.annotate(f"{p:g} W", (r, p), xytext=(8, 9), textcoords="offset points", color=color)
ax.set_ylabel("Dissipated power (W)")
ax.set_ylim(0, 17)
axes[1, 0].plot(resistance, current * resistance, color=blue, lw=2.5)
axes[1, 1].plot(resistance, voltage / resistance, color=orange, lw=2.5)
axes[1, 0].set_ylabel("Required voltage (V)")
axes[1, 1].set_ylabel("Resulting current (A)")
axes[1, 0].set_ylim(0, 17)
axes[1, 1].set_ylim(0, 2.3)
for ax, values, color in [(axes[1, 0], [5, 10], blue), (axes[1, 1], [1, 0.5], orange)]:
ax.scatter([5, 10], values, color=color, s=45, zorder=4)
for r, y in zip([5, 10], values):
unit = "V" if color == blue else "A"
ax.annotate(f"{y:g} {unit}", (r, y), xytext=(8, 7), textcoords="offset points", color=color)
ax.set_xlabel(r"Resistance $R$ ($\Omega$)")
for ax in axes.flat:
ax.set_xlim(2.5, 15)
ax.set_xticks([5, 10, 15])
ax.grid(alpha=0.18)
ax.spines[["top", "right"]].set_visible(False)
fig.savefig(Path(__file__).stem + ".png", dpi=130, facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()