codexthevenin-divider-and-equivalent-circuits.py
thevenin-divider-and-equivalent-circuits.py
"""Draw the original divider and its terminal equivalent; run from _media."""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Rectangle
import numpy as np
def wire(ax, *points, **kwargs):
ax.plot(*zip(*points), color="#253444", linewidth=1.8, **kwargs)
def resistor(ax, start, end, label, offset=(0, 0.33), color="#253444"):
start, end = np.array(start), np.array(end)
direction = end - start
normal = np.array([-direction[1], direction[0]]) / np.linalg.norm(direction)
points = [start, start + 0.2 * direction]
for k in range(9):
points.append(start + (0.25 + 0.0625 * k) * direction
+ (0.11 * (-1) ** k if k not in (0, 8) else 0) * normal)
points += [start + 0.8 * direction, end]
ax.plot(*zip(*points), color=color, linewidth=1.8)
midpoint = (start + end) / 2 + offset
ax.text(*midpoint, label, ha="center", va="center", fontsize=11, color=color)
def supply(ax, x, voltage):
wire(ax, (x, 0.8), (x, 1.55))
wire(ax, (x, 2.45), (x, 3.2))
ax.add_patch(Circle((x, 2), 0.45, edgecolor="#253444", facecolor="white", lw=1.8))
ax.text(x, 2.18, "+", ha="center", va="center", fontsize=13)
ax.text(x, 1.80, "−", ha="center", va="center", fontsize=13)
ax.text(x - 0.65, 2, voltage, ha="center", va="center", fontsize=12)
def terminals_and_load(ax):
wire(ax, (3.0, 3.2), (4.2, 3.2))
wire(ax, (3.0, 0.8), (4.2, 0.8))
resistor(ax, (4.2, 3.2), (4.2, 0.8), r"$R_L$", offset=(0.46, 0), color="#b54c2b")
for y, label in [(3.2, "a"), (0.8, "b")]:
ax.plot(3.0, y, "o", ms=5, color="#253444")
ax.text(3.02, y + (0.16 if y > 2 else -0.26), label, fontsize=12)
ax.annotate("", xy=(4.0, 3.45), xytext=(3.35, 3.45),
arrowprops={"arrowstyle": "->", "color": "#b54c2b", "lw": 1.6})
ax.text(3.66, 3.67, r"$I$ delivered", ha="center", color="#b54c2b", fontsize=11)
ax.text(3.15, 2, "+\n\n$V$\n\n−", va="center", ha="center", fontsize=12)
ax.add_patch(Rectangle((-0.87, 0.38), 3.68, 3.02, fill=False,
edgecolor="#6e8497", linestyle="--", linewidth=1.2))
fig, axes = plt.subplots(1, 2, figsize=(10.8, 4.8), facecolor="white")
for ax in axes:
ax.set_aspect("equal")
ax.set_xlim(-1.08, 4.9)
ax.set_ylim(-0.05, 4.3)
ax.axis("off")
ax.set_facecolor("white")
terminals_and_load(ax)
ax = axes[0]
supply(ax, 0, "12 V")
resistor(ax, (0, 3.2), (2.4, 3.2), r"$R_1=2\,\mathrm{k\Omega}$")
wire(ax, (2.4, 3.2), (3.0, 3.2))
resistor(ax, (2.4, 3.2), (2.4, 0.8), r"$R_2=4\,\mathrm{k\Omega}$", offset=(-0.85, 0))
wire(ax, (0, 0.8), (3.0, 0.8))
ax.plot(2.4, 3.2, "o", ms=4, color="#253444")
ax.plot(2.4, 0.8, "o", ms=4, color="#253444")
ax.set_title("Original 12 V divider", fontsize=14, pad=8)
ax.text(1.9, 0, r"With $R_L=4\,\mathrm{k\Omega}$: $V=6$ V, $I=1.5$ mA",
ha="center", fontsize=11)
ax = axes[1]
supply(ax, 0, "8 V")
resistor(ax, (0, 3.2), (2.4, 3.2), r"$R_{\mathrm{th}}=\frac{4}{3}\,\mathrm{k\Omega}$")
wire(ax, (2.4, 3.2), (3.0, 3.2))
wire(ax, (0, 0.8), (3.0, 0.8))
ax.set_title("Thévenin equivalent at a, b", fontsize=14, pad=8)
ax.text(1.9, 0, r"Same $V$ and $I$ for each connected load", ha="center", fontsize=11)
fig.tight_layout(pad=1.5)
fig.savefig(Path(__file__).stem + ".png", dpi=140, facecolor="white", transparent=False)
plt.close(fig)