GetTDewPointFromVapPres Function

public function GetTDewPointFromVapPres(TDryBulb, VapPres) result(TDewPoint)

Return dew-point temperature given dry-bulb temperature and vapor pressure. References: ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn. 5 and 6 Notes: The dew point temperature is solved by inverting the equation giving water vapor pressure at saturation from temperature rather than using the regressions provided by ASHRAE (eqn. 37 and 38) which are much less accurate and have a narrower range of validity. The Newton-Raphson (NR) method is used on the logarithm of water vapour pressure as a function of temperature, which is a very smooth function Convergence is usually achieved in 3 to 5 iterations. TDryBulb is not really needed here, just used for convenience.

Arguments

Type IntentOptional AttributesName
real, intent(in) :: TDryBulb

Dry-bulb temperature in °F [IP] or °C [SI]

real, intent(in) :: VapPres

Partial pressure of water vapor in moist air in Psi [IP] or Pa [SI]

Return Value real

Dew-point temperature in °F [IP] or °C [SI]


Calls

proc~~gettdewpointfromvappres~~CallsGraph proc~gettdewpointfromvappres GetTDewPointFromVapPres proc~dlnpws_ dLnPws_ proc~gettdewpointfromvappres->proc~dlnpws_ proc~isip isIP proc~gettdewpointfromvappres->proc~isip proc~getsatvappres GetSatVapPres proc~gettdewpointfromvappres->proc~getsatvappres proc~dlnpws_->proc~isip proc~gettrankinefromtfahrenheit GetTRankineFromTFahrenheit proc~dlnpws_->proc~gettrankinefromtfahrenheit proc~gettkelvinfromtcelsius GetTKelvinFromTCelsius proc~dlnpws_->proc~gettkelvinfromtcelsius proc~getsatvappres->proc~isip proc~getsatvappres->proc~gettrankinefromtfahrenheit proc~getsatvappres->proc~gettkelvinfromtcelsius

Called by

proc~~gettdewpointfromvappres~~CalledByGraph proc~gettdewpointfromvappres GetTDewPointFromVapPres proc~gettdewpointfromhumratio GetTDewPointFromHumRatio proc~gettdewpointfromhumratio->proc~gettdewpointfromvappres proc~gettdewpointfromrelhum GetTDewPointFromRelHum proc~gettdewpointfromrelhum->proc~gettdewpointfromvappres proc~calcpsychrometricsfromrelhum CalcPsychrometricsFromRelHum proc~calcpsychrometricsfromrelhum->proc~gettdewpointfromhumratio proc~gettwetbulbfromhumratio GetTWetBulbFromHumRatio proc~calcpsychrometricsfromrelhum->proc~gettwetbulbfromhumratio proc~gettwetbulbfromhumratio->proc~gettdewpointfromhumratio proc~calcpsychrometricsfromtwetbulb CalcPsychrometricsFromTWetBulb proc~calcpsychrometricsfromtwetbulb->proc~gettdewpointfromhumratio proc~gettdewpointfromtwetbulb GetTDewPointFromTWetBulb proc~gettdewpointfromtwetbulb->proc~gettdewpointfromhumratio proc~gettwetbulbfromtdewpoint GetTWetBulbFromTDewPoint proc~gettwetbulbfromtdewpoint->proc~gettwetbulbfromhumratio proc~calcminimaldxheating CalcMinimalDXHeating proc~calcminimaldxheating->proc~gettwetbulbfromhumratio proc~calcminimaldxcooling CalcMinimalDXCooling proc~calcminimaldxcooling->proc~gettwetbulbfromhumratio proc~gettwetbulbfromrelhum GetTWetBulbFromRelHum proc~gettwetbulbfromrelhum->proc~gettwetbulbfromhumratio proc~calcpsychrometricsfromtdewpoint CalcPsychrometricsFromTDewPoint proc~calcpsychrometricsfromtdewpoint->proc~gettwetbulbfromhumratio proc~simminimaldxheating SimMinimalDXHeating proc~simminimaldxheating->proc~calcminimaldxheating proc~simminimaldxcooling SimMinimalDXCooling proc~simminimaldxcooling->proc~calcminimaldxcooling

Contents


Source Code

  function GetTDewPointFromVapPres(TDryBulb, VapPres) result(TDewPoint)
    !+ Return dew-point temperature given dry-bulb temperature and vapor pressure.
    !+ References:
    !+ ASHRAE Handbook - Fundamentals (2017) ch. 1 eqn. 5 and 6
    !+ Notes:
    !+ The dew point temperature is solved by inverting the equation giving water vapor pressure
    !+ at saturation from temperature rather than using the regressions provided
    !+ by ASHRAE (eqn. 37 and 38) which are much less accurate and have a
    !+ narrower range of validity.
    !+ The Newton-Raphson (NR) method is used on the logarithm of water vapour
    !+ pressure as a function of temperature, which is a very smooth function
    !+ Convergence is usually achieved in 3 to 5 iterations.
    !+ TDryBulb is not really needed here, just used for convenience.

    real, intent(in)    ::  TDryBulb
      !+ Dry-bulb temperature in °F [IP] or °C [SI]
    real, intent(in)    ::  VapPres
      !+ Partial pressure of water vapor in moist air in Psi [IP] or Pa [SI]
    real                ::  TDewPoint
      !+ Dew-point temperature in °F [IP] or °C [SI]
    real                ::  lnVP
      !+ Natural logarithm of partial pressure of water vapor pressure in moist air
    real                ::  d_lnVP
      !+ Derivative of function, calculated numerically
    real                ::  lnVP_iter
      !+ Value of log of vapor water pressure used in NR calculation
    real                ::  TDewPoint_iter
      !+ Value of TDewPoint used in NR calculation
    real, dimension(2)  ::  BOUNDS
      !+ Valid temperature range in °F [IP] or °C [SI]
    integer             :: index
      !+ Index used in the calculation
     real ::  T_WATER_FREEZE, T_WATER_FREEZE_LOW, T_WATER_FREEZE_HIGH, PWS_FREEZE_LOW, PWS_FREEZE_HIGH

    ! Bounds and step size as a function of the system of units
    if (isIP()) then
        BOUNDS(1) = -148.0
        BOUNDS(2) =  392.0
        T_WATER_FREEZE = 32.
    else
        BOUNDS(1) = -100.0
        BOUNDS(2) =  200.0
        T_WATER_FREEZE = 0.
    end if

    ! Validity check -- bounds outside which a solution cannot be found
    if (VapPres < GetSatVapPres(BOUNDS(1)) .or. VapPres > GetSatVapPres(BOUNDS(2))) then
      error stop "Error: partial pressure of water vapor is outside range of validity of equations"
    end if

    ! Vapor pressure contained within the discontinuity of the Pws function: return temperature of freezing
    T_WATER_FREEZE_LOW = T_WATER_FREEZE - PSYCHROLIB_TOLERANCE / 10.        ! Temperature just below freezing
    T_WATER_FREEZE_LOW = T_WATER_FREEZE - PSYCHROLIB_TOLERANCE / 10.        ! Temperature just below freezing
    T_WATER_FREEZE_HIGH = T_WATER_FREEZE + PSYCHROLIB_TOLERANCE             ! Temperature just above freezing
    PWS_FREEZE_LOW = GetSatVapPres(T_WATER_FREEZE_LOW)
    PWS_FREEZE_HIGH = GetSatVapPres(T_WATER_FREEZE_HIGH)

    ! Restrict iteration to either left or right part of the saturation vapor pressure curve
    ! to avoid iterating back and forth across the discontinuity of the curve at the freezing point
    ! When the partial pressure of water vapor is within the discontinuity of GetSatVapPres,
    ! simply return the freezing point of water.
    if (VapPres < PWS_FREEZE_LOW) then
        BOUNDS(2) = T_WATER_FREEZE_LOW
    else if (VapPres > PWS_FREEZE_HIGH) then
        BOUNDS(1) = T_WATER_FREEZE_HIGH
    else
        TDewPoint = T_WATER_FREEZE
        return
    end if

    ! We use NR to approximate the solution.
    TDewPoint = TDryBulb
    lnVP = log(VapPres)
    index = 1

    do while (.true.)
      TDewPoint_iter = TDewPoint ! TDewPoint_iter used in NR calculation
      lnVP_iter = log(GetSatVapPres(TDewPoint_iter))

      ! Derivative of function, calculated analytically
      d_lnVP = dLnPws_(TDewPoint_iter)

      ! New estimate, bounded by the search domain defined above
      TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP
      TDewPoint = max(TDewPoint, BOUNDS(1))
      TDewPoint = min(TDewPoint, BOUNDS(2))

      if (abs(TDewPoint - TDewPoint_iter) <= PSYCHROLIB_TOLERANCE) then
        exit
      end if

      if (index > MAX_ITER_COUNT) then
        error stop "Convergence not reached in GetTDewPointFromVapPres. Stopping."
      end if

      index = index + 1
    end do

  TDewPoint = min(TDewPoint, TDryBulb)
  end function GetTDewPointFromVapPres