"""f04_ideal_fail_map -- contour map of |Z-1| in the (T_r, P_r) plane for a
simple fluid (PR with omega = 0), 1% and 5% contours highlighted in amber;
region where the ideal gas law is acceptable (|Z-1| < 0.01) shaded mist.
Uses a generic species with Tc=1, Pc=1 (Rb=1) and omega=0 so T_r, P_r map
directly to T, P in the cubic_params/Zroots machinery via a synthetic entry.
"""
import sys
sys.path.insert(0, "/home/claude/eos_lecture/code")
from eosstyle import *

# register a synthetic reduced-property species: Tc = 1, Pc = 1, omega = 0
SPECIES["_simple"] = dict(Tc=1.0, Pc=1.0, w=0.0)

Tr = np.linspace(0.55, 3.0, 140)
Pr = np.linspace(0.02, 7.0, 140)
TT, PP = np.meshgrid(Tr, Pr)
ZZ = np.full_like(TT, np.nan)

for i in range(TT.shape[0]):
    for j in range(TT.shape[1]):
        T = TT[i, j] * 1.0   # Tc = 1
        P = PP[i, j] * 1.0   # Pc = 1, Rg = 1
        try:
            r = Zroots("pr", "_simple", T, P, Rg=1.0)
            if len(r) == 0:
                continue
            ZZ[i, j] = r[-1]
        except Exception:
            continue

absdev = np.abs(ZZ - 1.0)

fig, ax = newfig(7.4, 4.6)
ax.grid(False)

levels = [0.0, 0.01, 0.05, 0.15, 0.35, 0.7, 1.2, 2.0]
cmap_colors = ["#EFF3F5", "#D9E2E6", "#B9C1C6", "#8FA0AC", "#5A91BE", "#3A6E96", "#1F4E79"]
cf = ax.contourf(TT, PP, absdev, levels=levels, colors=cmap_colors, extend="max")

# highlight the 1% and 5% contours in amber
c1 = ax.contour(TT, PP, absdev, levels=[0.01], colors=[AMBER], linewidths=2.4)
c5 = ax.contour(TT, PP, absdev, levels=[0.05], colors=[AMBER], linewidths=2.0, linestyles="--")

# shade the "ideal gas acceptable" region (|Z-1| < 0.01) with a mist hatch outline
ax.contourf(TT, PP, absdev, levels=[0.0, 0.01], colors=["none"], hatches=[None])

# The x axis is extended past the computed map (which stops at T_r = 3) to
# open a clear strip of paper on the right; the callouts live there and are
# tied to the features they name with short leader lines, so nothing is
# printed on top of a contour any more.
ax.annotate("ideal gas\nacceptable\n(|Z-1| < 1%)", xy=(2.78, 1.05), xytext=(3.35, 2.10),
            color=GRAPHITE, fontsize=11.5, ha="center", va="center", linespacing=1.3,
            bbox=dict(boxstyle="round,pad=0.34", fc="white", ec=MIST, lw=1.0),
            arrowprops=dict(arrowstyle="-", color=SLATE, lw=1.1,
                            shrinkA=4, shrinkB=0))
ax.annotate("1% contour", xy=(2.515, 5.05), xytext=(3.04, 5.35), color=AMBER, fontsize=11.5,
            arrowprops=dict(arrowstyle="-", color=AMBER, lw=1.1, shrinkA=3, shrinkB=0),
            ha="left", va="center")
ax.annotate("5% contour", xy=(1.94, 1.28), xytext=(0.78, 2.62), color=AMBER, fontsize=11.5,
            arrowprops=dict(arrowstyle="-", color=AMBER, lw=1.1, shrinkA=3, shrinkB=0),
            ha="left", va="center",
            bbox=dict(facecolor="white", edgecolor="none", alpha=0.88, pad=2.0))

cbar = fig.colorbar(cf, ax=ax, pad=0.025)
cbar.set_label(r"$|Z-1|$", fontsize=12, color=INK, labelpad=14)
cbar.ax.tick_params(labelsize=10.5, color=GRAPHITE)

ax.set_xlabel(r"Reduced temperature, $T_r$")
ax.set_ylabel(r"Reduced pressure, $P_r$")
ax.set_xlim(0.55, 3.74)
ax.set_xticks([0.5, 1.0, 1.5, 2.0, 2.5, 3.0])
ax.set_ylim(0.02, 7.0)

save(fig, "f04_ideal_fail_map")
