nx_ac_enthalpy_metrics_test.nx source
↩ module page · 84 lines · 4009 B
1// nx_ac_enthalpy_metrics_test.nx -- KAT gate for the AC performance crown.
2//
3// Proves the delivered-capacity / COP / EER / Carnot / drift math against
4// external references (0 degC = 273.15 K; 3-ton nominal ~= 10.55 kW; EER = COP
5// * 3.412) AND enforces the physical liar-kill surface (reversed enthalpy ->
6// negative capacity, P<=0 -> INFEASIBLE, T_cold>=T_hot -> INFEASIBLE, measured
7// COP strictly below the Carnot ceiling, negative superheat surfaced verbatim).
8//
9// expect_exit: 0
10// license_tier: ORIGINAL
11
12import "nx_psychrometrics.nx"
13import "nx_ac_enthalpy_metrics.nx"
14
15func nx_acm_abs(x: i64) -> i64 {
16 if x < 0 { return 0 - x }
17 return x
18}
19
20func main() -> i64 {
21 // ===== E1: exact pure-arithmetic KATs ===========================
22 // absolute-temperature anchor (external: 0 degC = 273.15 K, 25 degC = 298.15 K)
23 if nx_ac_temp_cK(0) != 27315 { return 1 }
24 if nx_ac_temp_cK(25000) != 29815 { return 2 }
25
26 // COP x100 = Q*100/P (10.8 kW / 3.0 kW = COP 3.60)
27 if nx_ac_cop_x100(10800, 3000) != 360 { return 3 }
28 // EER x100 = COP * 3.412 (COP 3.60 -> EER 12.28)
29 if nx_ac_eer_x100(360) != 1228 { return 4 }
30
31 // Carnot ceiling: cold 24C, hot 35C -> Tc/(Th-Tc) = 297.15/11.0 = 27.01
32 if nx_ac_carnot_cop_x100(24000, 35000) != 2701 { return 5 }
33
34 // refrigerant / air-side deltas
35 if nx_ac_superheat_mC(10000, 4000) != 6000 { return 6 } // 6 K superheat
36 if nx_ac_subcool_mC(45000, 37000) != 8000 { return 7 } // 8 K subcool
37 if nx_ac_evap_split_mC(24000, 12000) != 12000 { return 8 } // 12 K air split
38
39 // efficiency drift permille vs own baseline
40 if nx_ac_efficiency_drift_permille(328, 400) != 180 { return 9 } // 18% degraded
41 if nx_ac_efficiency_drift_permille(420, 400) != -50 { return 10 } // 5% improved
42
43 // ===== E2: liar-kill / infeasibility (LOUD, never fabricated) ===
44 // Carnot with cold reservoir hotter than hot reservoir -> impossible
45 if nx_ac_carnot_cop_x100(35000, 24000) != NX_ACM_INFEASIBLE { return 20 }
46 // COP with zero/negative electrical power -> impossible (no infinite COP)
47 if nx_ac_cop_x100(10800, 0) != NX_ACM_INFEASIBLE { return 21 }
48 if nx_ac_cop_x100(10800, -5) != NX_ACM_INFEASIBLE { return 22 }
49 // negative superheat surfaced verbatim (flooded coil / swapped sensor)
50 if nx_ac_superheat_mC(3000, 8000) != -5000 { return 23 }
51 // drift with non-positive baseline -> impossible
52 if nx_ac_efficiency_drift_permille(300, 0) != NX_ACM_INFEASIBLE { return 24 }
53
54 // ===== E3: air-side capacity chain (physics + external bands) ====
55 // Supply air 12C/90%RH, return air 24C/50%RH, 1200 CFM, rho 1.2 kg/m^3.
56 let h_sup: i64 = nx_psy_enthalpy_from_rh(12000, 900, NX_PSY_P_ATM_PA)
57 let h_ret: i64 = nx_psy_enthalpy_from_rh(24000, 500, NX_PSY_P_ATM_PA)
58 // INVARIANT: warmer, moister return air carries more enthalpy than the
59 // cooled/dehumidified supply air -> a real AC removes enthalpy.
60 if h_ret <= h_sup { return 30 }
61 let dh: i64 = h_ret - h_sup
62 if dh < 12000 { return 31 } // total enthalpy drop band (J/kg)
63 if dh > 20000 { return 32 }
64
65 // Delivered capacity for a 3-ton-class unit ~ 10.55 kW nominal.
66 let q_w: i64 = nx_ac_delivered_cooling_w(1200, dh, 1200)
67 if q_w < 9000 { return 33 } // external band: 3-ton = 10551 W
68 if q_w > 13000 { return 34 }
69
70 // Real COP in the plausible residential band...
71 let cop: i64 = nx_ac_cop_x100(q_w, 3000)
72 if cop < 280 { return 35 }
73 if cop > 460 { return 36 }
74 // ...and STRICTLY below the Carnot ceiling for this indoor/outdoor pair.
75 let carnot: i64 = nx_ac_carnot_cop_x100(24000, 35000)
76 if cop >= carnot { return 37 } // the hard physical liar-kill ceiling
77
78 // Reversed enthalpy (supply warmer than return = NOT cooling) -> negative
79 // delivered capacity, surfaced loud, never a fabricated positive.
80 let q_rev: i64 = nx_ac_delivered_cooling_w(1200, 0 - dh, 1200)
81 if q_rev >= 0 { return 38 }
82
83 return 0
84}