GetTDewPointFromVapPres Function

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

Arguments

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

Return Value real


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

    ! Bounds and step size as a function of the system of units
    if (isIP()) then
        BOUNDS(1) = -148.0
        BOUNDS(2) =  392.0
    else
        BOUNDS(1) = -100.0
        BOUNDS(2) =  200.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

    ! 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