codexrc-sinusoidal-turn-on.py
rc-sinusoidal-turn-on.py
"""Original switched-sinusoid RC response and a specified settling threshold."""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
def main():
tau = 1e-3
omega = 1000.0
amplitude = 1.0
ratio = omega * tau
t = np.linspace(0, 12 * tau, 2401)
steady = amplitude * (np.cos(omega * t) + ratio * np.sin(omega * t)) / (1 + ratio**2)
transient = -amplitude * np.exp(-t / tau) / (1 + ratio**2)
exact = steady + transient
derivative = amplitude * (-omega * np.sin(omega * t)
+ ratio * omega * np.cos(omega * t)
+ np.exp(-t / tau) / tau) / (1 + ratio**2)
assert exact[0] == 0
assert np.allclose(tau * derivative + exact, amplitude * np.cos(omega * t))
relative = np.exp(-t / tau) / np.sqrt(1 + ratio**2)
tolerance = 0.01
settling = tau * np.log(1 / (tolerance * np.sqrt(1 + ratio**2)))
assert np.isclose(settling / tau, 4.258596595708118)
assert np.allclose(abs(transient) / (amplitude / np.sqrt(1 + ratio**2)), relative)
fig, (response, decay) = plt.subplots(1, 2, figsize=(9.6, 4.2), dpi=100,
layout="constrained")
fig.set_facecolor("white")
response.plot(t * 1000, steady, "--", color="#286f99", label="Phasor steady state")
response.plot(t * 1000, exact, color="#b66b31", label="Exact switch-on response")
response.scatter([0, 0], [0.5, 0], color=["#286f99", "#b66b31"], s=22, zorder=4)
response.set(ylabel="Capacitor potential difference (V)",
title="The initial condition requires a transient", ylim=(-0.85, 1.15))
response.legend(fontsize=8.5, loc="upper right")
decay.semilogy(t * 1000, 100 * relative, color="#286f99", label="Relative transient")
decay.axhline(100 * tolerance, color="#444444", linestyle="--", label="1% allowance")
decay.axvline(settling * 1000, color="#b66b31", linestyle=":",
label=f"Settled after {settling * 1000:.3f} ms")
decay.set(ylabel="Transient / steady-state amplitude (%)", ylim=(1e-4, 120),
title="An exponential error bound sets the wait")
decay.legend(fontsize=8.5, loc="upper right")
for ax in [response, decay]:
ax.set(xlabel="Time after switch-on (ms)", xlim=(0, 12))
ax.grid(alpha=0.15)
fig.savefig(Path(__file__).with_suffix(".png").name, facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()