I'd like to propose the following corrections to the definitions for IP specific enthalpy units in units.txt:
Fix the precision difference between the "per lb" and "per lb_dry" versions of the unit
Correct discrepancies in unit names/capitalization
Add the approximately 17.78 kJ/kg offset required to go between the SI and IP definitions for specific enthalpy, as defined by ASHRAE (Fundamentals handbook). More on this below.
SI vs. IP Enthalpy
In HVAC calculations, specific enthalpy has an arbitrary zero point. In SI units, the zero point is 0°C; in IP units it is 0°F. The offset between the IP and SI quantities for enthalpy is equal to the SI specific enthalpy evaluated at 0°F (-17.7778°C):
Per the 2025 ASHRAE Handbook: Fundamentals, the specific enthalpy of dry air at -17°C is -17.095 kJ/kg and at -18°C is -18.1 kJ/kg
Interpolating between the two values, the estimated offset at -17.7778°C is -17.876689 kJ/kg
Introducing this offset to the units engine prevents the user from having to perform this correction manually when converting between SI and IP units of enthalpy.
I've tested these in SkySpark (v3.1.10) and they appear to work as expected.
Finally, it's also worth noting that the category of units that Haystack calls "enthalpy" are actually specific enthalpy; maybe we should update the units.txt category label as well.
Brian FrankMon 17 Aug
If no one has any further comments, then I will merge this later this week.
Jason HoganThu 20 Aug
Here is a concise summary of proposal #1196 for units.txt:Precision Standardization: Standardizes btu_per_pound_dry_air to match the exact multiplier of btu_per_pound ($2325.5576058607867$).Name & Capitalization Fixes: Corrects minor naming and casing inconsistencies across BTU enthalpy definitions (e.g., updating display symbol from btu/lb_dry to BTU/lb_dry).SI/IP Zero-Point Offset: Adds an absolute offset of $-17,876.689\text{ m}^2\text{s}^{-2}$ ($-17.876689\text{ kJ/kg}$). This accounts for the datum difference between SI ($0^\circ\text{C}$) and IP ($0^\circ\text{F}$) enthalpy baselines per the ASHRAE Fundamentals handbook.Expanded Units: Adds kbtu_per_pound and kbtu_per_pound_dry_air entries with the updated multiplier and offset.Category Labeling: Recommends updating the Haystack unit category name from "enthalpy" to "specific enthalpy" for technical accuracy.
Brian FrankFri 21 Aug
Stephen, thanks for the post. I started implementing this and think it needs more discussion
I went back to look were the current values came from. The current values were auto-generated almost two decades ago from the oBIX database in 2008 - they have not changed since. Every commit after that only added new units.
The oBIX db had two quantity sections that both carried BTU-per-pound, same dimension, different values:
// enthalpy (m2*sec-2)
Unit("btu_per_pound, BTU/lb; ...; 2325.5576058607867"),
// specific energy (m2*sec-2)
Unit("btus_per_pound, btu/lb; ...; 2326.0"),
Unit("btus_per_pound_dry_air, btu/lb_dry; ...; 2326.0"),
When those merged into one enthalpy block, btus_per_pound got dropped and btu_per_pound survived sitting next to btus_per_pound_dry_air. That is the whole origin of the discrepancy you found.
There are at least four BTU definitions in the db right now:
entry value implies BTU of
--------------------- -------------- --------------
btu 1054.852 no standard
BTU/h * 3600 1054.35 BTU_th
kBTU/h * 3600 1055055.85 BTU_IT
BTU/lb 2325.5576 1054.8552, no standard
btu/lb_dry 2326.0 BTU_IT
therm 105506000 disagree with
therm/h * 3600 105435000 each other
So BTU/h * h does not equal BTU today
2325.5576058607867 is the odd one out. Back it into a BTU and you get 1054.8552, which is not any standard and does not match our own btu two hundred lines up. 2326.0 is exact by construction:
That should include all your naming fixes: btus_ to btu_, lowercase btu/lb_dry to BTU/lb_dry, and the missing k variants. I kept btu/lb_dry as a secondary alias so its not a breaking change. And rename the section label to specific enthalpy.
With these BTU/h * h == BTU is exact in floating point for BTU, kBTU, MBTU, and therm
On the 17.78 offset
The problem is that an offset changes what subtraction means. Right now if you have two enthalpies in BTU/lb and subtract them, the answer is a real difference you can convert to kJ/kg and multiply by mass flow. Add the offset and that only works if you convert both numbers first and subtract afterward. Anyone who subtracts first and converts second is off by 17.88 kJ/kg, and there is no way for us to tell those two cases apart. That is why I had to create the temp vs temp_delta mess.
The offset also means 0 BTU/lb is no longer zero energy.
So I would say lets focus on the precision and numbers here, and that needs to be a separate discussion
Stephen FrankMon 24 Aug
Thanks for all that info Brian! ASHRAE uses the International Table (IT) definition, so I agree it would be best to standardize on that. ASHRAE's value for it is 1 BTU = 1055.05585262 J, which matches what you have above.
I see your point on the enthalpy offset math. Agreed to leave it alone for now.
Stephen Frank Tue 11 Aug
I'd like to propose the following corrections to the definitions for IP specific enthalpy units in
units.txt:SI vs. IP Enthalpy
In HVAC calculations, specific enthalpy has an arbitrary zero point. In SI units, the zero point is 0°C; in IP units it is 0°F. The offset between the IP and SI quantities for enthalpy is equal to the SI specific enthalpy evaluated at 0°F (-17.7778°C):
Introducing this offset to the units engine prevents the user from having to perform this correction manually when converting between SI and IP units of enthalpy.
Changes to Units.txt
Before...
After...
I've tested these in SkySpark (v3.1.10) and they appear to work as expected.
Finally, it's also worth noting that the category of units that Haystack calls "enthalpy" are actually specific enthalpy; maybe we should update the
units.txtcategory label as well.Brian Frank Mon 17 Aug
If no one has any further comments, then I will merge this later this week.
Jason Hogan Thu 20 Aug
Here is a concise summary of proposal #1196 for units.txt:Precision Standardization: Standardizes btu_per_pound_dry_air to match the exact multiplier of btu_per_pound ($2325.5576058607867$).Name & Capitalization Fixes: Corrects minor naming and casing inconsistencies across BTU enthalpy definitions (e.g., updating display symbol from btu/lb_dry to BTU/lb_dry).SI/IP Zero-Point Offset: Adds an absolute offset of $-17,876.689\text{ m}^2\text{s}^{-2}$ ($-17.876689\text{ kJ/kg}$). This accounts for the datum difference between SI ($0^\circ\text{C}$) and IP ($0^\circ\text{F}$) enthalpy baselines per the ASHRAE Fundamentals handbook.Expanded Units: Adds kbtu_per_pound and kbtu_per_pound_dry_air entries with the updated multiplier and offset.Category Labeling: Recommends updating the Haystack unit category name from "enthalpy" to "specific enthalpy" for technical accuracy.
Brian Frank Fri 21 Aug
Stephen, thanks for the post. I started implementing this and think it needs more discussion
I went back to look were the current values came from. The current values were auto-generated almost two decades ago from the oBIX database in 2008 - they have not changed since. Every commit after that only added new units.
The oBIX db had two quantity sections that both carried BTU-per-pound, same dimension, different values:
// enthalpy (m2*sec-2) Unit("btu_per_pound, BTU/lb; ...; 2325.5576058607867"), // specific energy (m2*sec-2) Unit("btus_per_pound, btu/lb; ...; 2326.0"), Unit("btus_per_pound_dry_air, btu/lb_dry; ...; 2326.0"),When those merged into one enthalpy block, btus_per_pound got dropped and btu_per_pound survived sitting next to btus_per_pound_dry_air. That is the whole origin of the discrepancy you found.
There are at least four BTU definitions in the db right now:
So BTU/h * h does not equal BTU today
2325.5576058607867 is the odd one out. Back it into a BTU and you get 1054.8552, which is not any standard and does not match our own btu two hundred lines up. 2326.0 is exact by construction:
This is what I would propose - pick BTU_IT and apply it everywhere, not just in the enthalpy section:
That should include all your naming fixes: btus_ to btu_, lowercase btu/lb_dry to BTU/lb_dry, and the missing k variants. I kept btu/lb_dry as a secondary alias so its not a breaking change. And rename the section label to specific enthalpy.
With these BTU/h * h == BTU is exact in floating point for BTU, kBTU, MBTU, and therm
On the 17.78 offset
The problem is that an offset changes what subtraction means. Right now if you have two enthalpies in BTU/lb and subtract them, the answer is a real difference you can convert to kJ/kg and multiply by mass flow. Add the offset and that only works if you convert both numbers first and subtract afterward. Anyone who subtracts first and converts second is off by 17.88 kJ/kg, and there is no way for us to tell those two cases apart. That is why I had to create the temp vs temp_delta mess.
The offset also means 0 BTU/lb is no longer zero energy.
So I would say lets focus on the precision and numbers here, and that needs to be a separate discussion
Stephen Frank Mon 24 Aug
Thanks for all that info Brian! ASHRAE uses the International Table (IT) definition, so I agree it would be best to standardize on that. ASHRAE's value for it is 1 BTU = 1055.05585262 J, which matches what you have above.
I see your point on the enthalpy offset math. Agreed to leave it alone for now.
Brian Frank Tue 25 Aug
Thanks, I pushed these changes:
unit db changeset
xeto quantity changeset