#!/usr/bin/env python3
"""
verify_P009.py -- Paper 9: water as a geometric thermometer.

This verifier checks the cubic-density moments, self-lensing energy, kappa,
triple-point temperature arithmetic, Kelvin critical-radius calculation,
geometric radius, phase-transition energy ratio, cluster-size estimate, and
macroscopic resonance-radius estimate in toe/09_Paper_WaterGeometricThermometer.tex.

Most displayed arithmetic reproduces. The flagged issues are interpretive and
dimensional: the temperature scale is obtained by working backward from the
water triple point and selecting an external room-temperature energy scale; the
droplet match uses S=1.5, essentially the supersaturation required to match the
geometric radius; the 3/r=1/pi derivation is dimensionally incomplete until a
length unit is inserted; and the "closest natural constant" claim is only a
small finite comparison, not a proof over natural constants.
"""

from __future__ import annotations

import math
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
from verify_common import Verifier, CheckResult


class ModernVerifier(Verifier):
    """Local adapter: modern check-line output format. Tolerance logic is
    inherited unchanged from verify_common.Verifier; only printing differs.
    Computed/claimed values stay as indented info lines."""

    def __init__(self, name: str) -> None:
        self.name = name
        self.results = []
        print(name)

    def record(self, label, ok, computed="", claimed="", detail=""):
        self.results.append(CheckResult(label, ok, computed, claimed, detail))
        status = "PASS" if ok else "FAIL"
        desc = f"{label} -- {detail}" if detail else label
        print(f"  [{status}] {len(self.results):>2}. {desc}")
        if computed != "" or claimed != "":
            print(f"          computed: {computed}")
            print(f"          claimed : {claimed}")
        return ok

    def summary(self) -> int:
        passed = sum(r.ok for r in self.results)
        failed = len(self.results) - passed
        print(f"\n{'='*60}\nRESULT: {passed} PASS / {failed} FAIL")
        return 1 if failed else 0


v = ModernVerifier("P009 -- Water Geometric Thermometer")

ROOT = Path(__file__).resolve().parents[2]
TEX = (ROOT / "toe" / "09_Paper_WaterGeometricThermometer.tex").read_text()

PI = math.pi
MU0 = 4.0 * PI**3 + PI**2 + PI
MU1 = 16.0 * PI**3 / 5.0 + 3.0 * PI**2 / 4.0 + 2.0 * PI / 3.0
MU2 = 16.0 * PI**3 / 6.0 + 3.0 * PI**2 / 5.0 + 2.0 * PI / 4.0
ALPHA = 1.0 / MU0
KAPPA = ALPHA**1.25

A = 48.0 * PI**3
B = 6.0 * PI**2
C = 2.0 * PI
E_RHO = 0.5 * (A**2 / 5.0 + 2.0 * A * B / 4.0 + (B**2 + 2.0 * A * C) / 3.0 + 2.0 * B * C / 2.0 + C**2)
E_SELF = E_RHO / MU0**2

K_B_EV = 8.617333e-5
T_TRIPLE = 273.16
T_GEOM = T_TRIPLE / (10.0 * PI)
E_SCALE = K_B_EV * T_GEOM / (KAPPA * E_SELF)
KB_300 = K_B_EV * 300.0

GAMMA = 0.072
V_M = 1.807e-5
R = 8.314
T = 298.0
S = 1.5
D_H2O_M = 2.75e-10
R_CRIT_M = 2.0 * GAMMA * V_M / (R * T * math.log(S))
R_CRIT_NM = R_CRIT_M * 1e9
R_GEOM_NM = 3.0 * PI * D_H2O_M * 1e9
S_REQUIRED = math.exp(2.0 * GAMMA * V_M / (R * T * (R_GEOM_NM * 1e-9)))


def pct(value: float, target: float) -> float:
    return 100.0 * (value - target) / abs(target)


v.check("mu0", MU0, 137.036303776, rel=2e-12)
v.check("mu1", MU1, 108.716683780, rel=2e-12)
v.check("mu2", MU2, 90.175963448, rel=5e-12)
v.check("beta_geom", MU1 / MU0, 0.793342208, rel=4e-10)
v.check("Dirichlet energy E[rho]", E_RHO, 247444.809832, rel=2e-12)
v.check("self-lensing energy", E_SELF, 13.176712697, rel=3e-11)
v.check("kappa alpha^(5/4)", KAPPA, 0.002132826, rel=7e-8)

v.check("T_geom = T_triple/(10pi)", T_GEOM, 8.695, rel=5e-5)
v.check("10pi warming reconstructs triple point", 10.0 * PI * T_GEOM, 273.16, rel=1e-12)
v.check("required E_scale", E_SCALE, 0.0267, rel=2e-3)
v.check("kB times 300K", KB_300, 0.0259, rel=2e-3)
v.check(
    "E_scale equals kB*300K precisely",
    E_SCALE,
    KB_300,
    rel=5e-3,
    detail="Expected fail: E_scale is about 3.1% above kB*300 K, so 'precisely equals' is too strong.",
)
v.check("T_geom / T_CMB ratio", T_GEOM / 2.725, 3.19, rel=4e-4)
v.check(
    "T_geom / T_CMB equals pi",
    T_GEOM / 2.725,
    PI,
    rel=5e-3,
    detail="Expected fail if treated as more than a loose approximation: the ratio is about 1.6% above pi.",
)

v.check("Kelvin critical radius at S=1.5 in nm", R_CRIT_NM, 2.5901, rel=7e-5)
v.check("geometric critical radius 3pi*dH2O in nm", R_GEOM_NM, 2.5918, rel=7e-5)
v.check("nucleation/geometric radius ratio", R_CRIT_NM / R_GEOM_NM, 0.9993, rel=1e-4)
v.check("radius agreement percent", abs(pct(R_CRIT_NM, R_GEOM_NM)), 0.07, rel=2e-1)
v.check("supersaturation required for exact geometric radius", S_REQUIRED, 1.5, rel=7e-4)

fusion = 6.01
vap = 40.66
ratio = vap / fusion
v.check("phase enthalpy ratio", ratio, 6.7654, rel=3e-6)
v.check("2pi comparison error percent", abs(pct(2.0 * PI, ratio)), 7.13, rel=7e-4)
v.check("pi comparison error percent", abs(pct(PI, ratio)), 53.6, rel=2e-3)
v.check("4pi/3 comparison error percent", abs(pct(4.0 * PI / 3.0, ratio)), 38.1, rel=2e-3)

rho = 997.0
molar_mass = 18.015e-3
n_a = 6.02214076e23
volume = (4.0 / 3.0) * PI * (R_GEOM_NM * 1e-9) ** 3
n_cluster = volume * rho / (molar_mass / n_a)
v.check("cluster size at geometric radius", n_cluster, 2430.0, rel=3e-3)
v.check("fog resonance radius", (10.0 * PI) * R_GEOM_NM, 81.0, rel=6e-3)

v.record(
    "triple-point temperature is predicted without using the triple point",
    False,
    computed="the proof computes T_geom = 273.16/(10*pi), then solves for E_scale",
    claimed="T_triple emerges from the geometric framework",
    detail="Expected proof-status fail: the headline temperature relation is reverse-engineered unless E_scale is derived independently.",
)
v.record(
    "3/r = 1/pi derivation is dimensionally complete",
    False,
    computed="A/V has units 1/length while 1/pi is dimensionless; the water molecular diameter is inserted only after r=3pi is obtained",
    claimed="setting 3/r = 1/pi implies r=3pi",
    detail="Expected dimensional-analysis fail.",
)
v.record(
    "S=1.5 is independently predicted rather than selected",
    False,
    computed=f"the exact supersaturation required to hit 3*pi*d_H2O with the displayed constants is S={S_REQUIRED:.6f}",
    claimed="realistic atmospheric supersaturation S=1.5 gives a geometric match",
    detail="Expected proof-status fail: the chosen realistic value is also effectively the fitted match value.",
)
v.record(
    "2pi is closest among all natural constants",
    False,
    computed="the paper compares only {1/pi, pi, 2pi, 4pi/3}; it does not define or search all natural constants/factors",
    claimed="closest among all natural constants",
    detail="Expected scope fail.",
)
v.record(
    "future predictions follow from formulas without empirical tuning",
    False,
    computed="cluster and fog-radius predictions are downstream of the selected molecular diameter, T_triple-derived T_geom, and S=1.5 match",
    claimed="testable predictions from the geometric framework",
    detail="Expected status fail.",
)

sys.exit(v.summary())
