Skip to content

Commit e552f12

Browse files
authored
Add functions to convert to dry bulb temperature or humidity ratio from enthalpy (#23)
Adds 2 function in each to calculate dry bulb temperature or humidity ration from enthalpy as detailed in #10 (named `GetTDryBulbFromEnthalpyAndHumRatio` and `GetTDryBulbFromEnthalpyAndHumRatio`).
1 parent 517686d commit e552f12

16 files changed

+791
-13
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ install:
1818

1919
script:
2020
# See https://stackoverflow.com/a/34140498 for why "python -m" is needed.
21-
- python -m pytest -v -s
21+
- python3 -m pytest -v -s
2222
- cd tests/js && npm test
2323
- cd $TRAVIS_BUILD_DIR
2424

docs/overview.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ The following psychrometric functions are currently available across all the sup
4444
|`GetDryAirEnthalpy`|Return dry-air enthalpy given dry-bulb temperature.|
4545
|`GetDryAirDensity`|Return dry-air density given dry-bulb temperature and pressure.|
4646
|`GetDryAirVolume`|Return dry-air volume given dry-bulb temperature and pressure.|
47+
|`GetTDryBulbFromEnthalpyAndHumRatio`|Return dry bulb temperature from enthalpy and humidity ratio.|
48+
|`GetHumRatioFromEnthalpyAndTDryBulb`|Return humidity ratio from enthalpy and dry-bulb temperature.|
4749
|`GetSatVapPres`|Return saturation vapor pressure given dry-bulb temperature.|
4850
|`GetSatHumRatio`|Return humidity ratio of saturated air given dry-bulb temperature and pressure.|
4951
|`GetSatAirEnthalpy`|Return saturated air enthalpy given dry-bulb temperature and pressure.|

src/c/psychrolib.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,36 @@ double GetDryAirVolume // (o) Dry air volume ft³ lb⁻¹ [IP] or in m
610610
return R_DA_SI * GetTKelvinFromTCelsius(TDryBulb) / Pressure;
611611
}
612612

613+
// Return dry bulb temperature from enthalpy and humidity ratio.
614+
// Reference: ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 30.
615+
// Notes: based on the `GetMoistAirEnthalpy` function, rearranged for temperature.
616+
double GetTDryBulbFromEnthalpyAndHumRatio // (o) Dry-bulb temperature in °F [IP] or °C [SI]
617+
( double MoistAirEnthalpy // (i) Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
618+
, double HumRatio // (i) Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
619+
)
620+
{
621+
ASSERT (HumRatio >= 0., "Humidity ratio is negative")
622+
623+
if (isIP())
624+
return (MoistAirEnthalpy - 1061.0 * HumRatio) / (0.240 + 0.444 * HumRatio);
625+
else
626+
return (MoistAirEnthalpy / 1000.0 - 2501.0 * HumRatio) / (1.006 + 1.86 * HumRatio);
627+
}
628+
629+
// Return humidity ratio from enthalpy and dry-bulb temperature.
630+
// Reference: ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 30.
631+
// Notes: based on the `GetMoistAirEnthalpy` function, rearranged for humidity ratio.
632+
double GetHumRatioFromEnthalpyAndTDryBulb // (o) Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
633+
( double MoistAirEnthalpy // (i) Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
634+
, double TDryBulb // (i) Dry-bulb temperature in °F [IP] or °C [SI]
635+
)
636+
{
637+
if (isIP())
638+
return (MoistAirEnthalpy - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb);
639+
else
640+
return (MoistAirEnthalpy / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb);
641+
}
642+
613643

614644
/******************************************************************************************************
615645
* Saturated Air Calculations

src/c/psychrolib.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -160,18 +160,28 @@ double GetHumRatioFromSpecificHum // (o) Humidity ratio in lb_H₂O lb_Dry_Air
160160
* Dry Air Calculations
161161
*****************************************************************************************************/
162162

163-
double GetDryAirEnthalpy // (o) Dry air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹ [SI]
164-
( double TDryBulb // (i) Dry bulb temperature in °F [IP] or °C [SI]
163+
double GetDryAirEnthalpy // (o) Dry air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹ [SI]
164+
( double TDryBulb // (i) Dry bulb temperature in °F [IP] or °C [SI]
165165
);
166166

167-
double GetDryAirDensity // (o) Dry air density in lb ft⁻³ [IP] or kg m⁻³ [SI]
168-
( double TDryBulb // (i) Dry bulb temperature in °F [IP] or °C [SI]
169-
, double Pressure // (i) Atmospheric pressure in Psi [IP] or Pa [SI]
167+
double GetDryAirDensity // (o) Dry air density in lb ft⁻³ [IP] or kg m⁻³ [SI]
168+
( double TDryBulb // (i) Dry bulb temperature in °F [IP] or °C [SI]
169+
, double Pressure // (i) Atmospheric pressure in Psi [IP] or Pa [SI]
170170
);
171171

172-
double GetDryAirVolume // (o) Dry air volume ft³ lb⁻¹ [IP] or in m³ kg⁻¹ [SI]
173-
( double TDryBulb // (i) Dry bulb temperature in °F [IP] or °C [SI]
174-
, double Pressure // (i) Atmospheric pressure in Psi [IP] or Pa [SI]
172+
double GetDryAirVolume // (o) Dry air volume ft³ lb⁻¹ [IP] or in m³ kg⁻¹ [SI]
173+
( double TDryBulb // (i) Dry bulb temperature in °F [IP] or °C [SI]
174+
, double Pressure // (i) Atmospheric pressure in Psi [IP] or Pa [SI]
175+
);
176+
177+
double GetTDryBulbFromEnthalpyAndHumRatio // (o) Dry-bulb temperature in °F [IP] or °C [SI]
178+
( double MoistAirEnthalpy // (i) Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
179+
, double HumRatio // (i) Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
180+
);
181+
182+
double GetHumRatioFromEnthalpyAndTDryBulb // (o) Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
183+
( double MoistAirEnthalpy // (i) Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
184+
, double TDryBulb // (i) Dry-bulb temperature in °F [IP] or °C [SI]
175185
);
176186

177187

src/fortran/psychrolib.f90

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ module psychrolib
6969
public :: GetDryAirEnthalpy
7070
public :: GetDryAirDensity
7171
public :: GetDryAirVolume
72+
public :: GetTDryBulbFromEnthalpyAndHumRatio
73+
public :: GetHumRatioFromEnthalpyAndTDryBulb
7274
public :: GetSatVapPres
7375
public :: GetSatHumRatio
7476
public :: GetSatAirEnthalpy
@@ -821,6 +823,52 @@ function GetDryAirVolume(TDryBulb, Pressure) result(DryAirVolume)
821823
end if
822824
end function GetDryAirVolume
823825

826+
function GetTDryBulbFromEnthalpyAndHumRatio(MoistAirEnthalpy, HumRatio) result(TDryBulb)
827+
!+ Return dry bulb temperature from enthalpy and humidity ratio.
828+
!+ Reference:
829+
!+ ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 30
830+
!+ Notes:
831+
!+ Based on the `GetMoistAirEnthalpy` function, rearranged for temperature.
832+
833+
real, intent(in) :: MoistAirEnthalpy
834+
!+ Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
835+
real, intent(in) :: HumRatio
836+
!+ Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
837+
real :: TDryBulb
838+
!+ Dry-bulb temperature in °F [IP] or °C [SI]
839+
840+
if (HumRatio < 0.0) then
841+
error stop "Error: humidity ratio is negative"
842+
end if
843+
844+
if (isIP()) then
845+
TDryBulb = (MoistAirEnthalpy - 1061.0 * HumRatio) / (0.240 + 0.444 * HumRatio)
846+
else
847+
TDryBulb = (MoistAirEnthalpy / 1000.0 - 2501.0 * HumRatio) / (1.006 + 1.86 * HumRatio)
848+
end if
849+
end function GetTDryBulbFromEnthalpyAndHumRatio
850+
851+
function GetHumRatioFromEnthalpyAndTDryBulb(MoistAirEnthalpy, TDryBulb) result(HumRatio)
852+
!+ Return humidity ratio from enthalpy and dry-bulb temperature.
853+
!+ Reference:
854+
!+ ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 30
855+
!+ Notes:
856+
!+ Based on the `GetMoistAirEnthalpy` function, rearranged for humidity ratio.
857+
858+
real, intent(in) :: MoistAirEnthalpy
859+
!+ Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
860+
real, intent(in) :: TDryBulb
861+
!+ Dry-bulb temperature in °F [IP] or °C [SI]
862+
real :: HumRatio
863+
!+ Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
864+
865+
if (isIP()) then
866+
HumRatio = (MoistAirEnthalpy - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb)
867+
else
868+
HumRatio = (MoistAirEnthalpy / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb)
869+
end if
870+
end function GetHumRatioFromEnthalpyAndTDryBulb
871+
824872

825873
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
826874
! Saturated Air Calculations

src/js/psychrolib.js

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,21 +555,49 @@ function Psychrometrics() {
555555
}
556556

557557
// Return dry-air volume given dry-bulb temperature and pressure.
558-
// Reference: ASHRAE Handbook - Fundamentals (2017) ch. 1
558+
// Reference: ASHRAE Handbook - Fundamentals (2017) ch. 1.
559559
// Notes: eqn 14 for the perfect gas relationship for dry air.
560560
// Eqn 1 for the universal gas constant.
561561
// The factor 144 in IP is for the conversion of Psi = lb in⁻² to lb ft⁻².
562562
this.GetDryAirVolume = function // (o) Dry air volume ft³ lb⁻¹ [IP] or in m³ kg⁻¹ [SI]
563563
( TDryBulb // (i) Dry bulb temperature in °F [IP] or °C [SI]
564564
, Pressure // (i) Atmospheric pressure in Psi [IP] or Pa [SI]
565565
) {
566-
567566
if (this.isIP())
568567
return R_DA_IP * this.GetTRankineFromTFahrenheit(TDryBulb) / (144. * Pressure);
569568
else
570569
return R_DA_SI * this.GetTKelvinFromTCelsius(TDryBulb) / Pressure;
571570
}
572571

572+
// Return dry bulb temperature from enthalpy and humidity ratio.
573+
// Reference: ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 30.
574+
// Notes: based on the `GetMoistAirEnthalpy` function, rearranged for temperature.
575+
this.GetTDryBulbFromEnthalpyAndHumRatio = function // (o) Dry-bulb temperature in °F [IP] or °C [SI]
576+
( MoistAirEnthalpy // (i) Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
577+
, HumRatio // (i) Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
578+
) {
579+
if (!(HumRatio >= 0.))
580+
throw new Error("Humidity ratio is negative");
581+
582+
if (this.isIP())
583+
return (MoistAirEnthalpy - 1061.0 * HumRatio) / (0.240 + 0.444 * HumRatio);
584+
else
585+
return (MoistAirEnthalpy / 1000.0 - 2501.0 * HumRatio) / (1.006 + 1.86 * HumRatio);
586+
}
587+
588+
// Return humidity ratio from enthalpy and dry-bulb temperature.
589+
// Reference: ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 30.
590+
// Notes: based on the `GetMoistAirEnthalpy` function, rearranged for humidity ratio.
591+
this.GetHumRatioFromEnthalpyAndTDryBulb = function // (o) Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻
592+
( MoistAirEnthalpy // (i) Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
593+
, TDryBulb // (i) Dry-bulb temperature in °F [IP] or °C [SI]
594+
) {
595+
if (this.isIP())
596+
return (MoistAirEnthalpy - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb);
597+
else
598+
return (MoistAirEnthalpy / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb);
599+
}
600+
573601

574602
/******************************************************************************************************
575603
* Saturated Air Calculations

src/python/psychrolib.py

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
import math
4646
from enum import Enum, auto
47+
from typing import Optional
4748

4849

4950
#######################################################################################################
@@ -119,7 +120,7 @@ def SetUnitSystem(Units: UnitSystem) -> None:
119120
else:
120121
PSYCHROLIB_TOLERANCE = 0.001
121122

122-
def GetUnitSystem() -> UnitSystem:
123+
def GetUnitSystem() -> Optional[UnitSystem]:
123124
"""
124125
Return system of units in use.
125126
@@ -799,6 +800,60 @@ def GetDryAirVolume(TDryBulb: float, Pressure: float) -> float:
799800
return DryAirVolume
800801

801802

803+
def GetTDryBulbFromEnthalpyAndHumRatio(MoistAirEnthalpy: float, HumRatio: float) -> float:
804+
"""
805+
Return dry bulb temperature from enthalpy and humidity ratio.
806+
807+
808+
Args:
809+
MoistAirEnthalpy : Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
810+
HumRatio : Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
811+
812+
Returns:
813+
Dry-bulb temperature in °F [IP] or °C [SI]
814+
815+
Reference:
816+
ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 30
817+
818+
Notes:
819+
Based on the `GetMoistAirEnthalpy` function, rearranged for temperature.
820+
821+
"""
822+
if HumRatio < 0:
823+
raise ValueError("Humidity ratio is negative")
824+
825+
if isIP():
826+
TDryBulb = (MoistAirEnthalpy - 1061.0 * HumRatio) / (0.240 + 0.444 * HumRatio)
827+
else:
828+
TDryBulb = (MoistAirEnthalpy / 1000.0 - 2501.0 * HumRatio) / (1.006 + 1.86 * HumRatio)
829+
return TDryBulb
830+
831+
def GetHumRatioFromEnthalpyAndTDryBulb(MoistAirEnthalpy: float, TDryBulb: float) -> float:
832+
"""
833+
Return humidity ratio from enthalpy and dry-bulb temperature.
834+
835+
836+
Args:
837+
MoistAirEnthalpy : Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
838+
TDryBulb : Dry-bulb temperature in °F [IP] or °C [SI]
839+
840+
Returns:
841+
Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
842+
843+
Reference:
844+
ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 30.
845+
846+
Notes:
847+
Based on the `GetMoistAirEnthalpy` function, rearranged for humidity ratio.
848+
849+
"""
850+
if isIP():
851+
HumRatio = (MoistAirEnthalpy - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb)
852+
else:
853+
HumRatio = (MoistAirEnthalpy / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb)
854+
return HumRatio
855+
856+
802857
#######################################################################################################
803858
# Saturated Air Calculations
804859
#######################################################################################################

src/vba/psychrolib.bas

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ Function GetSpecificHumFromHumRatio(ByVal HumRatio As Variant) As Variant
917917
' ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 9b
918918
'
919919
'
920-
Dim SpecificHum as Variant
920+
Dim SpecificHum As Variant
921921

922922
On Error GoTo ErrHandler
923923

@@ -1065,6 +1065,77 @@ ErrHandler:
10651065

10661066
End Function
10671067

1068+
Function GetTDryBulbFromEnthalpyAndHumRatio(ByVal MoistAirEnthalpy As Variant, ByVal HumRatio As Variant) As Variant
1069+
'
1070+
' Return dry bulb temperature from enthalpy and humidity ratio.
1071+
'
1072+
'
1073+
' Args:
1074+
' MoistAirEnthalpy : Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
1075+
' HumRatio : Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
1076+
'
1077+
' Returns:
1078+
' Dry-bulb temperature in °F [IP] or °C [SI]
1079+
'
1080+
' Reference:
1081+
' ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 30
1082+
'
1083+
' Notes:
1084+
' Based on the `GetMoistAirEnthalpy` function, rearranged for temperature.
1085+
'
1086+
1087+
On Error GoTo ErrHandler
1088+
1089+
If HumRatio < 0 Then
1090+
MyMsgBox ("Humidity ratio is negative")
1091+
GoTo ErrHandler
1092+
End If
1093+
1094+
If (isIP()) Then
1095+
GetTDryBulbFromEnthalpyAndHumRatio = (MoistAirEnthalpy - 1061.0 * HumRatio) / (0.24 + 0.444 * HumRatio)
1096+
Else:
1097+
GetTDryBulbFromEnthalpyAndHumRatio = (MoistAirEnthalpy / 1000.0 - 2501.0 * HumRatio) / (1.006 + 1.86 * HumRatio)
1098+
End If
1099+
Exit Function
1100+
1101+
ErrHandler:
1102+
GetTDryBulbFromEnthalpyAndHumRatio = CVErr(xlErrNA)
1103+
1104+
End Function
1105+
1106+
Function GetHumRatioFromEnthalpyAndTDryBulb(ByVal MoistAirEnthalpy As Variant, ByVal TDryBulb As Variant) As Variant
1107+
'
1108+
' Return humidity ratio from enthalpy and dry-bulb temperature.
1109+
'
1110+
'
1111+
' Args:
1112+
' MoistAirEnthalpy : Moist air enthalpy in Btu lb⁻¹ [IP] or J kg⁻¹
1113+
' TDryBulb : Dry-bulb temperature in °F [IP] or °C [SI]
1114+
'
1115+
' Returns:
1116+
' Humidity ratio in lb_H₂O lb_Air⁻¹ [IP] or kg_H₂O kg_Air⁻¹ [SI]
1117+
'
1118+
' Reference:
1119+
' ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn 30
1120+
'
1121+
' Notes:
1122+
' Based on the `GetMoistAirEnthalpy` function, rearranged for humidity ratio.
1123+
'
1124+
1125+
On Error GoTo ErrHandler
1126+
1127+
If (isIP()) Then
1128+
GetHumRatioFromEnthalpyAndTDryBulb = (MoistAirEnthalpy - 0.24 * TDryBulb) / (1061.0 + 0.444 * TDryBulb)
1129+
Else:
1130+
GetHumRatioFromEnthalpyAndTDryBulb = (MoistAirEnthalpy / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb)
1131+
End If
1132+
Exit Function
1133+
1134+
ErrHandler:
1135+
GetHumRatioFromEnthalpyAndTDryBulb = CVErr(xlErrNA)
1136+
1137+
End Function
1138+
10681139

10691140
'******************************************************************************************************
10701141
' Saturated Air Calculations

tests/js/test_psychrolib_ip.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ it('test_DryAir', function () {
133133
checkRelDiff(psyjs.GetDryAirEnthalpy(77), 18.498, 0.001)
134134
checkRelDiff(psyjs.GetDryAirVolume(77, 14.696), 13.5251, 0.001)
135135
checkRelDiff(psyjs.GetDryAirDensity(77, 14.696), 1/13.5251, 0.001)
136+
expect(psyjs.GetTDryBulbFromEnthalpyAndHumRatio(42.6168, 0.02)).to.be.closeTo(86, 0.05)
137+
checkRelDiff(psyjs.GetHumRatioFromEnthalpyAndTDryBulb(42.6168, 86), 0.02, 0.001)
136138
});
137139

138140

tests/js/test_psychrolib_si.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ it('test_DryAir', function () {
133133
checkRelDiff(psyjs.GetDryAirEnthalpy(25), 25148, 0.0003)
134134
checkRelDiff(psyjs.GetDryAirVolume(25, 101325), 0.8443, 0.001)
135135
checkRelDiff(psyjs.GetDryAirDensity(25, 101325), 1/0.8443, 0.001)
136+
expect(psyjs.GetTDryBulbFromEnthalpyAndHumRatio(81316, 0.02)).to.be.closeTo(30, 0.001)
137+
checkRelDiff(psyjs.GetHumRatioFromEnthalpyAndTDryBulb(81316, 30), 0.02, 0.001)
136138
});
137139

138140

0 commit comments

Comments
 (0)