codexreactive-power-overcompensation.py
reactive-power-overcompensation.py
"""Original fixed-load model: leading current need not exceed the baseline."""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
def main():
power, reactive, voltage, frequency = 1000.0, 750.0, 200.0, 50.0
omega = 2 * np.pi * frequency
optimum = reactive / (omega * voltage**2)
capacitance = np.linspace(0, 180e-6, 1201)
net_q = reactive - omega * capacitance * voltage**2
current = np.hypot(power, net_q) / voltage
baseline = np.hypot(power, reactive) / voltage
assert np.isclose(optimum * 1e6, 59.683103659460755)
assert baseline == 6.25
assert np.isclose(np.hypot(power, reactive - omega * 2 * optimum * voltage**2)
/ voltage, baseline)
assert np.isclose(np.hypot(power, reactive - omega * 100e-6 * voltage**2)
/ voltage, 5.6050894549555)
assert np.allclose(current**2 - baseline**2,
(omega * capacitance * voltage**2)
* (omega * capacitance * voltage**2 - 2 * reactive) / voltage**2)
fig, (q_axes, i_axes) = plt.subplots(1, 2, figsize=(10, 4.2), dpi=100,
layout="constrained")
fig.set_facecolor("white")
q_axes.plot(capacitance * 1e6, net_q, color="#286f99")
q_axes.axhline(0, color="#555555", linewidth=0.8)
q_axes.set(ylabel="Net reactive power (var)", title="Capacitance changes the sign of Q")
q_axes.text(5, 430, "Lagging", color="#286f99")
q_axes.text(100, -1400, "Leading", color="#9f4b27")
i_axes.plot(capacitance * 1e6, current, color="#9f4b27")
i_axes.axhline(baseline, color="#555555", linestyle="--", label="Uncorrected: 6.25 A")
i_axes.axvspan(optimum * 1e6, 2 * optimum * 1e6, color="#7d903b", alpha=0.13,
label="Leading, but below baseline current")
i_axes.scatter([optimum * 1e6], [power / voltage], color="#286f99", zorder=4)
i_axes.set(ylabel="RMS source current (A)", ylim=(4.5, 10.2),
title="Minimum at cancellation; baseline at 2C*")
i_axes.legend(loc="upper left", fontsize=8)
for ax in (q_axes, i_axes):
ax.axvline(optimum * 1e6, color="#286f99", linestyle=":", linewidth=1)
ax.axvline(2 * optimum * 1e6, color="#7d903b", linestyle=":", linewidth=1)
ax.set(xlabel="Shunt capacitance (µF)", xlim=(0, 180))
ax.set_xticks([0, optimum * 1e6, 2 * optimum * 1e6, 180],
["0", "C*\n59.7", "2C*\n119.4", "180"])
ax.grid(alpha=0.15)
fig.savefig(Path(__file__).with_suffix(".png").name, facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()