code wiki / (root) / nx_ac_enthalpy_metrics.nx

nx_ac_enthalpy_metrics.nx source

↩ module page · 123 lines · 6021 B

1// nx_ac_enthalpy_metrics.nx -- the AC PERFORMANCE crown, built on the 2// psychrometric floor. This is the R4 rung the HVAC-efficiency workstream 3// flagged as "the crown number, NOT built": independent delivered-capacity, 4// COP/EER, and efficiency-drift measured from out-of-band sensors -- the 5// data-center air-side method (delivered capacity = airflow * enthalpy drop), 6// which SOTA DCIM (Vertiv/Schneider/Sunbird) uses per cooling unit. 7// 8// Everything here is a physics quantity a vendor thermostat cannot fake and 9// does not report. Paired with nx_hvac_efficiency (fault verdict) and the 10// reading-level liar-killer (nx_ac_sensor_verify), it is the measurement core 11// of the "Flume for AC" product. 12// 13// KEY LIAR-KILL SURFACE (why this organ is trustworthy, not just a calculator): 14// - delivered cooling with h_return <= h_supply returns NEGATIVE (loud): 15// the air is not being cooled -- never a fabricated positive capacity. 16// - COP with electrical power <= 0 returns INFEASIBLE (loud), never inf. 17// - the CARNOT COP ceiling Tc/(Th-Tc) is a HARD physical bound: any measured 18// or claimed COP above it is thermodynamically impossible -> the downstream 19// liar-killer rejects the reading. carnot with T_cold >= T_hot is INFEASIBLE. 20// - superheat / subcooling / evaporator-split are returned VERBATIM incl. 21// negatives, so a flooded coil or a swapped/failed sensor shows as an 22// impossible value the liar-killer flags -- not silently clamped. 23// 24// NO-FLOAT integer fixed-point (ecosystem doctrine): 25// temperature = milli-degC (mC) airflow = CFM power = W 26// air density = g/m^3 (1200 = 1.2 kg/m^3; data-driven for altitude/temp) 27// enthalpy = J/kg dry air cooling = W 28// COP = x100 (centi-COP) EER = x100 29// Carnot COP = x100 drift = permille (positive = degraded) 30// abs temp = centi-Kelvin (cK): cK = mC/10 + 27315 (0 degC = 273.15 K) 31// 32// NEVER-BRICK #26: pure computation, read-only, no device/firmware write. 33// 34// genealogy_id: project-hvac-efficiency-sclass-2026-06-23 (R4 COP/EER crown) 35// + project-nishi-sensor-gap-census-2026-07-14 (axis-4 external-comp) 36// license_tier: ORIGINAL 37// 38// nx_capability_claims: 39// needs: [nx_psychrometrics] 40// provides: [delivered_cooling_capacity, cop_measure, eer_measure, 41// carnot_cop_ceiling, superheat_measure, subcooling_measure, 42// evaporator_split, efficiency_drift, air_side_enthalpy_method] 43// safety: [no_floating_point, no_syscall, bounded_iteration, 44// read_only_no_device_write, infeasible_input_is_loud, 45// carnot_bounded] 46// verdict: [physical_invariant, external_comp_band, no_silent_failure] 47// license: ORIGINAL 48// kind: iot_runtime_primitive 49// sss: [S0 (bit-equal), S6 (no cloud), S7 (sealed verdict)] 50 51import "nx_psychrometrics.nx" 52const NX_MAGIC_47195: i64 = 47195 53const NX_MAGIC_100000000000: i64 = 100000000000 54const NX_MAGIC_3412: i64 = 3412 55const NX_MAGIC_27315: i64 = 27315 56 57const NX_ACM_INFEASIBLE: i64 = -2000000000 58 59// Delivered cooling capacity in Watts, air-side enthalpy method: 60// Q = mdot_dryair * (h_return - h_supply) 61// mdot [kg/s] = CFM * 0.00047195 [m^3/s per CFM] * rho [kg/m^3] 62// integer: Q_W = CFM * dh_J * rho_gm3 * 47195 / 1e11 63// dh_j = h_return - h_supply (J/kg). NEGATIVE dh -> negative Q (loud: not cooling). 64func nx_ac_delivered_cooling_w(cfm: i64, dh_j: i64, rho_gm3: i64) -> i64 { 65 let a: i64 = cfm * dh_j 66 let b: i64 = a * rho_gm3 67 return (b * NX_MAGIC_47195) / NX_MAGIC_100000000000 68} 69 70// Coefficient of performance x100 = cooling_W / electrical_W. 71// P <= 0 -> INFEASIBLE (loud), never a divide-by-zero / infinite COP. 72func nx_ac_cop_x100(q_cool_w: i64, p_elec_w: i64) -> i64 { 73 if p_elec_w <= 0 { return NX_ACM_INFEASIBLE } 74 return (q_cool_w * 100) / p_elec_w 75} 76 77// EER x100 = COP * 3.412 (EER = BTU/h per W; 1 W = 3.412 BTU/h). 78func nx_ac_eer_x100(cop_x100: i64) -> i64 { 79 return (cop_x100 * NX_MAGIC_3412) / 1000 80} 81 82// Absolute temperature in centi-Kelvin from milli-degC. 0 degC = 273.15 K. 83func nx_ac_temp_cK(t_mC: i64) -> i64 { 84 return (t_mC / 10) + NX_MAGIC_27315 85} 86 87// Carnot COP ceiling x100 for a cooling cycle: COP_max = Tc / (Th - Tc). 88// Tc = cold reservoir (indoor/evaporator), Th = hot reservoir (outdoor/condenser). 89// T_cold >= T_hot is physically impossible for cooling -> INFEASIBLE (loud). 90func nx_ac_carnot_cop_x100(t_cold_mC: i64, t_hot_mC: i64) -> i64 { 91 let tc: i64 = nx_ac_temp_cK(t_cold_mC) 92 let th: i64 = nx_ac_temp_cK(t_hot_mC) 93 let d: i64 = th - tc 94 if d <= 0 { return NX_ACM_INFEASIBLE } 95 return (tc * 100) / d 96} 97 98// Refrigerant superheat (mC) = suction line temp - evaporator saturation temp. 99// Physically >= 0 in normal operation; a negative value is returned VERBATIM 100// (loud) so the liar-killer flags flooding / a swapped-or-failed sensor. 101func nx_ac_superheat_mC(t_suction_mC: i64, t_sat_evap_mC: i64) -> i64 { 102 return t_suction_mC - t_sat_evap_mC 103} 104 105// Refrigerant subcooling (mC) = condenser saturation temp - liquid line temp. 106// Physically >= 0 in normal operation; negatives returned verbatim (loud). 107func nx_ac_subcool_mC(t_sat_cond_mC: i64, t_liquid_mC: i64) -> i64 { 108 return t_sat_cond_mC - t_liquid_mC 109} 110 111// Evaporator air split (mC) = return air temp - supply air temp (cooling). 112// Healthy residential split ~ 8-12 degC (14-22 degF). > 0 in cooling. 113func nx_ac_evap_split_mC(t_return_air_mC: i64, t_supply_air_mC: i64) -> i64 { 114 return t_return_air_mC - t_supply_air_mC 115} 116 117// Efficiency drift permille vs the unit's OWN baseline COP (the Flume bill-hook: 118// "18% more energy per degree-day than last season"). Positive = degraded. 119// Baseline <= 0 -> INFEASIBLE (loud, no fabricated drift). 120func nx_ac_efficiency_drift_permille(cop_now_x100: i64, cop_base_x100: i64) -> i64 { 121 if cop_base_x100 <= 0 { return NX_ACM_INFEASIBLE } 122 return ((cop_base_x100 - cop_now_x100) * 1000) / cop_base_x100 123}