Modeling Zeotropic Refrigerant Temperature Glide & Mass Addition in Pure TypeScript
How to model non-linear zeotropic refrigerant glide (R-454B/R-32) and line-set mass addition in pure TypeScript with zero external dependencies.

With the global phase-down of high-GWP hydrofluorocarbons (HFCs) under the AIM Act and Kigali Amendment, the HVAC/R engineering landscape is undergoing a massive shift toward mildly flammable A2L refrigerants like R-454B and R-32.
For software engineers building computational simulation tools or digital twins for HVAC equipment, this transition exposes a critical mathematical challenge: zeotropic temperature glide.
In legacy single-component or azeotropic refrigerants (such as R-22 or R-410A), evaporation and condensation occur at constant temperatures for a given saturation pressure. In zeotropic blends like R-454B (composed of 68.9% R-32 and 31.1% R-1234yf), the constituent chemical components boil and condense at different temperatures. This introduces a 1.5°F to 8.0°F temperature glide across the evaporator and condenser coils.
If your calculation engine evaluates saturation state points with a single curve, your field diagnostics will suffer an immediate 2°F to 3°F error in subcooling and superheat readings.
Here is how we designed and implemented a deterministic, zero-dependency thermodynamic engine in pure TypeScript to model dual-phase saturation curves and line-set mass addition calculations entirely on the client side.
1. The Physics: Bubble Point vs. Dew Point
A zeotropic mixture does not possess a single saturation temperature T_sat(P). Instead, phase equilibrium splits into two distinct thermodynamic boundaries:
- Bubble Point Curve (T_bubble): The temperature at which the first bubble of vapor forms from saturated liquid. This boundary is strictly required to calculate subcooling:
Subcooling (°F) = T_bubble(P_liquid) - T_liquid_line
- Dew Point Curve (T_dew): The temperature at which the last droplet of liquid evaporates into saturated vapor. This boundary is strictly required to calculate superheat:
Superheat (°F) = T_suction_line - T_dew(P_suction)
Pressure (psig)
▲
│ SUPERHEATED VAPOR REGION
│ /
│ Dew Point / (Calculates Superheat)
│ Curve ──────/
│ / TWO-PHASE (GLIDE) REGION
│ Bubble /
│ Curve ───/ (Calculates Subcooling)
│ /
│ / SUBCOOLED LIQUID REGION
└─────────┴──────────────────────────────► Temperature (°F)
Attempting to evaluate liquid subcooling using the dew point curve results in a falsely elevated subcooling value, leading technicians to reclaim charge from a properly balanced system.
2. Implementing Dual-Curve Saturation in TypeScript
Rather than bundling heavy C++ binaries or relying on a remote API server that adds network latency and compromises user privacy, we derived high-precision polynomial regression equations validated against NIST REFPROP Standard 23 data.
Here is the core type definition and logarithmic polynomial solver:
export type RefrigerantId = "R454B" | "R32" | "R410A" | "R134a" | "R22";
export interface SaturationCurve {
// Coefficients for P -> T polynomial: T = c0 + c1*ln(P) + c2*(ln(P))^2 + ...
bubbleCoefficients: number[];
dewCoefficients: number[];
pressureMinPsig: number;
pressureMaxPsig: number;
}
export interface ThermodynamicState {
refrigerant: RefrigerantId;
pressurePsig: number;
lineTemperatureF: number;
saturationBubbleF: number;
saturationDewF: number;
glideF: number;
subcoolingF?: number;
superheatF?: number;
}
/**
* Solves saturation temperature from gauge pressure using log-polynomial curves
*/
export function solveSaturationTemp(
pressurePsig: number,
coefficients: number[]
): number {
const pAbs = pressurePsig + 14.696; // Convert to psia
const lnP = Math.log(pAbs);
return coefficients.reduce((acc, coeff, power) => {
return acc + coeff * Math.pow(lnP, power);
}, 0);
}
By decoupling the bubble evaluation from the dew evaluation, we compute exact phase boundaries simultaneously:
export function evaluateVaporCompressionPoint(
refrigerant: RefrigerantId,
liquidPressurePsig: number,
liquidLineTempF: number,
suctionPressurePsig: number,
suctionLineTempF: number,
curves: SaturationCurve
): { subcoolingF: number; superheatF: number; glideF: number } {
// Subcooling strictly uses the liquid Bubble Point
const tBubble = solveSaturationTemp(liquidPressurePsig, curves.bubbleCoefficients);
const subcoolingF = Number((tBubble - liquidLineTempF).toFixed(2));
// Superheat strictly uses the vapor Dew Point
const tDew = solveSaturationTemp(suctionPressurePsig, curves.dewCoefficients);
const superheatF = Number((suctionLineTempF - tDew).toFixed(2));
// Evaporator temperature glide across the saturation dome
const glideF = Number((tDew - solveSaturationTemp(suctionPressurePsig, curves.bubbleCoefficients)).toFixed(2));
return { subcoolingF, superheatF, glideF };
}
You can test this phase-equilibrium solver live in our web engine: Superheat & Subcooling Calculator and inspect individual pressure-temperature tables via the A2L Refrigerant PT Chart.
3. Modeling Line-Set Liquid Mass Addition
Thermodynamic diagnostic measurements only work when the base charge inside the split system matches OEM manufacturer specifications.
When split-system line sets exceed the pre-charged factory allowance (typically 15 ft or 25 ft), additional liquid mass must be calculated using the internal cross-sectional volume of the liquid line.
The Mass Addition Formulation:
Net Added Ounces = (Actual Length - Factory Allowance) * Adder Rate + Vertical Lift Penalty
Where:
Actual Length: Installed physical line length (ft)
Factory Allowance: Pre-charged line length limit included in outdoor condenser (ft)
Adder Rate: Mass rate per linear foot (oz/ft), dependent on liquid line outer diameter (OD) and refrigerant liquid density at 100°F condensing temperature
Vertical Lift Penalty: Hydrostatic liquid column correction factor for multi-story elevations
Here is the TypeScript implementation for OEM split-system mass addition:
export interface LineSetInput {
actualLengthFt: number;
factoryAllowanceFt: number;
liquidLineOd: "1/4" | "5/16" | "3/8" | "1/2";
adderRateOzPerFt: number;
factoryBaseChargeOz: number;
verticalLiftFt: number;
}
export interface LineSetOutput {
netLengthFt: number;
additionalChargeOz: number;
totalSystemChargeOz: number;
totalSystemChargeLbs: number;
requiresOilTrap: boolean;
}
export function calculateSystemMassCharge(input: LineSetInput): LineSetOutput {
const {
actualLengthFt,
factoryAllowanceFt,
adderRateOzPerFt,
factoryBaseChargeOz,
verticalLiftFt,
} = input;
if (actualLengthFt <= 0) {
throw new Error("Actual line set length must be positive.");
}
// Calculate length delta beyond factory pre-charged allowance
const netLengthFt = Math.max(0, actualLengthFt - factoryAllowanceFt);
const additionalChargeOz = Number((netLengthFt * adderRateOzPerFt).toFixed(2));
const totalSystemChargeOz = Number((factoryBaseChargeOz + additionalChargeOz).toFixed(2));
const totalSystemChargeLbs = Number((totalSystemChargeOz / 16).toFixed(3));
// ASHRAE standard: Vertical risers over 25 ft require oil traps to guarantee oil return
const requiresOilTrap = verticalLiftFt >= 25;
return {
netLengthFt,
additionalChargeOz,
totalSystemChargeOz,
totalSystemChargeLbs,
requiresOilTrap,
};
}
We packaged this full mass algorithm into an open-access web utility with pre-configured manufacturer profiles: Refrigerant Mass Charge Calculator.
4. Key Architectural Takeaways
Deterministic Execution: By compiling pure mathematical equations directly in TypeScript rather than making network calls, calculation latency drops below 1ms, enabling 60fps reactive slider interactions.
Zero-Database Privacy Guarantee: Field measurements, customer job site line lengths, and equipment serials stay strictly in memory inside the client browser.
Rigorous Physical Limits: Software engines modeling thermodynamic systems must enforce physical boundaries, such as alerting users when aspect ratios, Reynolds numbers, or vertical oil traps exceed safe mechanical standards.
To explore all the governing fluid mechanics, heat transfer formulas, and standards references, review our open documentation at the deterministic thermodynamic calculation engine.

