import React, { useState } from 'react';
// HVAC Condensate Calculator - Single-file React component
// TailwindCSS classes used for styling (requires Tailwind in the parent project)
// - Default export is the React component
export default function HvacCondensateCalculator() {
const [units, setUnits] = useState('imperial'); // 'imperial' or 'metric'
const [cfm, setCfm] = useState(1200);
const [tIn, setTIn] = useState(78); // inlet dry bulb (°F or °C)
const [rhIn, setRhIn] = useState(60); // %
const [tOut, setTOut] = useState(55); // coil outlet dry bulb
const [rhOut, setRhOut] = useState(95); // % (if coil leaves saturated near 100% may be >)
const [hoursPerDay, setHoursPerDay] = useState(24);
const [safetyFactor, setSafetyFactor] = useState(1.1);
// helper: convert units
const toF = (c) => (c * 9) / 5 + 32;
const toC = (f) => ((f - 32) * 5) / 9;
const toCFM = (m3h) => m3h / 1.699; // approximate
const toM3h = (cfm) => cfm * 1.699;
// Psychrometric helper functions (approximate using Magnus-Tetens)
// All calculations assume standard atmospheric pressure (101325 Pa)
// saturation vapor pressure (Pa) over liquid water using Magnus formula
function satVaporPressurePa(T_C) {
// T_C in deg C
// Magnus constants for water
const a = 17.62;
const b = 243.12; // deg C
const es = 610.94 * Math.exp((a * T_C) / (T_C + b));
return es; // Pa
}
function humidityRatio(T_C, RH_percent) {
// returns humidity ratio (kg water / kg dry air)
// p = 101325 Pa
const P = 101325;
const es = satVaporPressurePa(T_C);
const pv = (RH_percent / 100) * es;
const w = 0.622 * pv / (P - pv); // kg/kg
return w;
}
function densityAir(T_C) {
// approximate density of moist air (kg/m3) at 101325 Pa
// use ideal gas: rho = P / (R_specific * T_kelvin) * correction for humidity (small)
const R_d = 287.05; // J/(kg·K)
const T_k = T_C + 273.15;
const rho = 101325 / (R_d * T_k);
return rho; // kg/m3 dry air approx
}
// Main calculation
function compute() {
// Convert inputs to consistent units (metric internally)
const T_in_C = units === 'imperial' ? toC(tIn) : tIn;
const T_out_C = units === 'imperial' ? toC(tOut) : tOut;
const Q_cfm = units === 'imperial' ? Number(cfm) : Number(cfm) / 1.699; // if metric input given as m3/h, convert to CFM equivalent
// Convert CFM to m3/s
const CFM = Number(Q_cfm);
const m3_per_min = CFM * 0.0283168466; // 1 CFM = 0.0283168466 m3/min
const m3_per_s = m3_per_min / 60;
// Air mass flow (kg/s) = volumetric * density
const rho = densityAir(T_in_C);
const massFlowAir = m3_per_s * rho; // kg dry air / s
// humidity ratios
const w_in = humidityRatio(T_in_C, Number(rhIn));
const w_out = humidityRatio(T_out_C, Number(rhOut));
// water mass removed (kg/s) = massFlowAir * (w_in - w_out)
let w_removed = w_in - w_out;
if (w_removed < 0) w_removed = 0; // no negative condensate
const waterKgPerSec = massFlowAir * w_removed; // kg/s
const waterKgPerHour = waterKgPerSec * 3600;
const waterLPerHour = waterKgPerHour; // 1 kg water ≈ 1 L
const waterLPerDay = waterLPerHour * Number(hoursPerDay) * Number(safetyFactor);
// imperial conversions
const lbPerHour = waterKgPerHour * 2.2046226218;
const gallonsPerHour = waterKgPerHour * 0.2641720524;
const gallonsPerDay = gallonsPerHour * hoursPerDay * safetyFactor;
return {
waterKgPerSec,
waterKgPerHour,
waterLPerHour,
waterLPerDay,
lbPerHour,
gallonsPerHour,
gallonsPerDay,
massFlowAir,
w_in,
w_out,
};
}
const results = compute();
function downloadCSV() {
const rows = [
['Input', 'Value', 'Units'],
['Units system', units, ''],
['Airflow', cfm, units === 'imperial' ? 'CFM' : 'm3/h (approx)'],
['Inlet Temp', tIn, units === 'imperial' ? '°F' : '°C'],
['Inlet RH', rhIn, '%'],
['Outlet Temp', tOut, units === 'imperial' ? '°F' : '°C'],
['Outlet RH', rhOut, '%'],
['Hours per day', hoursPerDay, 'h/day'],
['Safety factor', safetyFactor, 'x'],
[],
['Result', 'Value', 'Units'],
['Condensate (kg/hr)', results.waterKgPerHour.toFixed(3), 'kg/hr'],
['Condensate (L/day)', results.waterLPerDay.toFixed(2), 'L/day'],
['Condensate (lb/hr)', results.lbPerHour.toFixed(3), 'lb/hr'],
['Condensate (gal/day)', results.gallonsPerDay.toFixed(3), 'gal/day'],
];
const csv = rows.map((r) => r.map((c) => `"${c}"`).join(',')).join('\n');
const blob = new Blob([csv], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'hvac-condensate-calculation.csv';
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(url);
}
return (
HVAC Condensate Calculator
Responsive web tool — approximate psychrometric method. Good for quick sizing & estimates.
);
}