fig, ax = plt.subplots(figsize=(10, 5))
ax.axhline(0, color='gray', lw=0.6)
xr = np.linspace(-np.pi - 0.05, 2*np.pi + 0.05, 1200)
V6_np = 1 - np.cos(xr)
for E_val_np, col, lw, alpha in [
(2.0, 'tomato', 2.2, 0.95), # separatrix
(0.3, 'steelblue', 1.3, 0.8),
(0.5, 'seagreen', 2.0, 0.95), # IVP orbit
(1.0, 'steelblue', 1.3, 0.7),
(1.6, 'steelblue', 1.3, 0.7),
(2.8, 'steelblue', 1.3, 0.65), # rotational orbits
(4.0, 'steelblue', 1.3, 0.55),
]:
rhs = 2*(E_val_np - V6_np)
valid = rhs >= 0
y_pos = np.where(valid, np.sqrt(np.maximum(rhs, 0)), np.nan)
y_neg = -y_pos
ax.plot(xr, y_pos, color=col, lw=lw, alpha=alpha)
ax.plot(xr, y_neg, color=col, lw=lw, alpha=alpha)
# Equilibria
for xeq, marker, col, label in [
(-np.pi, 's', 'tomato', 'Saddle'),
( 0, 'o', 'seagreen', 'Center'),
( np.pi, 's', 'tomato', None),
(2*np.pi,'o', 'seagreen', None),
]:
ax.plot(xeq, 0, marker, color=col, ms=9, zorder=6,
label=label if label else '')
# IVP initial condition
ax.plot(np.pi/3, 0, 'D', color='black', ms=8, zorder=7,
label=r'IC $(\pi/3, 0)$, $E=1/2$')
ax.set_xlim(-np.pi - 0.1, 2*np.pi + 0.1)
ax.set_ylim(-3.2, 3.2)
ax.set_xlabel(r'$x$ (angle)', fontsize=13)
ax.set_ylabel(r"$y = x'$ (angular velocity)", fontsize=13)
ax.set_title('Nonlinear pendulum: separatrix (tomato) at $E=2$', fontsize=11)
# x-axis tick labels at multiples of pi
ax.set_xticks([-np.pi, 0, np.pi, 2*np.pi])
ax.set_xticklabels([r'$-\pi$', r'$0$', r'$\pi$', r'$2\pi$'])
from matplotlib.lines import Line2D
handles = [
Line2D([0],[0], color='tomato', lw=2.2, label='Separatrix ($E=2$)'),
Line2D([0],[0], color='seagreen', lw=2.0, label=r'IVP orbit ($E=1/2$)'),
Line2D([0],[0], color='steelblue', lw=1.3, label='Other orbits'),
Line2D([0],[0], marker='s', color='tomato', lw=0, ms=8, label='Saddle'),
Line2D([0],[0], marker='o', color='seagreen',lw=0, ms=8, label='Center'),
Line2D([0],[0], marker='D', color='black', lw=0, ms=7,
label=r'IC $(\pi/3,0)$'),
]
ax.legend(handles=handles, fontsize=8, loc='upper right')
plt.tight_layout()
plt.show()