"""Hypothetical van der Waals inversion and finite-throttle temperature model. Python 3.14 / matplotlib 3.10.7 / numpy 2.3.5. Run from _media. No fitted material parameters or experimental points are used. r=v_m/b_m, theta=R*b_m*T/a_m, pi=b_m**2*p/a_m, eta=b_m*h_m/a_m. The caloric assumption is C_V,m/R=3/2, so u_m=C_V,m*T-a_m/v_m. Only supercritical theta>8/27 is displayed; all endpoints have pi>0. """ from pathlib import Path import matplotlib.pyplot as plt import numpy as np C = 1.5 CASES = ((.8, .12, "#176ca4", "Cooling"), (2.2, .12, "#9b4327", "Warming"), (1.45, .30, "#7950a2", "Warms, then cools")) OUTLET = .025 def initial_volume(theta, pressure): roots = np.roots([pressure, -pressure-theta, 1, -1]) valid = [z.real for z in roots if abs(z.imag) < 1e-9 and z.real > 1] if len(valid) != 1: raise ValueError("The plotted supercritical state must have one physical root") return valid[0] def state_on_isenthalp(r, eta): theta = (eta + 2/r) / (C + r/(r-1)) pressure = theta/(r-1) - 1/r**2 return theta, pressure def throttle(theta, pressure): r1 = initial_volume(theta, pressure) eta = C*theta + pressure*r1 - 1/r1 lo, hi = r1, 250. for _ in range(100): mid = (lo+hi)/2 if state_on_isenthalp(mid, eta)[1] > OUTLET: lo = mid else: hi = mid r = np.geomspace(r1, (lo+hi)/2, 600) t, p = state_on_isenthalp(r, eta) return r, t, p, eta def main(): plt.rcParams.update({"font.size": 11, "figure.facecolor": "white"}) fig, (ax, bx) = plt.subplots(1, 2, figsize=(10, 5.6), dpi=120) r = np.linspace(1.5, 450, 20000) inv_t, inv_p = 2*(1-1/r)**2, (2*r-3)/r**2 # At fixed theta, the inversion pressure is found directly from r. ts = np.linspace(.42, 2, 500) inverse_r = 1-np.sqrt(ts/2) ps = 2*inverse_r-3*inverse_r**2 ax.fill_betweenx(ts, 0, ps, color="#e6f2fa") ax.fill_betweenx(ts, ps, .38, color="#f9ece7") ax.axhspan(2, 2.36, color="#f9ece7") ax.plot(inv_p, inv_t, "k", linewidth=1.8, label="$\\mu_{JT}=0$") ax.text(.055, 1.06, "Cooling\n$\\mu_{JT}>0$", color="#176ca4", ha="center") ax.text(.30, 1.97, "Warming\n$\\mu_{JT}<0$", color="#9b4327", ha="center") ax.set(xlim=(0, .38), ylim=(.42, 2.36), xlabel="Reduced pressure $\\pi$", ylabel="Reduced temperature $\\theta$", title="Inversion curve and endpoint states") summary = [] for t1, p1, color, label in CASES: r, t, p, eta = throttle(t1, p1) ax.plot(p, t, color=color, linewidth=2) ax.plot([p[0], p[-1]], [t[0], t[-1]], "o", color=color, markersize=4) j = len(p)//2 ax.annotate("", xy=(p[j+25], t[j+25]), xytext=(p[j-25], t[j-25]), arrowprops={"arrowstyle": "->", "color": color, "lw": 1.8}) bx.plot(p1-p, t-t1, color=color, linewidth=2, label=label) bx.plot(p1-p[-1], t[-1]-t1, "o", color=color, markersize=4) summary.append((t1, p1, float(t[-1]), float(p[-1]), eta)) ax.legend(loc="lower left", framealpha=1) bx.axhline(0, color="#777777", linewidth=1) bx.set(xlabel="Pressure drop $\\pi_1-\\pi_2$", ylabel="Temperature change $\\theta_2-\\theta_1$", title="Finite drops along constant enthalpy") bx.legend(loc="lower right", fontsize=10, framealpha=1) for a in (ax, bx): a.grid(alpha=.22) fig.suptitle("Hypothetical van der Waals throttling: cooling is not universal", fontsize=15, weight="bold", y=.98) fig.text(.5, .10, "$r=v_m/b_m$, $\\theta=Rb_mT/a_m$, $\\pi=b_m^2p/a_m$; $C_{V,m}=3R/2$", ha="center", fontsize=11) fig.text(.5, .045, "Model curves only; supercritical states; no experimental measurements or fitted gas.", ha="center", fontsize=10, color="#555555") fig.subplots_adjust(left=.08, right=.98, bottom=.25, top=.86, wspace=.31) fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), facecolor="white") plt.close(fig) for row in summary: print("theta1=%.8f pi1=%.8f theta2=%.8f pi2=%.8f eta=%.8f" % row) if __name__ == "__main__": main()