Purchasedairmanager.f90 Source File

This File Depends On

sourcefile~~purchasedairmanager.f90~~EfferentGraph sourcefile~purchasedairmanager.f90 Purchasedairmanager.f90 sourcefile~schedulemanager.f90 ScheduleManager.f90 sourcefile~schedulemanager.f90->sourcefile~purchasedairmanager.f90 sourcefile~datazoneequipment.f90 DataZoneEquipment.f90 sourcefile~schedulemanager.f90->sourcefile~datazoneequipment.f90 sourcefile~nodeinputmanager.f90 NodeInputManager.f90 sourcefile~schedulemanager.f90->sourcefile~nodeinputmanager.f90 sourcefile~sqlitefortranroutines.f90 SQLiteFortranRoutines.f90 sourcefile~schedulemanager.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~outputprocessor.f90 OutputProcessor.f90 sourcefile~schedulemanager.f90->sourcefile~outputprocessor.f90 sourcefile~dataloopnode.f90 DataLoopNode.f90 sourcefile~dataloopnode.f90->sourcefile~purchasedairmanager.f90 sourcefile~outairnodemanager.f90 OutAirNodeManager.f90 sourcefile~dataloopnode.f90->sourcefile~outairnodemanager.f90 sourcefile~dataloopnode.f90->sourcefile~datazoneequipment.f90 sourcefile~dataloopnode.f90->sourcefile~nodeinputmanager.f90 sourcefile~branchnodeconnections.f90 BranchNodeConnections.f90 sourcefile~dataloopnode.f90->sourcefile~branchnodeconnections.f90 sourcefile~outairnodemanager.f90->sourcefile~purchasedairmanager.f90 sourcefile~datahvacglobals.f90 DataHVACGlobals.f90 sourcefile~datahvacglobals.f90->sourcefile~purchasedairmanager.f90 sourcefile~general.f90 General.f90 sourcefile~datahvacglobals.f90->sourcefile~general.f90 sourcefile~datahvacglobals.f90->sourcefile~datazoneequipment.f90 sourcefile~general.f90->sourcefile~purchasedairmanager.f90 sourcefile~general.f90->sourcefile~schedulemanager.f90 sourcefile~reportsizingmanager.f90 ReportSizingManager.f90 sourcefile~general.f90->sourcefile~reportsizingmanager.f90 sourcefile~psychroutines.f90 PsychRoutines.f90 sourcefile~general.f90->sourcefile~psychroutines.f90 sourcefile~general.f90->sourcefile~datazoneequipment.f90 sourcefile~general.f90->sourcefile~nodeinputmanager.f90 sourcefile~dataenvironment.f90 DataEnvironment.f90 sourcefile~general.f90->sourcefile~dataenvironment.f90 sourcefile~dataheatbalance.f90 DataHeatBalance.f90 sourcefile~general.f90->sourcefile~dataheatbalance.f90 sourcefile~general.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~general.f90->sourcefile~branchnodeconnections.f90 sourcefile~general.f90->sourcefile~outputprocessor.f90 sourcefile~fluidproperties.f90 FluidProperties.f90 sourcefile~general.f90->sourcefile~fluidproperties.f90 sourcefile~datacontaminantbalance.f90 DataContaminantBalance.f90 sourcefile~datacontaminantbalance.f90->sourcefile~purchasedairmanager.f90 sourcefile~datacontaminantbalance.f90->sourcefile~outairnodemanager.f90 sourcefile~datacontaminantbalance.f90->sourcefile~nodeinputmanager.f90 sourcefile~reportsizingmanager.f90->sourcefile~purchasedairmanager.f90 sourcefile~psychroutines.f90->sourcefile~purchasedairmanager.f90 sourcefile~psychroutines.f90->sourcefile~outairnodemanager.f90 sourcefile~psychroutines.f90->sourcefile~nodeinputmanager.f90 sourcefile~dataprecisionglobals.f90 DataPrecisionGlobals.f90 sourcefile~dataprecisionglobals.f90->sourcefile~purchasedairmanager.f90 sourcefile~dataprecisionglobals.f90->sourcefile~schedulemanager.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataloopnode.f90 sourcefile~dataprecisionglobals.f90->sourcefile~outairnodemanager.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datahvacglobals.f90 sourcefile~dataprecisionglobals.f90->sourcefile~general.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datacontaminantbalance.f90 sourcefile~dataprecisionglobals.f90->sourcefile~reportsizingmanager.f90 sourcefile~dataprecisionglobals.f90->sourcefile~psychroutines.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datazoneequipment.f90 sourcefile~dataglobals.f90 DataGlobals.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataglobals.f90 sourcefile~dataprecisionglobals.f90->sourcefile~nodeinputmanager.f90 sourcefile~dataipshortcuts.f90 DataIPShortCuts.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataipshortcuts.f90 sourcefile~datazoneenergydemands.f90 DataZoneEnergyDemands.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datazoneenergydemands.f90 sourcefile~dataheatbalfansys.f90 DataHeatBalFanSys.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataheatbalfansys.f90 sourcefile~datasizing.f90 DataSizing.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datasizing.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataenvironment.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataheatbalance.f90 sourcefile~inputprocessor.f90 InputProcessor.f90 sourcefile~dataprecisionglobals.f90->sourcefile~inputprocessor.f90 sourcefile~datainterfaces.f90 DataInterfaces.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datainterfaces.f90 sourcefile~datasystemvariables.f90 DataSystemVariables.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datasystemvariables.f90 sourcefile~datasurfaces.f90 DataSurfaces.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datasurfaces.f90 sourcefile~dataruntimelanguage.f90 DataRuntimeLanguage.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataruntimelanguage.f90 sourcefile~datavectortypes.f90 DataVectorTypes.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datavectortypes.f90 sourcefile~databsdfwindow.f90 DataBSDFWindow.f90 sourcefile~dataprecisionglobals.f90->sourcefile~databsdfwindow.f90 sourcefile~dataprecisionglobals.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~outputreportpredefined.f90 OutputReportPredefined.f90 sourcefile~dataprecisionglobals.f90->sourcefile~outputreportpredefined.f90 sourcefile~dataroomair.f90 DataRoomAir.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataroomair.f90 sourcefile~dataprecisionglobals.f90->sourcefile~outputprocessor.f90 sourcefile~dataprecisionglobals.f90->sourcefile~fluidproperties.f90 sourcefile~dataerrortracking.f90 DataErrorTracking.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataerrortracking.f90 sourcefile~datacomplexfenestration.f90 DataComplexFenestration.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datacomplexfenestration.f90 sourcefile~dataequivalentlayerwindow.f90 DataEquivalentLayerWindow.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataequivalentlayerwindow.f90 sourcefile~datazoneequipment.f90->sourcefile~purchasedairmanager.f90 sourcefile~dataglobals.f90->sourcefile~purchasedairmanager.f90 sourcefile~dataglobals.f90->sourcefile~schedulemanager.f90 sourcefile~dataglobals.f90->sourcefile~dataloopnode.f90 sourcefile~dataglobals.f90->sourcefile~outairnodemanager.f90 sourcefile~dataglobals.f90->sourcefile~datahvacglobals.f90 sourcefile~dataglobals.f90->sourcefile~general.f90 sourcefile~dataglobals.f90->sourcefile~datacontaminantbalance.f90 sourcefile~dataglobals.f90->sourcefile~reportsizingmanager.f90 sourcefile~dataglobals.f90->sourcefile~psychroutines.f90 sourcefile~dataglobals.f90->sourcefile~datazoneequipment.f90 sourcefile~dataglobals.f90->sourcefile~nodeinputmanager.f90 sourcefile~dataglobals.f90->sourcefile~dataipshortcuts.f90 sourcefile~dataglobals.f90->sourcefile~datasizing.f90 sourcefile~dataglobals.f90->sourcefile~dataenvironment.f90 sourcefile~dataglobals.f90->sourcefile~dataheatbalance.f90 sourcefile~dataglobals.f90->sourcefile~inputprocessor.f90 sourcefile~dataglobals.f90->sourcefile~datasurfaces.f90 sourcefile~dataglobals.f90->sourcefile~dataruntimelanguage.f90 sourcefile~dataglobals.f90->sourcefile~databsdfwindow.f90 sourcefile~dataglobals.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~dataglobals.f90->sourcefile~outputreportpredefined.f90 sourcefile~dataglobals.f90->sourcefile~dataroomair.f90 sourcefile~dataglobals.f90->sourcefile~branchnodeconnections.f90 sourcefile~databranchnodeconnections.f90 DataBranchNodeConnections.f90 sourcefile~dataglobals.f90->sourcefile~databranchnodeconnections.f90 sourcefile~dataglobals.f90->sourcefile~outputprocessor.f90 sourcefile~dataglobals.f90->sourcefile~fluidproperties.f90 sourcefile~sortandstringutilities.f90 SortAndStringUtilities.f90 sourcefile~dataglobals.f90->sourcefile~sortandstringutilities.f90 sourcefile~dataoutputs.f90 DataOutputs.f90 sourcefile~dataglobals.f90->sourcefile~dataoutputs.f90 sourcefile~dataglobalconstants.f90 DataGlobalConstants.f90 sourcefile~dataglobals.f90->sourcefile~dataglobalconstants.f90 sourcefile~dataglobals.f90->sourcefile~datacomplexfenestration.f90 sourcefile~dataglobals.f90->sourcefile~dataequivalentlayerwindow.f90 sourcefile~nodeinputmanager.f90->sourcefile~purchasedairmanager.f90 sourcefile~nodeinputmanager.f90->sourcefile~outairnodemanager.f90 sourcefile~nodeinputmanager.f90->sourcefile~datazoneequipment.f90 sourcefile~dataipshortcuts.f90->sourcefile~purchasedairmanager.f90 sourcefile~dataipshortcuts.f90->sourcefile~schedulemanager.f90 sourcefile~dataipshortcuts.f90->sourcefile~general.f90 sourcefile~dataipshortcuts.f90->sourcefile~inputprocessor.f90 sourcefile~dataipshortcuts.f90->sourcefile~outputprocessor.f90 sourcefile~datazoneenergydemands.f90->sourcefile~purchasedairmanager.f90 sourcefile~dataheatbalfansys.f90->sourcefile~purchasedairmanager.f90 sourcefile~datasizing.f90->sourcefile~purchasedairmanager.f90 sourcefile~datasizing.f90->sourcefile~datazoneequipment.f90 sourcefile~datasizing.f90->sourcefile~inputprocessor.f90 sourcefile~dataenvironment.f90->sourcefile~purchasedairmanager.f90 sourcefile~dataenvironment.f90->sourcefile~schedulemanager.f90 sourcefile~dataenvironment.f90->sourcefile~outairnodemanager.f90 sourcefile~dataenvironment.f90->sourcefile~psychroutines.f90 sourcefile~dataenvironment.f90->sourcefile~nodeinputmanager.f90 sourcefile~dataenvironment.f90->sourcefile~dataheatbalance.f90 sourcefile~dataenvironment.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~dataenvironment.f90->sourcefile~outputprocessor.f90 sourcefile~dataheatbalance.f90->sourcefile~purchasedairmanager.f90 sourcefile~dataheatbalance.f90->sourcefile~datazoneequipment.f90 sourcefile~dataheatbalance.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~dataheatbalance.f90->sourcefile~outputprocessor.f90 sourcefile~inputprocessor.f90->sourcefile~purchasedairmanager.f90 sourcefile~inputprocessor.f90->sourcefile~schedulemanager.f90 sourcefile~inputprocessor.f90->sourcefile~outairnodemanager.f90 sourcefile~inputprocessor.f90->sourcefile~general.f90 sourcefile~inputprocessor.f90->sourcefile~datazoneequipment.f90 sourcefile~inputprocessor.f90->sourcefile~nodeinputmanager.f90 sourcefile~inputprocessor.f90->sourcefile~dataheatbalance.f90 sourcefile~inputprocessor.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~inputprocessor.f90->sourcefile~branchnodeconnections.f90 sourcefile~inputprocessor.f90->sourcefile~outputprocessor.f90 sourcefile~inputprocessor.f90->sourcefile~fluidproperties.f90 sourcefile~inputprocessor.f90->sourcefile~dataglobalconstants.f90 sourcefile~datainterfaces.f90->sourcefile~purchasedairmanager.f90 sourcefile~datainterfaces.f90->sourcefile~schedulemanager.f90 sourcefile~datainterfaces.f90->sourcefile~outairnodemanager.f90 sourcefile~datainterfaces.f90->sourcefile~general.f90 sourcefile~datainterfaces.f90->sourcefile~reportsizingmanager.f90 sourcefile~datainterfaces.f90->sourcefile~psychroutines.f90 sourcefile~datainterfaces.f90->sourcefile~datazoneequipment.f90 sourcefile~datainterfaces.f90->sourcefile~nodeinputmanager.f90 sourcefile~datainterfaces.f90->sourcefile~dataenvironment.f90 sourcefile~datainterfaces.f90->sourcefile~dataheatbalance.f90 sourcefile~datainterfaces.f90->sourcefile~inputprocessor.f90 sourcefile~datainterfaces.f90->sourcefile~dataruntimelanguage.f90 sourcefile~datainterfaces.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~datainterfaces.f90->sourcefile~branchnodeconnections.f90 sourcefile~datainterfaces.f90->sourcefile~outputprocessor.f90 sourcefile~datainterfaces.f90->sourcefile~fluidproperties.f90 sourcefile~datastringglobals.f90 DataStringGlobals.f90 sourcefile~datastringglobals.f90->sourcefile~schedulemanager.f90 sourcefile~datastringglobals.f90->sourcefile~general.f90 sourcefile~datastringglobals.f90->sourcefile~inputprocessor.f90 sourcefile~datastringglobals.f90->sourcefile~datasystemvariables.f90 sourcefile~datastringglobals.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~datastringglobals.f90->sourcefile~outputprocessor.f90 sourcefile~datasystemvariables.f90->sourcefile~schedulemanager.f90 sourcefile~datasystemvariables.f90->sourcefile~inputprocessor.f90 sourcefile~datasystemvariables.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~datasystemvariables.f90->sourcefile~outputprocessor.f90 sourcefile~datasurfaces.f90->sourcefile~general.f90 sourcefile~datasurfaces.f90->sourcefile~datacontaminantbalance.f90 sourcefile~datasurfaces.f90->sourcefile~dataheatbalance.f90 sourcefile~datasurfaces.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~dataruntimelanguage.f90->sourcefile~general.f90 sourcefile~datavectortypes.f90->sourcefile~dataheatbalance.f90 sourcefile~datavectortypes.f90->sourcefile~datasurfaces.f90 sourcefile~datavectortypes.f90->sourcefile~databsdfwindow.f90 sourcefile~databsdfwindow.f90->sourcefile~dataheatbalance.f90 sourcefile~databsdfwindow.f90->sourcefile~datasurfaces.f90 sourcefile~sqlitefortranroutines.f90->sourcefile~reportsizingmanager.f90 sourcefile~sqlitefortranroutines.f90->sourcefile~outputprocessor.f90 sourcefile~outputreportpredefined.f90->sourcefile~reportsizingmanager.f90 sourcefile~outputreportpredefined.f90->sourcefile~outputprocessor.f90 sourcefile~dataroomair.f90->sourcefile~sqlitefortranroutines.f90 sourcefile~branchnodeconnections.f90->sourcefile~datazoneequipment.f90 sourcefile~branchnodeconnections.f90->sourcefile~nodeinputmanager.f90 sourcefile~databranchnodeconnections.f90->sourcefile~branchnodeconnections.f90 sourcefile~outputprocessor.f90->sourcefile~nodeinputmanager.f90 sourcefile~fluidproperties.f90->sourcefile~nodeinputmanager.f90 sourcefile~dataerrortracking.f90->sourcefile~nodeinputmanager.f90 sourcefile~sortandstringutilities.f90->sourcefile~inputprocessor.f90 sourcefile~sortandstringutilities.f90->sourcefile~outputprocessor.f90 sourcefile~dataoutputs.f90->sourcefile~inputprocessor.f90 sourcefile~dataoutputs.f90->sourcefile~outputprocessor.f90 sourcefile~dataglobalconstants.f90->sourcefile~outputprocessor.f90 sourcefile~datacomplexfenestration.f90->sourcefile~dataheatbalance.f90 sourcefile~dataequivalentlayerwindow.f90->sourcefile~dataheatbalance.f90
Help

Files Dependent On This One

sourcefile~~purchasedairmanager.f90~~AfferentGraph sourcefile~purchasedairmanager.f90 Purchasedairmanager.f90 sourcefile~systemreports.f90 SystemReports.f90 sourcefile~purchasedairmanager.f90->sourcefile~systemreports.f90 sourcefile~zoneequipmentmanager.f90 Zoneequipmentmanager.f90 sourcefile~purchasedairmanager.f90->sourcefile~zoneequipmentmanager.f90 sourcefile~simulationmanager.f90 SimulationManager.f90 sourcefile~systemreports.f90->sourcefile~simulationmanager.f90 sourcefile~utilityroutines.f90 UtilityRoutines.f90 sourcefile~systemreports.f90->sourcefile~utilityroutines.f90 sourcefile~hvacmanager.f90 HVACManager.f90 sourcefile~systemreports.f90->sourcefile~hvacmanager.f90 sourcefile~zoneequipmentmanager.f90->sourcefile~hvacmanager.f90 sourcefile~sizingmanager.f90 SizingManager.f90 sourcefile~zoneequipmentmanager.f90->sourcefile~sizingmanager.f90 sourcefile~simulationmanager.f90->sourcefile~utilityroutines.f90 sourcefile~energyplus.f90 EnergyPlus.f90 sourcefile~simulationmanager.f90->sourcefile~energyplus.f90 sourcefile~hvacmanager.f90->sourcefile~simulationmanager.f90 sourcefile~heatbalanceairmanager.f90 HeatBalanceAirManager.f90 sourcefile~hvacmanager.f90->sourcefile~heatbalanceairmanager.f90 sourcefile~heatbalanceairmanager.f90->sourcefile~simulationmanager.f90 sourcefile~heatbalancesurfacemanager.f90 HeatBalanceSurfaceManager.f90 sourcefile~heatbalanceairmanager.f90->sourcefile~heatbalancesurfacemanager.f90 sourcefile~heatbalancesurfacemanager.f90->sourcefile~simulationmanager.f90 sourcefile~heatbalancemanager.f90 HeatBalanceManager.f90 sourcefile~heatbalancesurfacemanager.f90->sourcefile~heatbalancemanager.f90 sourcefile~heatbalancemanager.f90->sourcefile~simulationmanager.f90 sourcefile~heatbalancemanager.f90->sourcefile~sizingmanager.f90 sourcefile~sizingmanager.f90->sourcefile~simulationmanager.f90
Help


Source Code

MODULE PurchasedAirManager

  ! Module containing data and routines dealing with Ideal Loads Air System (formerly PURCHASED AIR).

  ! MODULE INFORMATION:
  !       AUTHOR         Russ Taylor
  !       DATE WRITTEN   May 1997
  !       MODIFIED       Fred Buhl Dec 1999
  !                      B. Griffith Dec 2006. added OA lookup function, moved getinputflag up to Module
  !                      M. Witte June 2011, add new features including DCV, economizer, dehumidification and humidification
  !                      NOTE: MJW Sep 13, 2011:  Still need to review checks for negative loads and impossible supply temps???
  !                           There are no Deallocate statements in here - should there be?
  !       RE-ENGINEERED  na

  ! PURPOSE OF THIS MODULE:
  ! To encapsulate the data and algorithms required to simulate the
  ! Zone Ideal Loads Air System component. This component supplies hot or cold air
  ! at a fixed or variable temperature to a zone to meet the zone load.
  ! With the June 2011 enhancements it will also supply outdoor air with optional demand-controlled ventilation
  ! and economizer controls, plus new options for controlling zone humidity.

  ! METHODOLOGY EMPLOYED:
  ! The user can choose via input the max/min hot and cold supply air
  ! temperature and humidity ratio. The air mass flow rate is chosen
  ! to meet the (remaining) zone load or based on the outdoor air flow requirement.
  ! If the outdoor air flow sets the flow rate, the supply air temperature and
  ! humidity ratio are adjusted to meet the zone load.

  ! REFERENCES: none

  ! OTHER NOTES: none

  ! USE STATEMENTS:
  ! Use statements for data only modules
    USE DataPrecisionGlobals
    USE DataGlobals
    USE DataHVACGlobals
    USE DataHeatBalFanSys, ONLY: ZoneAirHumRat, ZoneThermostatSetPointHi, ZoneThermostatSetPointLo
    Use DataEnvironment, ONLY: StdBaroPress, OutBaroPress, OutHumRat, OutEnthalpy, StdRhoAir
    USE DataInterfaces

  ! Use statements for access to subroutines in other modules
    USE ScheduleManager
    USE Psychrometrics,  ONLY: PsyRhoAirFnPbTdbW,PsyHFnTdbW,PsyTdbFnHW,PsyCpAirFnWTdb,PsyTsatFnHPb,PsyWFnTdbH,PsyWFnTdbRhPb

IMPLICIT NONE         ! Enforce explicit typing of all variables

PRIVATE ! Everything private unless explicitly made public

  !MODULE PARAMETER DEFINITIONS:
          ! MODULE PARAMETER DEFINITIONS:
  ! Heating and Cooling Limit type parameters
    INTEGER, PARAMETER :: NoLimit                     = 1
    INTEGER, PARAMETER :: LimitFlowRate               = 2
    INTEGER, PARAMETER :: LimitCapacity               = 3
    INTEGER, PARAMETER :: LimitFlowRateAndCapacity    = 4
    CHARACTER(len=*), DIMENSION(4), PARAMETER :: cLimitType=  &
       (/'NoLimit                 ',  &
         'LimitFlowRate           ',  &
         'LimitCapacity           ',  &
         'LimitFlowRateAndCapacity'/)
  ! Dehumidification and Humidification control type parameters
    INTEGER, PARAMETER :: None                        = 1
    INTEGER, PARAMETER :: ConstantSensibleHeatRatio   = 2
    INTEGER, PARAMETER :: Humidistat                  = 3
    INTEGER, PARAMETER :: ConstantSupplyHumidityRatio = 4
  ! Demand controlled ventilation type parameters
    INTEGER, PARAMETER :: NoDCV                       = 1
    INTEGER, PARAMETER :: OccupancySchedule           = 2
    INTEGER, PARAMETER :: CO2Setpoint                 = 3
  ! Outdoor air economizer type parameters
    INTEGER, PARAMETER :: NoEconomizer                = 1
    INTEGER, PARAMETER :: DifferentialDryBulb         = 2
    INTEGER, PARAMETER :: DifferentialEnthalpy        = 3
  ! Heat recovery type parameters
    INTEGER, PARAMETER :: NoHeatRecovery              = 1
    INTEGER, PARAMETER :: Sensible                    = 2
    INTEGER, PARAMETER :: Enthalpy                    = 3
  ! Operating mode parameters
    INTEGER, PARAMETER :: Off                       = 0
    INTEGER, PARAMETER :: Heat                      = 1
    INTEGER, PARAMETER :: Cool                      = 2
    INTEGER, PARAMETER :: Deadband                  = 3
  ! Delta humidity ratio limit, 0.00025 equals delta between 45F dewpoint and 46F dewpoint
  ! used to prevent dividing by near zero
    REAL(r64), PARAMETER :: SmallDeltaHumRat = 0.00025d0

  ! DERIVED TYPE DEFINITIONS:
    TYPE ZonePurchasedAir
      CHARACTER(len=MaxNameLength) :: cObjectName  =' ' ! Name of the object from IDD
      CHARACTER(len=MaxNameLength) :: Name = ' '        ! Name or identifier of this piece of equipment
      CHARACTER(len=MaxNameLength) :: AvailSched   = ' ' ! System availablity schedule
      INTEGER   :: AvailSchedPtr            = 0          ! Index to system availability schedule
      INTEGER   :: ZoneSupplyAirNodeNum    = 0          ! Node number of zone supply air node for purchased air
      INTEGER   :: ZoneExhaustAirNodeNum   = 0          ! Node number of zone exhaust air node for purchased air
      INTEGER   :: ZoneRecircAirNodeNum    = 0          ! Node number of recirculation air node for purchased air
                                                        !   same as exhaust node if specified, otherwise zone return node
      REAL(r64) :: MaxHeatSuppAirTemp      = 0.0d0      ! Maximum supply air temperature for heating [C]
      REAL(r64) :: MinCoolSuppAirTemp      = 0.0d0      ! Minimum supply air temperature for cooling [C]
      REAL(r64) :: MaxHeatSuppAirHumRat    = 0.0d0      ! Maximum supply heating air humidity ratio [kg water/kg dry air]
      REAL(r64) :: MinCoolSuppAirHumRat    = 0.0d0      ! Minimum supply cooling air humidity ratio [kg water/kg dry air]
      INTEGER   :: HeatingLimit            = 0          ! Heating capacity limit type - NoLimit, LimitFlowRate, LimitCapacity,
                                                        !       or LimitFlowRateAndCapacity
      REAL(r64) :: MaxHeatVolFlowRate      = 0.0d0      ! Maximum heating supply air flow[m3/s]
      REAL(r64) :: MaxHeatSensCap          = 0.0d0      ! Maximum heating sensible capacity [W]
      INTEGER   :: CoolingLimit            = 0          ! Cooling capacity limit type - NoLimit, LimitFlowRate, LimitCapacity,
                                                        !       or LimitFlowRateAndCapacity
      REAL(r64) :: MaxCoolVolFlowRate      = 0.0d0      ! Maximum cooling supply air flow [m3/s]
      REAL(r64) :: MaxCoolTotCap           = 0.0d0      ! Maximum cooling total capacity [W]
      CHARACTER(len=MaxNameLength) :: HeatSched   = ' ' ! Heating availablity schedule
      INTEGER   :: HeatSchedPtr            = 0          ! Index to heating availability schedule
      CHARACTER(len=MaxNameLength) :: CoolSched   = ' ' ! Cooling availability schedule
      INTEGER   :: CoolSchedPtr            = 0          ! Index to the cooling availability schedule
      INTEGER   :: DehumidCtrlType         = 0          ! Dehumidification control type - ConstantSensibleHeatRatio,
                                                        !      Humidistat, or ConstantSupplyHumidityRatio
      REAL(r64) :: CoolSHR                 = 0.0d0      ! Cooling sensible heat ratio
      INTEGER   :: HumidCtrlType           = 0          ! Humidification control type - None,
                                                        !      Humidistat, or ConstantSupplyHumidityRatio
      INTEGER   :: OARequirementsPtr       = 0          ! Index to DesignSpecification:OutdoorAir object
      INTEGER   :: DCVType                 = 0          ! Demand controlled ventilation type - None,
                                                        !      OccupancySchedule, or CO2Setpoint
      INTEGER   :: EconomizerType          = 0          ! Outdoor air economizer type - NoEconomizer,
                                                        !      DifferentialDryBulb, or DifferentialEnthalpy
      LOGICAL   :: OutdoorAir              = .false.    ! Is there outdoor air?
      INTEGER   :: OutdoorAirNodeNum       = 0          ! Node number of the outdoor air inlet node
      INTEGER   :: HtRecType               = 0          ! Outdoor air heat recovery type - None, Sensible, Enthalpy
      REAL(r64) :: HtRecSenEff             = 0.0d0      ! Sensible heat recovery effectiveness
      REAL(r64) :: HtRecLatEff             = 0.0d0      ! Latent heat recovery effectiveness

      INTEGER   :: OAFlowFracSchPtr        = 0          ! Fraction schedule applied to total OA requirement

      REAL(r64) :: MaxHeatMassFlowRate     = 0.0d0      ! The maximum heating air mass flow rate [kg/s]
      REAL(r64) :: MaxCoolMassFlowRate     = 0.0d0      ! The maximum cooling air mass flow rate [kg/s]
      LOGICAL   :: EMSOverrideMdotOn       = .FALSE.    ! if true, then EMS is calling to override supply mass flow rate
      REAL(r64) :: EMSValueMassFlowRate    = 0.0d0      ! Value EMS is directing to use for supply mass flow rate [kg/s]
      LOGICAL   :: EMSOverrideOAMdotOn     = .FALSE.    ! if true, then EMS is calling to override OA mass flow rate
      REAL(r64) :: EMSValueOAMassFlowRate  = 0.0d0      ! Value EMS is directing to use for OA mass flow rate [kg/s]
      LOGICAL   :: EMSOverrideSupplyTempOn = .FALSE.    ! if true, then EMS is calling to override supply temperature
      REAL(r64) :: EMSValueSupplyTemp      = 0.0d0      ! Value EMS is directing to use for supply temperature [C]
      LOGICAL   :: EMSOverrideSupplyHumRatOn = .FALSE.  ! if true, then EMS is calling to override supply humidity ratio
      REAL(r64) :: EMSValueSupplyHumRat    = 0.0d0      ! Value EMS is directing to use for supply humidity ratio [kg-H2O/kg-dryair]
      REAL(r64) :: MinOAMassFlowRate       = 0.0d0      ! The minimum required outdoor air mass flow rate [kg/s]
      REAL(r64) :: OutdoorAirMassFlowRate  = 0.0d0      ! The outdoor air mass flow rate [kg/s]
      ! Intermediate results
      REAL(r64) :: FinalMixedAirTemp        = 0.0d0      ! Dry-bulb temperature of the mixed air, saved for system ventilation load reporting [C]
      REAL(r64) :: FinalMixedAirHumRat      = 0.0d0      ! Humidity ratio of the mixed air, saved for system ventilation load reporting [kg-H2O/kg-dryair]
      REAL(r64) :: HtRecSenOutput           = 0.0d0      ! Sensible heating/cooling rate from heat recovery (<0 means cooling) [W]
      REAL(r64) :: HtRecLatOutput           = 0.0d0      ! Latent heating/cooling rate from heat recovery (<0 means cooling or dehumidfying) [W]
      REAL(r64) :: OASenOutput              = 0.0d0      ! Outdoor air sensible output relative to zone conditions [W], <0 means OA is cooler than zone air
      REAL(r64) :: OALatOutput              = 0.0d0      ! Outdoor air latent output relative to zone conditions [W], <0 means OA is drier than zone air
      REAL(r64) :: SenOutputToZone          = 0.0d0      ! Ideal Loads System sensible output to zone [W], <0 means supply is cooler than zone air
      REAL(r64) :: LatOutputToZone          = 0.0d0      ! Ideal Loads System latent heat output to zone [W], <0 means supply is drier than zone air
      REAL(r64) :: SenCoilLoad              = 0.0d0      ! Ideal Loads System sensible load on "coils" (<0 means cooling) [W]
      REAL(r64) :: LatCoilLoad              = 0.0d0      ! Ideal Loads System latent load on "coils" (<0 means cooling or dehumidfying) [W]
      INTEGER   :: OAFlowMaxCoolOutputError = 0          ! Counter for OAFlow > Max Cooling Flow error
      INTEGER   :: OAFlowMaxHeatOutputError = 0          ! Counter for OAFlow > Max Heating Flow error
      INTEGER   :: SaturationOutputError    = 0          ! Counter for OAFlow > Max Heating Flow error
      INTEGER   :: OAFlowMaxCoolOutputIndex = 0          ! Recurring warning index for OAFlow > Max Cooling Flow error
      INTEGER   :: OAFlowMaxHeatOutputIndex = 0          ! Recurring warning index for OAFlow > Max Heating Flow error
      INTEGER   :: SaturationOutputIndex    = 0          ! Recurring warning index for OAFlow > Max Heating Flow error
      INTEGER   :: AvailStatus              = 0
      INTEGER   :: CoolErrIndex             = 0          ! Cooling setpoint error index (recurring errors)
      INTEGER   :: HeatErrIndex             = 0          ! Heating setpoint error index (recurring errors)

      ! Output variables
      REAL(r64) :: SenHeatEnergy           = 0.0d0      ! Sensible heating energy consumed [J]
      REAL(r64) :: LatHeatEnergy           = 0.0d0      ! Latent   heating energy consumed [J]
      REAL(r64) :: TotHeatEnergy           = 0.0d0      ! Total    heating energy consumed [J]
      REAL(r64) :: SenCoolEnergy           = 0.0d0      ! Sensible cooling energy consumed [J]
      REAL(r64) :: LatCoolEnergy           = 0.0d0      ! Latent   cooling energy consumed [J]
      REAL(r64) :: TotCoolEnergy           = 0.0d0      ! Total    cooling energy consumed [J]
      REAL(r64) :: ZoneSenHeatEnergy       = 0.0d0      ! Sensible heating energy supplied to the zone [J]
      REAL(r64) :: ZoneLatHeatEnergy       = 0.0d0      ! Latent   heating energy supplied to the zone [J]
      REAL(r64) :: ZoneTotHeatEnergy       = 0.0d0      ! Total    heating energy supplied to the zone [J]
      REAL(r64) :: ZoneSenCoolEnergy       = 0.0d0      ! Sensible cooling energy supplied to the zone [J]
      REAL(r64) :: ZoneLatCoolEnergy       = 0.0d0      ! Latent   cooling energy supplied to the zone [J]
      REAL(r64) :: ZoneTotCoolEnergy       = 0.0d0      ! Total    cooling energy supplied to the zone [J]
      REAL(r64) :: OASenHeatEnergy         = 0.0d0      ! Sensible heating energy required for OA to equal zone air [J]
      REAL(r64) :: OALatHeatEnergy         = 0.0d0      ! Latent   heating energy required for OA to equal zone air [J]
      REAL(r64) :: OATotHeatEnergy         = 0.0d0      ! Total    heating energy required for OA to equal zone air [J]
      REAL(r64) :: OASenCoolEnergy         = 0.0d0      ! Sensible cooling energy required for OA to equal zone air [J]
      REAL(r64) :: OALatCoolEnergy         = 0.0d0      ! Latent   cooling energy required for OA to equal zone air [J]
      REAL(r64) :: OATotCoolEnergy         = 0.0d0      ! Total    cooling energy required for OA to equal zone air [J]
      REAL(r64) :: HtRecSenHeatEnergy      = 0.0d0      ! Sensible heating energy from heat reocovery [J]
      REAL(r64) :: HtRecLatHeatEnergy      = 0.0d0      ! Latent   heating energy from heat reocovery [J]
      REAL(r64) :: HtRecTotHeatEnergy      = 0.0d0      ! Total    heating energy from heat reocovery [J]
      REAL(r64) :: HtRecSenCoolEnergy      = 0.0d0      ! Sensible cooling energy from heat reocovery [J]
      REAL(r64) :: HtRecLatCoolEnergy      = 0.0d0      ! Latent   cooling energy from heat reocovery [J]
      REAL(r64) :: HtRecTotCoolEnergy      = 0.0d0      ! Total    cooling energy from heat reocovery [J]
      REAL(r64) :: SenHeatRate             = 0.0d0      ! Sensible heating rate consumed [W]
      REAL(r64) :: LatHeatRate             = 0.0d0      ! Latent   heating rate consumed [W]
      REAL(r64) :: TotHeatRate             = 0.0d0      ! Total    heating rate consumed [W]
      REAL(r64) :: SenCoolRate             = 0.0d0      ! Sensible cooling rate consumed [W]
      REAL(r64) :: LatCoolRate             = 0.0d0      ! Latent   cooling rate consumed [W]
      REAL(r64) :: TotCoolRate             = 0.0d0      ! Total    cooling rate consumed [W]
      REAL(r64) :: ZoneSenHeatRate         = 0.0d0      ! Sensible heating rate supplied to the zone [W]
      REAL(r64) :: ZoneLatHeatRate         = 0.0d0      ! Latent   heating rate supplied to the zone [W]
      REAL(r64) :: ZoneTotHeatRate         = 0.0d0      ! Total    heating rate supplied to the zone [W]
      REAL(r64) :: ZoneSenCoolRate         = 0.0d0      ! Sensible cooling rate supplied to the zone [W]
      REAL(r64) :: ZoneLatCoolRate         = 0.0d0      ! Latent   cooling rate supplied to the zone [W]
      REAL(r64) :: ZoneTotCoolRate         = 0.0d0      ! Total    cooling rate supplied to the zone [W]
      REAL(r64) :: OASenHeatRate           = 0.0d0      ! Sensible heating rate required for OA to equal zone air [W]
      REAL(r64) :: OALatHeatRate           = 0.0d0      ! Latent   heating rate required for OA to equal zone air [W]
      REAL(r64) :: OATotHeatRate           = 0.0d0      ! Total    heating rate required for OA to equal zone air [W]
      REAL(r64) :: OASenCoolRate           = 0.0d0      ! Sensible cooling rate required for OA to equal zone air [W]
      REAL(r64) :: OALatCoolRate           = 0.0d0      ! Latent   cooling rate required for OA to equal zone air [W]
      REAL(r64) :: OATotCoolRate           = 0.0d0      ! Total    cooling rate required for OA to equal zone air [W]
      REAL(r64) :: HtRecSenHeatRate        = 0.0d0      ! Sensible heating rate from heat reocovery [W]
      REAL(r64) :: HtRecLatHeatRate        = 0.0d0      ! Latent   heating rate from heat reocovery [W]
      REAL(r64) :: HtRecTotHeatRate        = 0.0d0      ! Total    heating rate from heat reocovery [W]
      REAL(r64) :: HtRecSenCoolRate        = 0.0d0      ! Sensible cooling rate from heat reocovery [W]
      REAL(r64) :: HtRecLatCoolRate        = 0.0d0      ! Latent   cooling rate from heat reocovery [W]
      REAL(r64) :: HtRecTotCoolRate        = 0.0d0      ! Total    cooling rate from heat reocovery [W]
      REAL(r64) :: TimeEconoActive         = 0.0d0      ! Time economizer is active [hrs]
      REAL(r64) :: TimeHtRecActive         = 0.0d0      ! Time heat reocovery is active [hrs]
    END TYPE ZonePurchasedAir


  !MODULE VARIABLE DECLARATIONS:
    TYPE (ZonePurchasedAir), ALLOCATABLE, DIMENSION(:) :: PurchAir   ! Used to specify purchased air parameters

    INTEGER, SAVE :: NumPurchAir
    LOGICAL, SAVE :: GetPurchAirInputFlag = .TRUE.
    LOGICAL, ALLOCATABLE, DIMENSION(:) :: CheckEquipName
  !SUBROUTINE SPECIFICATIONS FOR MODULE PurchasedAir:

PUBLIC  SimPurchasedAir
PRIVATE GetPurchasedAir
PRIVATE InitPurchasedAir
PRIVATE CalcPurchAirLoads
PRIVATE UpdatePurchasedAir
PRIVATE ReportPurchasedAir
PUBLIC  GetPurchasedAirOutAirMassFlow
PUBLIC  GetPurchasedAirZoneInletAirNode
PUBLIC  GetPurchasedAirMixedAirTemp
PUBLIC  GetPurchasedAirMixedAirHumRat
PUBLIC  GetPurchasedAirReturnAirNode
PRIVATE CalcPurchAirMinOAMassFlow
PRIVATE CalcPurchAirMixedAir

CONTAINS

SUBROUTINE SimPurchasedAir(PurchAirName, SysOutputProvided, MoistOutputProvided, FirstHVACIteration, &
                                  ControlledZoneNum, ActualZoneNum, CompIndex)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Russ Taylor
          !       DATE WRITTEN   May 1997
          !       MODIFIED       Don Shirey, Aug 2009 (LatOutputProvided - now MoistOutputProvided)
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine manages Purchased Air component simulation.
          ! It is called from SimZoneEquipment in the ZoneEquipmentManager
          ! at the system time step.

          ! METHODOLOGY EMPLOYED:

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
      USE DataGlobals, ONLY:  MaxNameLength
      USE InputProcessor, ONLY: FindItemInList
      USE General, ONLY: TrimSigDigits

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
      CHARACTER(len=*), INTENT(IN) :: PurchAirName
      REAL(r64), INTENT(INOUT) :: SysOutputProvided
      REAL(r64), INTENT(OUT)   :: MoistOutputProvided ! Moisture output provided (kg/s), dehumidification = negative
      LOGICAL, INTENT(IN) :: FirstHVACIteration
      INTEGER, INTENT(IN) :: ControlledZoneNum
      INTEGER, INTENT(IN) :: ActualZoneNum
      INTEGER, INTENT(INOUT) :: CompIndex

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:

      INTEGER :: PurchAirNum

      ! Beginning of Code

      IF (GetPurchAirInputFlag ) THEN
        CALL GetPurchasedAir
        GetPurchAirInputFlag = .FALSE.
      END IF

      ! Find the correct PurchasedAir Equipment
      IF (CompIndex == 0) THEN
        PurchAirNum = FindItemInList(PurchAirName, PurchAir%Name, NumPurchAir)
        IF (PurchAirNum == 0) THEN
          CALL ShowFatalError('SimPurchasedAir: Unit not found='//TRIM(PurchAirName))
        ENDIF
        CompIndex=PurchAirNum
      ELSE
        PurchAirNum=CompIndex
        IF (PurchAirNum > NumPurchAir .or. PurchAirNum < 1) THEN
          CALL ShowFatalError('SimPurchasedAir:  Invalid CompIndex passed='//  &
                              TRIM(TrimSigDigits(PurchAirNum))// &
                              ', Number of Units='//TRIM(TrimSigDigits(NumPurchAir))//  &
                              ', Entered Unit name='//TRIM(PurchAirName))
        ENDIF
        IF (CheckEquipName(PurchAirNum)) THEN
          IF (PurchAirName /= PurchAir(PurchAirNum)%Name) THEN
            CALL ShowFatalError('SimPurchasedAir: Invalid CompIndex passed='//  &
                                TRIM(TrimSigDigits(PurchAirNum))// &
                                ', Unit name='//TRIM(PurchAirName)//', stored Unit Name for that index='//  &
                                TRIM(PurchAir(PurchAirNum)%Name))
          ENDIF
          CheckEquipName(PurchAirNum)=.false.
        ENDIF
      ENDIF

      CALL InitPurchasedAir(PurchAirNum, FirstHVACIteration, ControlledZoneNum, ActualZoneNum)

      CALL CalcPurchAirLoads(PurchAirNum, SysOutputProvided, MoistOutputProvided, ControlledZoneNum, ActualZoneNum)

      CALL UpdatePurchasedAir(PurchAirNum)

      CALL ReportPurchasedAir(PurchAirNum)

      RETURN

    END SUBROUTINE SimPurchasedAir

    SUBROUTINE GetPurchasedAir

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Russ Taylor
          !       DATE WRITTEN   June 1997
          !       MODIFIED       M. Witte, June 2011, add new features including DCV, economizer, dehumidification
          !                                           and humidification controls
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Get the input data for the Purchased Air objects.
          ! Set up output variables.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE InputProcessor,   ONLY: GetNumObjectsFound, GetObjectItem, VerifyName, SameString, FindIteminList
  USE NodeInputManager, ONLY: GetOnlySingleNode,InitUniqueNodeCheck,CheckUniqueNodes,EndUniqueNodeCheck
  USE OutAirNodeManager, ONLY: CheckAndAddAirNodeNumber
  USE DataLoopNode
  USE DataIPShortCuts
  USE DataSizing, ONLY: OARequirements, NumOARequirements   ! to find DesignSpecification:OutdoorAir pointer
  USE DataContaminantBalance, ONLY: Contaminant

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
          ! na

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
      INTEGER :: PurchAirNum
      INTEGER :: NumAlphas
      INTEGER :: NumNums
      INTEGER :: IOSTAT
      CHARACTER(len=*), PARAMETER  :: RoutineName='GetPurchasedAir: ' ! include trailing blank space
      LOGICAL :: ErrorsFound = .false.   ! If errors detected in input
      LOGICAL :: IsNotOK                 ! Flag to verify name
      LOGICAL :: IsBlank                 ! Flag for blank name
      LOGICAL :: IsOANodeListed          ! Flag for OA node name listed in OutdoorAir:Node or Nodelist
      LOGICAL :: UniqueNodeError         ! Flag for non-unique node error(s)

      cCurrentModuleObject='ZoneHVAC:IdealLoadsAirSystem'

      NumPurchAir = GetNumObjectsFound(cCurrentModuleObject)

      ALLOCATE (PurchAir(NumPurchAir))
      ALLOCATE(CheckEquipName(NumPurchAir))
      CheckEquipName=.true.

      IF (NumPurchAir .GT. 0)THEN
        CALL InitUniqueNodeCheck(cCurrentModuleObject)
        DO PurchAirNum = 1,  NumPurchAir
          PurchAir(PurchAirNum)%cObjectName = cCurrentModuleObject

          CALL GetObjectItem(cCurrentModuleObject,PurchAirNum,cAlphaArgs,NumAlphas,rNumericArgs, &
                             NumNums,IOSTAT, NumBlank=lNumericFieldBlanks, AlphaBlank=lAlphaFieldBlanks, &
                             AlphaFieldNames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
          IsNotOK=.false.
          IsBlank=.false.
          CALL VerifyName(cAlphaArgs(1),PurchAir%Name,PurchAirNum-1,IsNotOK,IsBlank,TRIM(cCurrentModuleObject)//' Name')
          IF (IsNotOK) THEN
            ErrorsFound=.true.
            IF (IsBlank) cAlphaArgs(1)='xxxxx'
          ENDIF
          PurchAir(PurchAirNum)%Name       = cAlphaArgs(1)
          ! get optional  availability schedule
          PurchAir(PurchAirNum)%AvailSched = cAlphaArgs(2)
          IF (lAlphaFieldBlanks(2)) THEN
            PurchAir(PurchAirNum)%AvailSchedPtr = ScheduleAlwaysOn
          ELSE
            PurchAir(PurchAirNum)%AvailSchedPtr = GetScheduleIndex(cAlphaArgs(2))
            IF (PurchAir(PurchAirNum)%AvailSchedPtr == 0) THEN
              CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//trim(cAlphaArgs(1))//' invalid data')
              CALL ShowContinueError('Invalid-not found '//TRIM(cAlphaFieldNames(2))//  &
                 '="'//TRIM(cAlphaArgs(2))//'".')
              ErrorsFound=.true.
            END IF
          END IF
                  ! Purchased air supply air node is an outlet node
          PurchAir(PurchAirNum)%ZoneSupplyAirNodeNum  = &
               GetOnlySingleNode(cAlphaArgs(3),ErrorsFound,TRIM(cCurrentModuleObject),cAlphaArgs(1), &
               NodeType_Air,NodeConnectionType_Outlet,1,ObjectIsNotParent)
          UniqueNodeError=.false.
          CALL CheckUniqueNodes(cAlphaFieldNames(3),'NodeName',UniqueNodeError,CheckName=cAlphaArgs(3),ObjectName=cAlphaArgs(1))
          IF (UniqueNodeError) ErrorsFound=.true.
                  ! If new (optional) exhaust air node name is present, then register it as inlet
          IF (.NOT.lAlphaFieldBlanks(4)) THEN
            PurchAir(PurchAirNum)%ZoneExhaustAirNodeNum  = &
                 GetOnlySingleNode(cAlphaArgs(4),ErrorsFound,TRIM(cCurrentModuleObject),cAlphaArgs(1), &
                 NodeType_Air,NodeConnectionType_Inlet,1,ObjectIsNotParent)
            UniqueNodeError=.false.
            CALL CheckUniqueNodes(cAlphaFieldNames(4),'NodeName',UniqueNodeError,CheckName=cAlphaArgs(4),ObjectName=cAlphaArgs(1))
            IF (UniqueNodeError) ErrorsFound=.true.
          ENDIF
          PurchAir(PurchAirNum)%MaxHeatSuppAirTemp    = rNumericArgs(1)
          PurchAir(PurchAirNum)%MinCoolSuppAirTemp    = rNumericArgs(2)
          PurchAir(PurchAirNum)%MaxHeatSuppAirHumRat  = rNumericArgs(3)
          PurchAir(PurchAirNum)%MinCoolSuppAirHumRat  = rNumericArgs(4)

          IF (SameString(cAlphaArgs(5),'NoLimit')) THEN
            PurchAir(PurchAirNum)%HeatingLimit = NoLimit
          ELSEIF (SameString(cAlphaArgs(5),'LimitFlowRate')) THEN
            IF (lNumericFieldBlanks(5)) THEN
              PurchAir(PurchAirNum)%HeatingLimit = NoLimit
            ELSE
              PurchAir(PurchAirNum)%HeatingLimit = LimitFlowRate
            ENDIF
          ELSEIF (SameString(cAlphaArgs(5),'LimitCapacity')) THEN
            IF (lNumericFieldBlanks(6)) THEN
              PurchAir(PurchAirNum)%HeatingLimit = NoLimit
            ELSE
              PurchAir(PurchAirNum)%HeatingLimit = LimitCapacity
            ENDIF
          ELSEIF (SameString(cAlphaArgs(5),'LimitFlowRateAndCapacity')) THEN
            IF (lNumericFieldBlanks(5) .AND. lNumericFieldBlanks(6)) THEN
              PurchAir(PurchAirNum)%HeatingLimit = NoLimit
            ELSEIF (lNumericFieldBlanks(5)) THEN
              PurchAir(PurchAirNum)%HeatingLimit = LimitCapacity
            ELSEIF (lNumericFieldBlanks(6)) THEN
              PurchAir(PurchAirNum)%HeatingLimit = LimitFlowRate
            ELSE
              PurchAir(PurchAirNum)%HeatingLimit = LimitFlowRateAndCapacity
            ENDIF
          ELSE
            CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//trim(cAlphaArgs(1))//' invalid data')
            CALL ShowContinueError('Invalid-entry '//TRIM(cAlphaFieldNames(5))//'="'//TRIM(cAlphaArgs(5))//'".')
            CALL ShowContinueError('Valid entries are NoLimit, LimitFlowRate, LimitCapacity, or LimitFlowRateAndCapacity')
            ErrorsFound=.true.
          END IF
          PurchAir(PurchAirNum)%MaxHeatVolFlowRate = rNumericArgs(5)
          PurchAir(PurchAirNum)%MaxHeatSensCap     = rNumericArgs(6)

          IF (SameString(cAlphaArgs(6),'NoLimit')) THEN
            PurchAir(PurchAirNum)%CoolingLimit = NoLimit
          ELSEIF (SameString(cAlphaArgs(6),'LimitFlowRate')) THEN
            IF (lNumericFieldBlanks(7)) THEN
              PurchAir(PurchAirNum)%CoolingLimit = NoLimit
            ELSE
              PurchAir(PurchAirNum)%CoolingLimit = LimitFlowRate
            ENDIF
          ELSEIF (SameString(cAlphaArgs(6),'LimitCapacity')) THEN
            IF (lNumericFieldBlanks(8)) THEN
              PurchAir(PurchAirNum)%CoolingLimit = NoLimit
            ELSE
              PurchAir(PurchAirNum)%CoolingLimit = LimitCapacity
            ENDIF
          ELSEIF (SameString(cAlphaArgs(6),'LimitFlowRateAndCapacity')) THEN
            IF (lNumericFieldBlanks(7) .AND. lNumericFieldBlanks(8)) THEN
              PurchAir(PurchAirNum)%CoolingLimit = NoLimit
            ELSEIF (lNumericFieldBlanks(7)) THEN
              PurchAir(PurchAirNum)%CoolingLimit = LimitCapacity
            ELSEIF (lNumericFieldBlanks(8)) THEN
              PurchAir(PurchAirNum)%CoolingLimit = LimitFlowRate
            ELSE
              PurchAir(PurchAirNum)%CoolingLimit = LimitFlowRateAndCapacity
            ENDIF
          ELSE
            CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//trim(cAlphaArgs(1))//' invalid data')
            CALL ShowContinueError('Invalid-entry '//TRIM(cAlphaFieldNames(6))//'="'//TRIM(cAlphaArgs(6))//'".')
            CALL ShowContinueError('Valid entries are NoLimit, LimitFlowRate, LimitCapacity, or LimitFlowRateAndCapacity')
            ErrorsFound=.true.
          END IF
          PurchAir(PurchAirNum)%MaxCoolVolFlowRate    = rNumericArgs(7)
          PurchAir(PurchAirNum)%MaxCoolTotCap         = rNumericArgs(8)

          ! get optional heating availability schedule
          PurchAir(PurchAirNum)%HeatSched = cAlphaArgs(7)
          IF (lAlphaFieldBlanks(7)) THEN
            PurchAir(PurchAirNum)%HeatSchedPtr = ScheduleAlwaysOn
          ELSE
            PurchAir(PurchAirNum)%HeatSchedPtr = GetScheduleIndex(cAlphaArgs(7))
            IF (PurchAir(PurchAirNum)%HeatSchedPtr == 0) THEN
              CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//trim(cAlphaArgs(1))//' invalid data')
              CALL ShowContinueError('Invalid-not found '//TRIM(cAlphaFieldNames(7))//'="'//TRIM(cAlphaArgs(7))//'".')
              ErrorsFound=.true.
            END IF
          END IF
          ! get optional cooling availability schedule
          PurchAir(PurchAirNum)%CoolSched = cAlphaArgs(8)
          IF (lAlphaFieldBlanks(8)) THEN
            PurchAir(PurchAirNum)%CoolSchedPtr = ScheduleAlwaysOn
          ELSE
            PurchAir(PurchAirNum)%CoolSchedPtr = GetScheduleIndex(cAlphaArgs(8))
            IF (PurchAir(PurchAirNum)%CoolSchedPtr == 0) THEN
              CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//trim(cAlphaArgs(1))//' invalid data')
              CALL ShowContinueError('Invalid-not found '//TRIM(cAlphaFieldNames(8))//'="'//TRIM(cAlphaArgs(8))//'".')
              ErrorsFound=.true.
            END IF
          END IF
          ! get Dehumidification control type
          IF (SameString(cAlphaArgs(9),'None')) THEN
                  PurchAir(PurchAirNum)%DehumidCtrlType = None
          ELSEIF (SameString(cAlphaArgs(9),'ConstantSensibleHeatRatio')) THEN
                  PurchAir(PurchAirNum)%DehumidCtrlType = ConstantSensibleHeatRatio
          ELSEIF(SameString(cAlphaArgs(9),'Humidistat')) THEN
                  PurchAir(PurchAirNum)%DehumidCtrlType = Humidistat
          ELSEIF(SameString(cAlphaArgs(9),'ConstantSupplyHumidityRatio')) THEN
                  PurchAir(PurchAirNum)%DehumidCtrlType = ConstantSupplyHumidityRatio
          ELSE
            CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//trim(cAlphaArgs(1))//' invalid data')
            CALL ShowContinueError('Invalid-entry '//TRIM(cAlphaFieldNames(9))//'="'//TRIM(cAlphaArgs(9))//'".')
            CALL ShowContinueError('Valid entries are ConstantSensibleHeatRatio, Humidistat, or ConstantSupplyHumidityRatio')
            ErrorsFound=.true.
          END IF
          PurchAir(PurchAirNum)%CoolSHR = rNumericArgs(9)

          ! get Humidification control type
          IF (SameString(cAlphaArgs(10),'None')) THEN
                  PurchAir(PurchAirNum)%HumidCtrlType = None
          ELSEIF(SameString(cAlphaArgs(10),'Humidistat')) THEN
                  PurchAir(PurchAirNum)%HumidCtrlType = Humidistat
          ELSEIF(SameString(cAlphaArgs(10),'ConstantSupplyHumidityRatio')) THEN
                  PurchAir(PurchAirNum)%HumidCtrlType = ConstantSupplyHumidityRatio
          ELSE
            CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//trim(cAlphaArgs(1))//' invalid data')
            CALL ShowContinueError('Invalid-entry '//TRIM(cAlphaFieldNames(10))//'="'//TRIM(cAlphaArgs(10))//'".')
            CALL ShowContinueError('Valid entries are None, Humidistat, or ConstantSupplyHumidityRatio')
            ErrorsFound=.true.
          END IF

          ! get Design specification outdoor air object
          IF(.NOT. lAlphaFieldBlanks(11))THEN
            PurchAir(PurchAirNum)%OARequirementsPtr = FindItemInList(cAlphaArgs(11),OARequirements%Name,NumOARequirements)
            IF(PurchAir(PurchAirNum)%OARequirementsPtr .EQ. 0)THEN
              CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//trim(cAlphaArgs(1))//' invalid data')
              CALL ShowContinueError('Invalid-not found'//TRIM(cAlphaFieldNames(11))//'="'//TRIM(cAlphaArgs(11))//'".')
              ErrorsFound=.true.
            ELSE
              PurchAir(PurchAirNum)%OutdoorAir = .true.
            END IF
          END IF

          ! If outdoor air specified, then get Outdoor air inlet node and other outdoor air inputs
          IF (PurchAir(PurchAirNum)%OutdoorAir) THEN
            IF (lAlphaFieldBlanks(12)) THEN
                ! If there is outdoor air and outdoor air inlet node is blank, then create one
                IF (LEN_TRIM(cAlphaArgs(1)) < (MaxNameLength - 23) ) THEN ! protect against long name leading to > 100 chars
                    cAlphaArgs(12) = TRIM(cAlphaArgs(1))//' OUTDOOR AIR INLET NODE'
                ELSE
                    cAlphaArgs(12) = TRIM(cAlphaArgs(1)(1:75))//' OUTDOOR AIR INLET NODE'
                ENDIF
                IF (DisplayExtraWarnings) THEN
                    CALL ShowWarningError(RoutineName//TRIM(cCurrentModuleObject)//'="'//  &
                       trim(cAlphaArgs(1))//' blank field')
                    CALL ShowContinueError(TRIM(cAlphaFieldNames(12))// &
                          ' is blank, but there is outdoor air requested for this system.')
                    CALL ShowContinueError('Creating node name ='//TRIM(cAlphaArgs(12)))
                ENDIF
            ENDIF
                ! Register OA node
            PurchAir(PurchAirNum)%OutdoorAirNodeNum  = &
                  GetOnlySingleNode(cAlphaArgs(12),ErrorsFound,TRIM(cCurrentModuleObject),cAlphaArgs(1), &
                  NodeType_Air,NodeConnectionType_Outlet,1,ObjectIsNotParent)
                ! Check if OA node is initialized in OutdoorAir:Node or OutdoorAir:Nodelist
            CALL CheckAndAddAirNodeNumber(PurchAir(PurchAirNum)%OutdoorAirNodeNum,IsOANodeListed)
            IF ((.not. IsOANodeListed) .AND. DisplayExtraWarnings) THEN
                CALL ShowWarningError(RoutineName//TRIM(cCurrentModuleObject)//'="'//  &
                       trim(cAlphaArgs(1))//' missing data')
                CALL ShowContinueError(TRIM(cAlphaArgs(12))// &
                      ' does not appear in an OutdoorAir:NodeList or as an OutdoorAir:Node.')
                CALL ShowContinueError('Adding OutdoorAir:Node='//TRIM(cAlphaArgs(12)))
            ENDIF
            UniqueNodeError=.false.
            CALL CheckUniqueNodes(cAlphaFieldNames(12),'NodeName',UniqueNodeError,CheckName=cAlphaArgs(12),ObjectName=cAlphaArgs(1))
            IF (UniqueNodeError) ErrorsFound=.true.

            ! get Demand controlled ventilation type
            IF (SameString(cAlphaArgs(13),'None')) THEN
                    PurchAir(PurchAirNum)%DCVType = NoDCV
            ELSEIF(SameString(cAlphaArgs(13),'OccupancySchedule')) THEN
                    PurchAir(PurchAirNum)%DCVType = OccupancySchedule
            ELSEIF(SameString(cAlphaArgs(13),'CO2Setpoint')) THEN
              IF(Contaminant%CO2Simulation) THEN
                    PurchAir(PurchAirNum)%DCVType = CO2Setpoint
              ELSE
                    PurchAir(PurchAirNum)%DCVType = NoDCV
                    CALL ShowWarningError(RoutineName//TRIM(cCurrentModuleObject)//'="'//  &
                       trim(cAlphaArgs(1))//' invalid data')
                    CALL ShowContinueError(TRIM(cAlphaFieldNames(13))//'='//TRIM(cAlphaArgs(13))// &
                         ' but CO2 simulation is not active.')
                    CALL ShowContinueError('Resetting '//TRIM(cAlphaFieldNames(13))//' to NoDCV')
                    CALL ShowContinueError('To activate CO2 simulation, use ZoneAirContaminantBalance object'// &
                         ' and specify "Carbon Dioxide Concentration"="Yes".')
              END IF
            ELSE
              CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//  &
                       trim(cAlphaArgs(1))//' invalid data')
              CALL ShowContinueError('Invalid-entry '//TRIM(cAlphaFieldNames(13))//'='//TRIM(cAlphaArgs(13)))
              CALL ShowContinueError('Valid entries are None, OccupancySchedule, or CO2Setpoint')
              ErrorsFound=.true.
            END IF
            ! get Outdoor air economizer type
            IF (SameString(cAlphaArgs(14),'NoEconomizer')) THEN
                    PurchAir(PurchAirNum)%EconomizerType = NoEconomizer
            ELSEIF(SameString(cAlphaArgs(14),'DifferentialDryBulb')) THEN
                    PurchAir(PurchAirNum)%EconomizerType = DifferentialDryBulb
            ELSEIF(SameString(cAlphaArgs(14),'DifferentialEnthalpy')) THEN
                    PurchAir(PurchAirNum)%EconomizerType = DifferentialEnthalpy
            ELSE
              CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//  &
                       trim(cAlphaArgs(1))//' invalid data')
              CALL ShowContinueError('Invalid-entry '//TRIM(cAlphaFieldNames(14))//'='//TRIM(cAlphaArgs(14)))
              CALL ShowContinueError('Valid entries are NoEconomizer, DifferentialDryBulb, or DifferentialEnthalpy')
              ErrorsFound=.true.
            END IF
            ! get Outdoor air heat recovery type and effectiveness
            IF (SameString(cAlphaArgs(15),'None')) THEN
                    PurchAir(PurchAirNum)%HtRecType = NoHeatRecovery
            ELSEIF(SameString(cAlphaArgs(15),'Sensible')) THEN
                    PurchAir(PurchAirNum)%HtRecType = Sensible
            ELSEIF(SameString(cAlphaArgs(15),'Enthalpy')) THEN
                    PurchAir(PurchAirNum)%HtRecType = Enthalpy
            ELSE
              CALL ShowSevereError(RoutineName//TRIM(cCurrentModuleObject)//'="'//  &
                       trim(cAlphaArgs(1))//' invalid data')
              CALL ShowContinueError('Invalid-entry '//TRIM(cAlphaFieldNames(15))//'='//TRIM(cAlphaArgs(15)))
              CALL ShowContinueError('Valid entries are None, Sensible, or Enthalpy')
              ErrorsFound=.true.
            END IF
          ELSE !No outdoorair
            PurchAir(PurchAirNum)%DCVType = NoDCV
            PurchAir(PurchAirNum)%EconomizerType = NoEconomizer
            PurchAir(PurchAirNum)%HtRecType = NoHeatRecovery
          END IF

          PurchAir(PurchAirNum)%HtRecSenEff = rNumericArgs(10)
          PurchAir(PurchAirNum)%HtRecLatEff = rNumericArgs(11)


           ! initialize the calculated and report values
          PurchAir(PurchAirNum)%MaxHeatMassFlowRate  = 0.0d0
          PurchAir(PurchAirNum)%MaxCoolMassFlowRate  = 0.0d0
          PurchAir(PurchAirNum)%SenHeatEnergy        = 0.0d0
          PurchAir(PurchAirNum)%LatHeatEnergy        = 0.0d0
          PurchAir(PurchAirNum)%TotHeatEnergy        = 0.0d0
          PurchAir(PurchAirNum)%SenCoolEnergy        = 0.0d0
          PurchAir(PurchAirNum)%LatCoolEnergy        = 0.0d0
          PurchAir(PurchAirNum)%TotCoolEnergy        = 0.0d0
          PurchAir(PurchAirNum)%ZoneSenHeatEnergy    = 0.0d0
          PurchAir(PurchAirNum)%ZoneLatHeatEnergy    = 0.0d0
          PurchAir(PurchAirNum)%ZoneTotHeatEnergy    = 0.0d0
          PurchAir(PurchAirNum)%ZoneSenCoolEnergy    = 0.0d0
          PurchAir(PurchAirNum)%ZoneLatCoolEnergy    = 0.0d0
          PurchAir(PurchAirNum)%ZoneTotCoolEnergy    = 0.0d0
          PurchAir(PurchAirNum)%OASenHeatEnergy      = 0.0d0
          PurchAir(PurchAirNum)%OALatHeatEnergy      = 0.0d0
          PurchAir(PurchAirNum)%OATotHeatEnergy      = 0.0d0
          PurchAir(PurchAirNum)%OASenCoolEnergy      = 0.0d0
          PurchAir(PurchAirNum)%OALatCoolEnergy      = 0.0d0
          PurchAir(PurchAirNum)%OATotCoolEnergy      = 0.0d0
          PurchAir(PurchAirNum)%HtRecSenHeatEnergy   = 0.0d0
          PurchAir(PurchAirNum)%HtRecLatHeatEnergy   = 0.0d0
          PurchAir(PurchAirNum)%HtRecTotHeatEnergy   = 0.0d0
          PurchAir(PurchAirNum)%HtRecSenCoolEnergy   = 0.0d0
          PurchAir(PurchAirNum)%HtRecLatCoolEnergy   = 0.0d0
          PurchAir(PurchAirNum)%HtRecTotCoolEnergy   = 0.0d0
          PurchAir(PurchAirNum)%SenHeatRate          = 0.0d0
          PurchAir(PurchAirNum)%LatHeatRate          = 0.0d0
          PurchAir(PurchAirNum)%TotHeatRate          = 0.0d0
          PurchAir(PurchAirNum)%SenCoolRate          = 0.0d0
          PurchAir(PurchAirNum)%LatCoolRate          = 0.0d0
          PurchAir(PurchAirNum)%TotCoolRate          = 0.0d0
          PurchAir(PurchAirNum)%ZoneSenHeatRate      = 0.0d0
          PurchAir(PurchAirNum)%ZoneLatHeatRate      = 0.0d0
          PurchAir(PurchAirNum)%ZoneTotHeatRate      = 0.0d0
          PurchAir(PurchAirNum)%ZoneSenCoolRate      = 0.0d0
          PurchAir(PurchAirNum)%ZoneLatCoolRate      = 0.0d0
          PurchAir(PurchAirNum)%ZoneTotCoolRate      = 0.0d0
          PurchAir(PurchAirNum)%OASenHeatRate        = 0.0d0
          PurchAir(PurchAirNum)%OALatHeatRate        = 0.0d0
          PurchAir(PurchAirNum)%OATotHeatRate        = 0.0d0
          PurchAir(PurchAirNum)%OASenCoolRate        = 0.0d0
          PurchAir(PurchAirNum)%OALatCoolRate        = 0.0d0
          PurchAir(PurchAirNum)%OATotCoolRate        = 0.0d0
          PurchAir(PurchAirNum)%HtRecSenHeatRate     = 0.0d0
          PurchAir(PurchAirNum)%HtRecLatHeatRate     = 0.0d0
          PurchAir(PurchAirNum)%HtRecTotHeatRate     = 0.0d0
          PurchAir(PurchAirNum)%HtRecSenCoolRate     = 0.0d0
          PurchAir(PurchAirNum)%HtRecLatCoolRate     = 0.0d0
          PurchAir(PurchAirNum)%HtRecTotCoolRate     = 0.0d0

        END DO
        CALL EndUniqueNodeCheck(cCurrentModuleObject)
      END IF

      DO PurchAirNum = 1,NumPurchAir

        ! Setup Output variables
        !    energy variables
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Sensible Heating Energy [J]', PurchAir(PurchAirNum)%SenHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Latent Heating Energy [J]', PurchAir(PurchAirNum)%LatHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Total Heating Energy [J]', PurchAir(PurchAirNum)%TotHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name,  &
                               ResourceTypeKey='DISTRICTHEATING',EndUseKey='Heating',GroupKey='System')
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Sensible Cooling Energy [J]', PurchAir(PurchAirNum)%SenCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Latent Cooling Energy [J]', PurchAir(PurchAirNum)%LatCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Total Cooling Energy [J]', PurchAir(PurchAirNum)%TotCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name,  &
                               ResourceTypeKey='DISTRICTCOOLING',EndUseKey='Cooling',GroupKey='System')
        CALL SetupOutputVariable('Zone Ideal Loads Zone Sensible Heating Energy [J]', PurchAir(PurchAirNum)%ZoneSenHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Latent Heating Energy [J]', PurchAir(PurchAirNum)%ZoneLatHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Total Heating Energy [J]', PurchAir(PurchAirNum)%ZoneTotHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Sensible Cooling Energy [J]', PurchAir(PurchAirNum)%ZoneSenCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Latent Cooling Energy [J]', PurchAir(PurchAirNum)%ZoneLatCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Total Cooling Energy [J]', PurchAir(PurchAirNum)%ZoneTotCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Sensible Heating Energy [J]', &
                                PurchAir(PurchAirNum)%OASenHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Latent Heating Energy [J]', PurchAir(PurchAirNum)%OALatHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Total Heating Energy [J]', PurchAir(PurchAirNum)%OATotHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Sensible Cooling Energy [J]', &
                                  PurchAir(PurchAirNum)%OASenCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Latent Cooling Energy [J]', PurchAir(PurchAirNum)%OALatCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Total Cooling Energy [J]', PurchAir(PurchAirNum)%OATotCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Sensible Heating Energy [J]', &
                                  PurchAir(PurchAirNum)%HtRecSenHeatEnergy,&
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Latent Heating Energy [J]', &
                                  PurchAir(PurchAirNum)%HtRecLatHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Total Heating Energy [J]', &
                                  PurchAir(PurchAirNum)%HtRecTotHeatEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Sensible Cooling Energy [J]',   &
                               PurchAir(PurchAirNum)%HtRecSenCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Latent Cooling Energy [J]', &
                                  PurchAir(PurchAirNum)%HtRecLatCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Total Cooling Energy [J]', &
                                  PurchAir(PurchAirNum)%HtRecTotCoolEnergy, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)

        !    rate variables
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Sensible Heating Rate [W]', PurchAir(PurchAirNum)%SenHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Latent Heating Rate [W]', PurchAir(PurchAirNum)%LatHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Total Heating Rate [W]', PurchAir(PurchAirNum)%TotHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Sensible Cooling Rate [W]', PurchAir(PurchAirNum)%SenCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Latent Cooling Rate [W]', PurchAir(PurchAirNum)%LatCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Supply Air Total Cooling Rate [W]', PurchAir(PurchAirNum)%TotCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Sensible Heating Rate [W]', PurchAir(PurchAirNum)%ZoneSenHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Latent Heating Rate [W]', PurchAir(PurchAirNum)%ZoneLatHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Total Heating Rate [W]', PurchAir(PurchAirNum)%ZoneTotHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Sensible Cooling Rate [W]', PurchAir(PurchAirNum)%ZoneSenCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Latent Cooling Rate [W]', PurchAir(PurchAirNum)%ZoneLatCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Zone Total Cooling Rate [W]', PurchAir(PurchAirNum)%ZoneTotCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Sensible Heating Rate [W]', PurchAir(PurchAirNum)%OASenHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Latent Heating Rate [W]', PurchAir(PurchAirNum)%OALatHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Total Heating Rate [W]', PurchAir(PurchAirNum)%OATotHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Sensible Cooling Rate [W]', PurchAir(PurchAirNum)%OASenCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Latent Cooling Rate [W]', PurchAir(PurchAirNum)%OALatCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Outdoor Air Total Cooling Rate [W]', PurchAir(PurchAirNum)%OATotCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Sensible Heating Rate [W]', &
                                  PurchAir(PurchAirNum)%HtRecSenHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Latent Heating Rate [W]', PurchAir(PurchAirNum)%HtRecLatHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Total Heating Rate [W]', PurchAir(PurchAirNum)%HtRecTotHeatRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Sensible Cooling Rate [W]', &
                                  PurchAir(PurchAirNum)%HtRecSenCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Latent Cooling Rate [W]', PurchAir(PurchAirNum)%HtRecLatCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Total Cooling Rate [W]', PurchAir(PurchAirNum)%HtRecTotCoolRate, &
                               'System','Average',PurchAir(PurchAirNum)%Name)

        CALL SetupOutputVariable('Zone Ideal Loads Economizer Active Time [hr]', PurchAir(PurchAirNum)%TimeEconoActive, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)
        CALL SetupOutputVariable('Zone Ideal Loads Heat Recovery Active Time [hr]', PurchAir(PurchAirNum)%TimeHtRecActive, &
                               'System','Sum',PurchAir(PurchAirNum)%Name)

        CALL SetupOutputVariable('Zone Ideal Loads Hybrid Ventilation Available Status []',PurchAir(PurchAirNum)%AvailStatus,&
                               'System','Average',PurchAir(PurchAirNum)%Name)

        IF (AnyEnergyManagementSystemInModel) THEN
          CALL SetupEMSActuator('Ideal Loads Air System', PurchAir(PurchAirNum)%Name, 'Air Mass Flow Rate' , '[kg/s]', &
                                  PurchAir(PurchAirNum)%EMSOverrideMdotOn, PurchAir(PurchAirNum)%EMSValueMassFlowRate )
          CALL SetupEMSActuator('Ideal Loads Air System', PurchAir(PurchAirNum)%Name, 'Outdoor Air Mass Flow Rate' , '[kg/s]', &
                                  PurchAir(PurchAirNum)%EMSOverrideOAMdotOn, PurchAir(PurchAirNum)%EMSValueOAMassFlowRate )
          CALL SetupEMSActuator('Ideal Loads Air System', PurchAir(PurchAirNum)%Name, 'Air Temperature' , '[C]', &
                                  PurchAir(PurchAirNum)%EMSOverrideSupplyTempOn, PurchAir(PurchAirNum)%EMSValueSupplyTemp )
          CALL SetupEMSActuator('Ideal Loads Air System', PurchAir(PurchAirNum)%Name, 'Air Humidity Ratio' , '[kgWater/kgDryAir]', &
                                  PurchAir(PurchAirNum)%EMSOverrideSupplyHumRatOn, PurchAir(PurchAirNum)%EMSValueSupplyHumRat )

        ENDIF
      END DO


      IF (ErrorsFound) THEN
        CALL ShowFatalError(RoutineName//'Errors found in input. Preceding conditions cause termination.')
      ENDIF

      RETURN

    END SUBROUTINE GetPurchasedAir


    SUBROUTINE InitPurchasedAir(PurchAirNum,FirstHVACIteration,ControlledZoneNum,ActualZoneNum)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Russ Taylor
          !       DATE WRITTEN   Nov 1997
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Initialize the PurchAir data structure.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
     USE DataHeatBalance, ONLY: Zone
     USE General, ONLY: RoundSigDigits
     USE DataZoneEquipment,  ONLY: ZoneEquipInputsFilled,CheckZoneEquipmentList,ZoneEquipConfig
     USE DataSizing, ONLY: OARequirements   ! to access DesignSpecification:OutdoorAir inputs
     USE DataHeatBalance,  ONLY: Zone ! to access zone area, volume, and multipliers
     USE General, ONLY: FindNumberinList
     USE DataLoopNode, ONLY: NodeID

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
     LOGICAL, INTENT(IN) :: FirstHVACIteration !unused1208
     INTEGER, INTENT(IN) :: PurchAirNum
     INTEGER, INTENT(IN) :: ControlledZoneNum
     INTEGER, INTENT(IN) :: ActualZoneNum

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
      LOGICAL,SAVE        :: MyOneTimeFlag = .true.
      LOGICAL,SAVE        :: ZoneEquipmentListChecked = .false.  ! True after the Zone Equipment List has been checked for items
      Integer             :: Loop
      LOGICAL, ALLOCATABLE,Save, DIMENSION(:) :: MyEnvrnFlag
      LOGICAL, ALLOCATABLE,Save, DIMENSION(:) :: MySizeFlag
      LOGICAL, ALLOCATABLE,Save, DIMENSION(:) :: OneTimeUnitInitsDone ! True if one-time inits for PurchAirNum are completed
!      LOGICAL :: ErrorsFound = .false.   ! If errors detected in input
      LOGICAL :: UnitOn   ! simple checks for error
      LOGICAL :: CoolOn   ! simple checks for error
      LOGICAL :: HeatOn   ! simple checks for error
      Integer             :: SupplyNodeNum    ! Node number for ideal loads supply node
      Integer             :: ExhaustNodeNum    ! Node number for ideal loads exhaust node
      Integer             :: NodeIndex  ! Array index of zone inlet or zone exhaust node that matches ideal loads node
      LOGICAL :: UseReturnNode   ! simple checks for error


      ! Do the Begin Simulation initializations
      IF (MyOneTimeFlag) THEN

        ALLOCATE(MyEnvrnFlag(NumPurchAir))
        ALLOCATE(MySizeFlag(NumPurchAir))
        ALLOCATE(OneTimeUnitInitsDone(NumPurchAir))
        MyEnvrnFlag = .TRUE.
        MySizeFlag = .TRUE.
        OneTimeUnitInitsDone = .false.
        MyOneTimeFlag = .false.

      END IF

      ! need to check all units to see if they are on Zone Equipment List or issue warning
      IF (.not. ZoneEquipmentListChecked .and. ZoneEquipInputsFilled) THEN
        ZoneEquipmentListChecked=.true.
        DO Loop=1,NumPurchAir
          IF (CheckZoneEquipmentList(PurchAir(Loop)%cObjectName,PurchAir(Loop)%Name)) CYCLE
          CALL ShowSevereError('InitPurchasedAir: '//TRIM(PurchAir(Loop)%cObjectName)//' = '// &
                               TRIM(PurchAir(Loop)%Name)//' is not on any ZoneHVAC:EquipmentList.  It will not be simulated.')
        ENDDO
      ENDIF

      ! one time inits for each unit - links PurchAirNum with static input data from ControlledZoneNum and ActualZoneNum
      IF (.not. OneTimeUnitInitsDone(PurchAirNum)) THEN
        OneTimeUnitInitsDone(PurchAirNum) = .true.

        ! Is the supply node really a zone inlet node?
        ! this check has to be done here because of SimPurchasedAir passing in ControlledZoneNum
        SupplyNodeNum = PurchAir(PurchAirNum)%ZoneSupplyAirNodeNum
        IF (SupplyNodeNum .GT. 0) THEN
          NodeIndex = FindNumberinList(SupplyNodeNum, ZoneEquipConfig(ControlledZoneNum)%InletNode, &
                                           ZoneEquipConfig(ControlledZoneNum)%NumInletNodes)
          IF (NodeIndex == 0) THEN
            CALL ShowSevereError('InitPurchasedAir: In '//TRIM(PurchAir(PurchAirNum)%cObjectName)//' = '// &
                  TRIM(PurchAir(PurchAirNum)%Name))
            CALL ShowContinueError('Zone Supply Air Node Name='//TRIM(NodeID(SupplyNodeNum))//' is not a zone inlet node.')
            CALL ShowContinueError('Check ZoneHVAC:EquipmentConnections for zone='// &
                                   TRIM(ZoneEquipConfig(ControlledZoneNum)%ZoneName))
            CALL ShowFatalError('Preceding condition causes termination.')
          END IF
        END IF

        ! Set recirculation node number
        ! If exhaust node is specified, then recirculation is exhaust node, otherwise use zone return node
        ! this check has to be done here because of SimPurchasedAir passing in ControlledZoneNum
        UseReturnNode = .false.
        IF (PurchAir(PurchAirNum)%ZoneExhaustAirNodeNum .GT. 0) THEN
          ExhaustNodeNum = PurchAir(PurchAirNum)%ZoneExhaustAirNodeNum
          NodeIndex = FindNumberinList(ExhaustNodeNum, ZoneEquipConfig(ControlledZoneNum)%ExhaustNode, &
                                           ZoneEquipConfig(ControlledZoneNum)%NumExhaustNodes)
          IF (NodeIndex == 0) THEN
            CALL ShowSevereError('InitPurchasedAir: In '//TRIM(PurchAir(PurchAirNum)%cObjectName)//' = '// &
                  TRIM(PurchAir(PurchAirNum)%Name))
            CALL ShowContinueError('Zone Exhaust Air Node Name='//TRIM(NodeID(ExhaustNodeNum))//' is not a zone exhaust node.')
            CALL ShowContinueError('Check ZoneHVAC:EquipmentConnections for zone='// &
                                   TRIM(ZoneEquipConfig(ControlledZoneNum)%ZoneName))
            CALL ShowContinueError('Zone return air node will be used for ideal loads recirculation air.')
            UseReturnNode = .true.
          ELSE
            PurchAir(PurchAirNum)%ZoneRecircAirNodeNum = PurchAir(PurchAirNum)%ZoneExhaustAirNodeNum
          END IF
        ELSE
          UseReturnNode = .true.
        END IF
        IF(UseReturnNode) THEN
          IF (ZoneEquipConfig(ControlledZoneNum)%ReturnAirNode .GT. 0) THEN
            PurchAir(PurchAirNum)%ZoneRecircAirNodeNum = ZoneEquipConfig(ControlledZoneNum)%ReturnAirNode
          ELSE
            CALL ShowFatalError('InitPurchasedAir: In '//TRIM(PurchAir(PurchAirNum)%cObjectName)//' = '// &
                  TRIM(PurchAir(PurchAirNum)%Name))
            CALL ShowContinueError(' Invalid recirculation node. No exhaust or return node has been'// &
                  ' specified for this zone in ZoneHVAC:EquipmentConnections.')
            CALL ShowFatalError('Preceding condition causes termination.')
          END IF
        END IF
        ! If there is OA and economizer is active, then there must be a limit on cooling flow rate
        IF (PurchAir(PurchAirNum)%OutdoorAir .AND. (PurchAir(PurchAirNum)%EconomizerType /= NoEconomizer)) THEN
          IF ((PurchAir(PurchAirNum)%CoolingLimit == NoLimit) .OR. (PurchAir(PurchAirNum)%CoolingLimit == LimitCapacity)) THEN
            CALL ShowSevereError('InitPurchasedAir: In '//TRIM(PurchAir(PurchAirNum)%cObjectName)//' = '// &
                  TRIM(PurchAir(PurchAirNum)%Name))
            CALL ShowContinueError('There is outdoor air with economizer active but there is no limit on cooling air flow rate.')
            CALL ShowContinueError('Cooling Limit must be set to LimitFlowRate or LimitFlowRateAndCapacity, and '// &
                                   'Maximum Cooling Air Flow Rate must be set to a value or autosize.')
            CALL ShowContinueError('Simulation will proceed with no limit on outdoor air flow rate.')
          END IF
        END IF
      END IF

      IF ( .NOT. SysSizingCalc .AND. MySizeFlag(PurchAirNum) ) THEN

        CALL SizePurchasedAir(PurchAirNum)

        MySizeFlag(PurchAirNum) = .FALSE.
      END IF

      ! Do the Begin Environment initializations
      IF (BeginEnvrnFlag .and. MyEnvrnFlag(PurchAirNum)) THEN

        IF ((PurchAir(PurchAirNum)%HeatingLimit == LimitFlowRate) .OR. &
            (PurchAir(PurchAirNum)%HeatingLimit == LimitFlowRateAndCapacity)) THEN
          PurchAir(PurchAirNum)%MaxHeatMassFlowRate = StdRhoAir * PurchAir(PurchAirNum)%MaxHeatVolFlowRate
        ELSE
          PurchAir(PurchAirNum)%MaxHeatMassFlowRate = 0.0d0
        END IF
        IF ((PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRate) .OR. &
            (PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRateAndCapacity)) THEN
          PurchAir(PurchAirNum)%MaxCoolMassFlowRate = StdRhoAir * PurchAir(PurchAirNum)%MaxCoolVolFlowRate
        ELSE
          PurchAir(PurchAirNum)%MaxCoolMassFlowRate = 0.0d0
        END IF
        MyEnvrnFlag(PurchAirNum) = .FALSE.
      END IF

      IF (.not. BeginEnvrnFlag) THEN
        MyEnvrnFlag(PurchAirNum) = .TRUE.
      ENDIF

      ! These initializations are done every iteration
      ! check that supply air temps can meet the zone thermostat setpoints
      IF (PurchAir(PurchAirNum)%MinCoolSuppAirTemp > ZoneThermostatSetPointHi(ActualZoneNum) .AND. &
          ZoneThermostatSetPointHi(ActualZoneNum) .NE. 0 .and. PurchAir(PurchAirNum)%CoolingLimit == NoLimit) THEN
            ! Check if the unit is scheduled off
        UnitOn = .true.
!        IF (PurchAir(PurchAirNum)%AvailSchedPtr > 0) THEN
          IF (GetCurrentScheduleValue(PurchAir(PurchAirNum)%AvailSchedPtr) <= 0) THEN
            UnitOn = .FALSE.
          END IF
!        END IF
            ! Check if cooling available
        CoolOn = .TRUE.
!        IF (PurchAir(PurchAirNum)%CoolSchedPtr > 0) THEN
          IF (GetCurrentScheduleValue(PurchAir(PurchAirNum)%CoolSchedPtr) <= 0) THEN
            CoolOn = .FALSE.
          END IF
!        END IF
        IF (UnitOn .and. CoolOn) THEN
          IF (PurchAir(PurchAirNum)%CoolErrIndex == 0) THEN
            CALL ShowSevereError('InitPurchasedAir: For '//TRIM(PurchAir(PurchAirNum)%cObjectName)//' = '// &
                               TRIM(PurchAir(PurchAirNum)%Name) //' serving Zone ' // TRIM(Zone(ActualZoneNum)%Name) )
            CALL ShowContinueError('..the minimum supply air temperature for cooling ['//  &
                TRIM(RoundSigDigits(PurchAir(PurchAirNum)%MinCoolSuppAirTemp,2))// &
                '] is greater than the zone cooling mean air temperature (MAT) setpoint ['//  &
                TRIM(RoundSigDigits(ZoneThermostatSetPointHi(ActualZoneNum),2))//'].')
            CALL ShowContinueError('..For operative and comfort thermostat controls, the MAT setpoint is computed.')
            CALL ShowContinueError('..This error may indicate that the mean radiant temperature '//  &
               'or another comfort factor is too warm.')
            CALL ShowContinueError('Unit availability is nominally ON and Cooling availability is nominally ON.')
            CALL ShowContinueError('Limit Cooling Capacity Type='//trim(cLimitType(PurchAir(PurchAirNum)%CoolingLimit)))
! could check for optemp control or comfort control here
            CALL ShowContinueErrorTimeStamp(' ')
          ENDIF
          CALL ShowRecurringSevereErrorAtEnd('InitPurchasedAir: For '//TRIM(PurchAir(PurchAirNum)%cObjectName)//' = '// &
                             TRIM(PurchAir(PurchAirNum)%Name) //' serving Zone ' // TRIM(Zone(ActualZoneNum)%Name)// &
                             ', the minimum supply air temperature for cooling error continues',                     &
                             PurchAir(PurchAirNum)%CoolErrIndex,ReportMinOf=PurchAir(PurchAirNum)%MinCoolSuppAirTemp, &
                             ReportMaxOf=PurchAir(PurchAirNum)%MinCoolSuppAirTemp,ReportMinUnits='C',ReportMaxUnits='C')
        ENDIF
      END IF
      IF (PurchAir(PurchAirNum)%MaxHeatSuppAirTemp < ZoneThermostatSetPointLo(ActualZoneNum) .AND. &
          ZoneThermostatSetPointLo(ActualZoneNum) .NE. 0 .and. PurchAir(PurchAirNum)%HeatingLimit == NoLimit) THEN
            ! Check if the unit is scheduled off
        UnitOn = .true.
!        IF (PurchAir(PurchAirNum)%AvailSchedPtr > 0) THEN
          IF (GetCurrentScheduleValue(PurchAir(PurchAirNum)%AvailSchedPtr) <= 0) THEN
            UnitOn = .FALSE.
          END IF
!        END IF
            ! Check if heating and cooling available
        HeatOn = .TRUE.
!        IF (PurchAir(PurchAirNum)%HeatSchedPtr > 0) THEN
          IF (GetCurrentScheduleValue(PurchAir(PurchAirNum)%HeatSchedPtr) <= 0) THEN
            HeatOn = .FALSE.
          END IF
!        END IF
        IF (UnitOn .and. HeatOn) THEN
          IF (PurchAir(PurchAirNum)%HeatErrIndex == 0) THEN
            CALL ShowSevereMessage('InitPurchasedAir: For '//TRIM(PurchAir(PurchAirNum)%cObjectName)//' = '//&
                                 TRIM(PurchAir(PurchAirNum)%Name) // ' serving Zone ' // TRIM(Zone(ActualZoneNum)%Name) )
            CALL ShowContinueError('..the maximum supply air temperature for heating ['//  &
                TRIM(RoundSigDigits(PurchAir(PurchAirNum)%MaxHeatSuppAirTemp,2))// &
                '] is less than the zone mean air temperature heating setpoint ['//  &
                TRIM(RoundSigDigits(ZoneThermostatSetPointLo(ActualZoneNum),2))//'].')
            CALL ShowContinueError('..For operative and comfort thermostat controls, the MAT setpoint is computed.')
            CALL ShowContinueError('..This error may indicate that the mean radiant temperature '//  &
               'or another comfort factor is too cold.')
            CALL ShowContinueError('Unit availability is nominally ON and Heating availability is nominally ON.')
            CALL ShowContinueError('Limit Heating Capacity Type='//trim(cLimitType(PurchAir(PurchAirNum)%HeatingLimit)))
! could check for optemp control or comfort control here
            CALL ShowContinueErrorTimeStamp(' ')
          ENDIF
          CALL ShowRecurringSevereErrorAtEnd('InitPurchasedAir: For '//TRIM(PurchAir(PurchAirNum)%cObjectName)//' = '// &
                             TRIM(PurchAir(PurchAirNum)%Name) //' serving Zone ' // TRIM(Zone(ActualZoneNum)%Name)// &
                             ', maximum supply air temperature for heating error continues',                         &
                             PurchAir(PurchAirNum)%HeatErrIndex,ReportMinOf=PurchAir(PurchAirNum)%MaxHeatSuppAirTemp, &
                             ReportMaxOf=PurchAir(PurchAirNum)%MaxHeatSuppAirTemp,ReportMinUnits='C',ReportMaxUnits='C')
        ENDIF
      END IF
!      IF (ErrorsFound .and. .not. WarmupFlag) THEN
!        CALL ShowFatalError('Preceding conditions cause termination.')
!      ENDIF

      RETURN

    END SUBROUTINE InitPurchasedAir

    SUBROUTINE SizePurchasedAir(PurchAirNum)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Fred Buhl
          !       DATE WRITTEN   April 2003
          !       MODIFIED       M. Witte, June 2011, add sizing for new capacity fields
          !                      August 2013 Daeho Kang, add component sizing table entries
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine is for sizing Purchased Air Components for which flow rates have not been
          ! specified in the input.

          ! METHODOLOGY EMPLOYED:
          ! Obtains flow rates from the zone sizing arrays.

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
      USE DataSizing
      USE InputProcessor
      USE ReportSizingManager, ONLY: ReportSizingOutput
      USE Psychrometrics, ONLY: PsyCpAirFnWTdb, RhoH2O, CpHw, CpCw, PsyHFnTdbW
      USE General,             ONLY: RoundSigDigits

      IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
      Integer, Intent(IN) :: PurchAirNum

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
      REAL(r64)           :: MixedAirTemp
      REAL(r64)           :: OutletTemp
      REAL(r64)           :: MixedAirHumRat
      REAL(r64)           :: OutletHumRat
      REAL(r64)           :: DesignLoad
      LOGICAL             :: IsAutosize              ! Indicator to autosize
      REAL(r64)           :: MaxHeatVolFlowRateDes   ! Autosized maximum heating air flow for reporting
      REAL(r64)           :: MaxHeatVolFlowRateUser  ! Hardsized maximum heating air flow for reporting
      REAL(r64)           :: MaxCoolVolFlowRateDes   ! Autosized maximum cooling air flow for reporting
      REAL(r64)           :: MaxCoolVolFlowRateUser  ! Hardsized maximum cooling air flow for reporting
      REAL(r64)           :: MaxHeatSensCapDes       ! Autosized maximum sensible heating capacity for reporting
      REAL(r64)           :: MaxHeatSensCapUser      ! Hardsized maximum sensible heating capacity for reporting
      REAL(r64)           :: MaxCoolTotCapDes        ! Autosized maximum sensible cooling capacity for reporting
      REAL(r64)           :: MaxCoolTotCapUser       ! Hardsized maximum sensible cooling capacity for reporting

      IsAutosize = .FALSE.
      MaxHeatVolFlowRateDes = 0.0d0
      MaxHeatVolFlowRateUser = 0.0d0
      MaxCoolVolFlowRateDes = 0.0d0
      MaxCoolVolFlowRateUser = 0.0d0
      MaxHeatSensCapDes = 0.0d0
      MaxHeatSensCapUser = 0.0d0
      MaxCoolTotCapDes = 0.0d0
      MaxCoolTotCapUser = 0.0d0

      IF ((PurchAir(PurchAirNum)%MaxHeatVolFlowRate == AutoSize) .AND. &
          ((PurchAir(PurchAirNum)%HeatingLimit == LimitFlowRate) .OR. &
           (PurchAir(PurchAirNum)%HeatingLimit == LimitFlowRateAndCapacity))) THEN
        IsAutosize = .TRUE.
      END IF

      IF (CurZoneEqNum > 0) THEN
        IF (.NOT. IsAutosize .AND. .NOT. ZoneSizingRunDone) THEN ! Simulation continue
          IF (PurchAir(PurchAirNum)%MaxHeatVolFlowRate > 0.0d0) THEN
            CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                        'User-Specified Maximum Heating Air Flow Rate [m3/s]', PurchAir(PurchAirNum)%MaxHeatVolFlowRate)
          END IF
        ELSE
          CALL CheckZoneSizing(TRIM(PurchAir(PurchAirNum)%cObjectName), PurchAir(PurchAirNum)%Name)
          MaxHeatVolFlowRateDes = FinalZoneSizing(CurZoneEqNum)%DesHeatVolFlow
          IF (MaxHeatVolFlowRateDes < SmallAirVolFlow) THEN
            MaxHeatVolFlowRateDes = 0.0d0
          END IF
          IF (IsAutosize) THEN
            PurchAir(PurchAirNum)%MaxHeatVolFlowRate = MaxHeatVolFlowRateDes
            CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                              'Design Size Maximum Heating Air Flow Rate [m3/s]', MaxHeatVolFlowRateDes)
          ELSE
            IF (PurchAir(PurchAirNum)%MaxHeatVolFlowRate > 0.0d0 .AND. MaxHeatVolFlowRateDes > 0.0d0) THEN
              MaxHeatVolFlowRateUser = PurchAir(PurchAirNum)%MaxHeatVolFlowRate
              CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                              'Design Size Maximum Heating Air Flow Rate [m3/s]', MaxHeatVolFlowRateDes, &
                              'User-Specified Maximum Heating Air Flow Rate [m3/s]', MaxHeatVolFlowRateUser)
              IF (DisplayExtraWarnings) THEN
                IF ((ABS(MaxHeatVolFlowRateDes - MaxHeatVolFlowRateUser)/ MaxHeatVolFlowRateUser) > AutoVsHardSizingThreshold) THEN
                  CALL ShowMessage('SizePurchasedAir: Potential issue with equipment sizing for ' &
                                      //TRIM(PurchAir(PurchAirNum)%cObjectName)//' '// &
                                      TRIM(PurchAir(PurchAirNum)%Name))
                  CALL ShowContinueError('User-Specified Maximum Heating Air Flow Rate of '// &
                                      TRIM(RoundSigDigits(MaxHeatVolFlowRateUser,5))// ' [m3/s]')
                  CALL ShowContinueError('differs from Design Size Maximum Heating Air Flow Rate of ' // &
                                      TRIM(RoundSigDigits(MaxHeatVolFlowRateDes,5))// ' [m3/s]')
                  CALL ShowContinueError('This may, or may not, indicate mismatched component sizes.')
                  CALL ShowContinueError('Verify that the value entered is intended and is consistent with other components.')
                END IF
              ENDIF
            END IF
          END IF
        END IF
      END IF

      IsAutosize = .FALSE.
      IF ((PurchAir(PurchAirNum)%MaxCoolVolFlowRate == AutoSize) .AND. &
          ((PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRate) .OR. &
           (PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRateAndCapacity) .OR. &
           (PurchAir(PurchAirNum)%OutdoorAir .AND. PurchAir(PurchAirNum)%EconomizerType .NE. NoEconomizer))) THEN
        IsAutosize = .TRUE.
      END IF

      IF (CurZoneEqNum > 0) THEN
        IF (.NOT. IsAutosize .AND. .NOT. ZoneSizingRunDone) THEN ! Simulation continue
          IF (PurchAir(PurchAirNum)%MaxCoolVolFlowRate > 0.0d0) THEN
            CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                        'User-Specified Maximum Cooling Air Flow Rate [m3/s]', PurchAir(PurchAirNum)%MaxCoolVolFlowRate)
          END IF
        ELSE
          CALL CheckZoneSizing(TRIM(PurchAir(PurchAirNum)%cObjectName), PurchAir(PurchAirNum)%Name)
          MaxCoolVolFlowRateDes = FinalZoneSizing(CurZoneEqNum)%DesCoolVolFlow
          IF (MaxCoolVolFlowRateDes < SmallAirVolFlow) THEN
            MaxCoolVolFlowRateDes = 0.0d0
          END IF
          IF (IsAutosize) THEN
            PurchAir(PurchAirNum)%MaxCoolVolFlowRate = MaxCoolVolFlowRateDes
            CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                              'Design Size Maximum Cooling Air Flow Rate [m3/s]', MaxCoolVolFlowRateDes)
          ELSE
            IF (PurchAir(PurchAirNum)%MaxCoolVolFlowRate > 0.0d0 .AND. MaxCoolVolFlowRateDes > 0.0d0) THEN
              MaxCoolVolFlowRateUser = PurchAir(PurchAirNum)%MaxCoolVolFlowRate
              CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                              'Design Size Maximum Cooling Air Flow Rate [m3/s]', MaxCoolVolFlowRateDes, &
                              'User-Specified Maximum Cooling Air Flow Rate [m3/s]', MaxCoolVolFlowRateUser)
              IF (DisplayExtraWarnings) THEN
              IF ((ABS(MaxCoolVolFlowRateDes - MaxCoolVolFlowRateUser)/MaxCoolVolFlowRateUser) > AutoVsHardSizingThreshold) THEN
                CALL ShowMessage('SizePurchasedAir: Potential issue with equipment sizing for ' &
                                    //TRIM(PurchAir(PurchAirNum)%cObjectName)//' '// &
                                    TRIM(PurchAir(PurchAirNum)%Name))
                CALL ShowContinueError('User-Specified Maximum Cooling Air Flow Rate of '// &
                                    TRIM(RoundSigDigits(MaxCoolVolFlowRateUser,5))// ' [m3/s]')
                CALL ShowContinueError('differs from Design Size Maximum Cooling Air Flow Rate of ' // &
                                    TRIM(RoundSigDigits(MaxCoolVolFlowRateDes,5))// ' [m3/s]')
                CALL ShowContinueError('This may, or may not, indicate mismatched component sizes.')
                CALL ShowContinueError('Verify that the value entered is intended and is consistent with other components.')
              END IF
              ENDIF
            END IF
          END IF
        END IF
      END IF

      IsAutosize = .FALSE.
      IF ((PurchAir(PurchAirNum)%MaxHeatSensCap == AutoSize) .AND. &
          ((PurchAir(PurchAirNum)%HeatingLimit == LimitCapacity) .OR. &
           (PurchAir(PurchAirNum)%HeatingLimit == LimitFlowRateAndCapacity))) THEN
        IsAutosize = .TRUE.
      END IF

      IF (CurZoneEqNum > 0) THEN
        IF (.NOT. IsAutosize .AND. .NOT. ZoneSizingRunDone) THEN ! Simulation continue
          IF (PurchAir(PurchAirNum)%MaxHeatSensCap > 0.0d0) THEN
            CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                        'User-Specified Maximum Sensible Heating Capacity [W]', PurchAir(PurchAirNum)%MaxHeatSensCap)
          END IF
        ELSE
          CALL CheckZoneSizing(TRIM(PurchAir(PurchAirNum)%cObjectName), PurchAir(PurchAirNum)%Name)
          MixedAirTemp = FinalZoneSizing(CurZoneEqNum)%DesHeatCoilInTemp
          OutletTemp   = FinalZoneSizing(CurZoneEqNum)%HeatDesTemp
          OutletHumRat = FinalZoneSizing(CurZoneEqNum)%HeatDesHumRat
          DesignLoad   = PsyCpAirFnWTdb(OutletHumRat, 0.5d0*(MixedAirTemp+OutletTemp), 'SizePurchasedAir') &
                          * FinalZoneSizing(CurZoneEqNum)%DesHeatMassFlow &
                          * (OutletTemp-MixedAirTemp)
          MaxHeatSensCapDes = DesignLoad
          IF (MaxHeatSensCapDes < SmallLoad) THEN
            MaxHeatSensCapDes = 0.0d0
          END IF
          IF (IsAutosize) THEN
            PurchAir(PurchAirNum)%MaxHeatSensCap = MaxHeatSensCapDes
            CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                              'Design Size Maximum Sensible Heating Capacity [W]', MaxHeatSensCapDes)
            ! If there is OA, check if sizing calcs have OA>0, throw warning if not
            IF ((PurchAir(PurchAirNum)%OutdoorAir) .AND. (FinalZoneSizing(CurZoneEqNum)%MinOA == 0.0)) THEN
              CALL ShowWarningError('InitPurchasedAir: In '//TRIM(PurchAir(PurchAirNum)%cObjectName)//' = '// &
                    TRIM(PurchAir(PurchAirNum)%Name))
              CALL ShowContinueError('There is outdoor air specified in this object, '//  &
                 'but the design outdoor air flow rate for this ')
              CALL ShowContinueError('zone is zero. The Maximum Sensible Heating Capacity will be '//  &
                 'autosized for zero outdoor air flow. ')
              CALL ShowContinueError('Check the outdoor air specifications in the Sizing:Zone object for zone '// &
                                     TRIM(FinalZoneSizing(CurZoneEqNum)%ZoneName)//'.')
            END IF
          ELSE
            IF (PurchAir(PurchAirNum)%MaxHeatSensCap > 0.0d0 .AND. MaxHeatSensCapDes > 0.0d0) THEN
              MaxHeatSensCapUser = PurchAir(PurchAirNum)%MaxHeatSensCap
              CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                              'Design Size Maximum Sensible Heating Capacity [W]', MaxHeatSensCapDes, &
                              'User-Specified Maximum Sensible Heating Capacity [W]', MaxHeatSensCapUser)
              IF (DisplayExtraWarnings) THEN
                IF ((ABS(MaxHeatSensCapDes - MaxHeatSensCapUser)/MaxHeatSensCapUser) > AutoVsHardSizingThreshold) THEN
                  CALL ShowMessage('SizePurchasedAir: Potential issue with equipment sizing for ' &
                                      //TRIM(PurchAir(PurchAirNum)%cObjectName)//' '// &
                                      TRIM(PurchAir(PurchAirNum)%Name))
                  CALL ShowContinueError('...User-Specified Maximum Sensible Heating Capacity of '// &
                                      TRIM(RoundSigDigits(MaxHeatSensCapUser,2))// ' [W]')
                  CALL ShowContinueError('...differs from Design Size Maximum Sensible Heating Capacity of ' // &
                                      TRIM(RoundSigDigits(MaxHeatSensCapDes,2))// ' [W]')
                  CALL ShowContinueError('This may, or may not, indicate mismatched component sizes.')
                  CALL ShowContinueError('Verify that the value entered is intended and is consistent with other components.')
                END IF
              ENDIF
            END IF
          END IF
        END IF
      END IF

      IsAutosize = .FALSE.
      IF ((PurchAir(PurchAirNum)%MaxCoolTotCap == AutoSize) .AND. &
          ((PurchAir(PurchAirNum)%CoolingLimit == LimitCapacity) .OR. &
           (PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRateAndCapacity))) THEN
        IsAutosize = .TRUE.
      END IF

      IF (CurZoneEqNum > 0) THEN
        IF (.NOT. IsAutosize .AND. .NOT. ZoneSizingRunDone) THEN ! Simulation continue
          IF (PurchAir(PurchAirNum)%MaxCoolTotCap > 0.0d0) THEN
            CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                        'User-Specified Maximum Heating Air Flow Rate [m3/s]', PurchAir(PurchAirNum)%MaxCoolTotCap)
          END IF
        ELSE
          CALL CheckZoneSizing(TRIM(PurchAir(PurchAirNum)%cObjectName), PurchAir(PurchAirNum)%Name)
          MixedAirTemp = FinalZoneSizing(CurZoneEqNum)%DesCoolCoilInTemp
          OutletTemp = FinalZoneSizing(CurZoneEqNum)%CoolDesTemp
          OutletHumRat = FinalZoneSizing(CurZoneEqNum)%CoolDesHumRat
          MixedAirHumRat = FinalZoneSizing(CurZoneEqNum)%DesCoolCoilInHumRat
          DesignLoad = FinalZoneSizing(CurZoneEqNum)%DesCoolMassFlow &
                      * (PsyHFnTdbW(MixedAirTemp, MixedAirHumRat, 'SizePurchasedAir') &
                      -PsyHFnTdbW(OutletTemp, OutletHumRat, 'SizePurchasedAir'))
          MaxCoolTotCapDes = DesignLoad
          IF (MaxCoolTotCapDes < SmallLoad) THEN
            MaxCoolTotCapDes = 0.0d0
          END IF
          IF (IsAutosize) THEN
            PurchAir(PurchAirNum)%MaxCoolTotCap = MaxCoolTotCapDes
            CALL ReportSizingOutput(PurchAir(PurchAirNum)%cObjectName, PurchAir(PurchAirNum)%Name, &
                              'Design Size Maximum Total Cooling Capacity [W]', MaxCoolTotCapDes)
            ! If there is OA, check if sizing calcs have OA>0, throw warning if not
            IF ((PurchAir(PurchAirNum)%OutdoorAir) .AND. (FinalZoneSizing(CurZoneEqNum)%MinOA == 0.0)) THEN
              CALL ShowWarningError('SizePurchasedAir: In '//TRIM(PurchAir(PurchAirNum)%cObjectName)//' = '// &
                    TRIM(PurchAir(PurchAirNum)%Name))
              CALL ShowContinueError('There is outdoor air specified in this object, '//  &
                 'but the design outdoor air flow rate for this ')
              CALL ShowContinueError('zone is zero. The Maximum Total Cooling Capacity will be autosized '//  &
                 'for zero outdoor air flow. ')
              CALL ShowContinueError('Check the outdoor air specifications in the Sizing:Zone object for zone '// &
                                     TRIM(FinalZoneSizing(CurZoneEqNum)%ZoneName)//'.')
            END IF
          ELSE
            IF (PurchAir(PurchAirNum)%MaxCoolTotCap > 0.0d0 .AND. MaxCoolTotCapDes > 0.0d0) THEN
              MaxCoolTotCapUser = PurchAir(PurchAirNum)%MaxCoolTotCap
              CALL ReportSizingOutput(TRIM(PurchAir(PurchAirNum)%cObjectName), PurchAir(PurchAirNum)%Name, &
                              'Design Size Maximum Total Cooling Capacity [W]', MaxCoolTotCapDes, &
                              'User-Specified Maximum Total Cooling Capacity [W]', MaxCoolTotCapUser)
              IF (DisplayExtraWarnings) THEN
                IF ((ABS(MaxCoolTotCapDes - MaxCoolTotCapUser)/MaxCoolTotCapUser) > AutoVsHardSizingThreshold) THEN
                  CALL ShowMessage('SizePurchasedAir: Potential issue with equipment sizing for ' &
                                      //TRIM(PurchAir(PurchAirNum)%cObjectName)//' '// &
                                      TRIM(PurchAir(PurchAirNum)%Name))
                  CALL ShowContinueError('User-Specified Maximum Total Cooling Capacity of '// &
                                      TRIM(RoundSigDigits(MaxCoolTotCapUser,2))// ' [W]')
                  CALL ShowContinueError('differs from Design Size Maximum Total Cooling Capacity of ' // &
                                      TRIM(RoundSigDigits(MaxCoolTotCapDes,2))// ' [W]')
                  CALL ShowContinueError('This may, or may not, indicate mismatched component sizes.')
                  CALL ShowContinueError('Verify that the value entered is intended and is consistent with other components.')
                END IF
              ENDIF
            END IF
          END IF
        END IF
      END IF

!      IF (PurchAir(PurchAirNum)%OutdoorAir .AND. PurchAir(PurchAirNum)%OutsideAirVolFlowRate == AutoSize) THEN
!
!        IF (CurZoneEqNum > 0) THEN
!
!          CALL CheckZoneSizing(TRIM(PurchAir(PurchAirNum)%cObjectName), PurchAir(PurchAirNum)%Name)
!          PurchAir(PurchAirNum)%OutsideAirVolFlowRate = FinalZoneSizing(CurZoneEqNum)%MinOA
!          IF (PurchAir(PurchAirNum)%OutsideAirVolFlowRate < SmallAirVolFlow) THEN
!            PurchAir(PurchAirNum)%OutsideAirVolFlowRate = 0.0
!          END IF
!          CALL ReportSizingOutput(TRIM(PurchAir(PurchAirNum)%cObjectName), PurchAir(PurchAirNum)%Name, &
!                              'Outdoor Air Flow Rate [m3/s]', PurchAir(PurchAirNum)%OutsideAirVolFlowRate )
!        END IF
!
!      END IF

    RETURN

    END SUBROUTINE SizePurchasedAir

    SUBROUTINE CalcPurchAirLoads(PurchAirNum, SysOutputProvided, MoistOutputProvided, ControlledZoneNum, ActualZoneNum)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Russ Taylor
          !       DATE WRITTEN   Nov 1997
          !       MODIFIED       Shirey, Aug 2009 (LatOutputProvided - now MoistOutputProvided)
          !                      M. Witte June 2011, add new features including DCV, economizer, dehumidification
          !                          and humidification,
          !                      July 2012, Chandan Sharma - FSEC: Added hybrid ventilation manager
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Needs description.

          ! METHODOLOGY EMPLOYED:
          ! Needs description, as appropriate.

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
         USE DataZoneEnergyDemands, ONLY: ZoneSysEnergyDemand, ZoneSysMoistureDemand
         USE DataLoopNode, ONLY: Node
         USE DataZoneEquipment, ONLY: ZoneEquipConfig
         USE DataHVACGlobals, ONLY: SmallLoad, ZoneComp, ForceOff
         USE DataHeatBalance, ONLY: Zone
         USE DataHeatBalFanSys, ONLY:TempControlType
         USE General, ONLY: TrimSigDigits
         USE DataContaminantBalance, ONLY: Contaminant
         USE DataZoneEquipment, ONLY: PurchasedAir_Num

        IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
         REAL(r64), INTENT(INOUT) :: SysOutputProvided ! Sensible output provided [W] cooling = negative
         REAL(r64), INTENT(OUT)   :: MoistOutputProvided ! Moisture output provided [kg/s] dehumidification = negative
         INTEGER, INTENT(IN) :: ActualZoneNum
         INTEGER, INTENT(IN) :: ControlledZoneNum
         INTEGER, INTENT(IN) :: PurchAirNum

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
         INTEGER   :: InNodeNum         ! Ideal loads supply node to zone
!         INTEGER   :: ExhNodeNum        ! Ideal loads exhaust node from zone
         INTEGER   :: ZoneNodeNum       ! Zone air node
         INTEGER   :: OANodeNum         ! Outdoor air inlet node
         INTEGER   :: RecircNodeNum     ! Return air or zone exhaust node
         INTEGER   :: OperatingMode     ! current operating mode, Off, Heat, Cool, or Deadband
         REAL(r64) :: SupplyMassFlowRate  ! System supply air mass flow rate [kg/s]
         REAL(r64) :: SupplyMassFlowRateForHumid  ! System supply air mass flow rate required to meet humdification load [kg/s]
         REAL(r64) :: SupplyMassFlowRateForDehum  ! System supply air mass flow rate required to meet dehumidification load [kg/s]
         REAL(r64) :: SupplyMassFlowRateForCool   ! System supply air mass flow rate required to meet sensible cooling load[kg/s]
         REAL(r64) :: SupplyMassFlowRateForHeat   ! System supply air mass flow rate required to meet sensible heating load[kg/s]
         REAL(r64) :: SupplyHumRatForHumid ! Supply air humidity ratio require to meet the humidification load [kgH2O/kgAir]
         REAL(r64) :: SupplyHumRatForDehum ! Supply air humidity ratio require to meet the dehumidification load [kgH2O/kgAir]
         REAL(r64) :: OAMassFlowRate    ! Outdoor air mass flow rate [kg/s]
         REAL(r64) :: OAVolFlowRate     ! Outdoor air volume flow rate at standard density [m3/s]
         REAL(r64) :: MinOASensOutput   ! Minimum Outdoor air sensible output [W], <0 means OA is cooler than zone air
         REAL(r64) :: MinOALatOutput    ! Minimum Outdoor air moisture load [kg/s]
         REAL(r64) :: SensOutput        ! Sensible output [W] (psitive means heating, negative means cooling)
         REAL(r64) :: HeatSensOutput    ! Heating sensible output [W]
         REAL(r64) :: CoolSensOutput    ! Cooling sensible output [W] (positive value menas cooling)
         REAL(r64) :: LatOutput         ! Latent output [W] (positive value means hudmification, negative means dehumidification)
         REAL(r64) :: CoolLatOutput     ! Cooling latent output [W] (positive value means dehumidification)
         REAL(r64) :: CoolTotOutput     ! Cooling total output [W] (positive value means cooling)
         REAL(r64) :: DeltaT            ! Delta temperature - reused in multiple places
         REAL(r64) :: DeltaHumRat       ! Delta humidity ratio - reused in multiple places
         REAL(r64) :: QZnHeatSP         ! Load required to meet heating setpoint [W] (>0 is a heating load)
         REAL(r64) :: QZnCoolSP         ! Load required to meet cooling setpoint [W] (<0 is a cooling load)
         REAL(r64) :: MdotZnHumidSP     ! Load required to meet humidifying setpoint [kg H2O/s] (>0 = a humidify load)
         REAL(r64) :: MdotZnDehumidSP   ! Load required to meet dehumidifying setpoint [kg H2O/s] (<0 = a dehumidify load)
         LOGICAL   :: UnitOn
         LOGICAL   :: HeatOn            ! Flag for heating and humidification availbility schedule, true if heating is on
         LOGICAL   :: CoolOn            ! Flag for cooling and dehumidification availbility schedule, true if cooling is on
         LOGICAL   :: EconoOn           ! Flag for economizer operation, true if economizer is on
         REAL(r64) :: SupplyTemp        ! Supply inlet to zone dry bulb temperature [C]
         REAL(r64) :: SupplyHumRat      ! Supply inlet to zone humidity ratio [kg H2O/kg Air]
         REAL(r64) :: SupplyHumRatOrig  ! Supply inlet to zone humidity ratio before saturation check [kg H2O/kg Air]
         REAL(r64) :: SupplyHumRatSat   ! Supply inlet to zone humidity ratio saturation at SupplyTemp [kg H2O/kg Air]
         REAL(r64) :: SupplyEnthalpy    ! Supply inlet to zone enthalpy [J/kg]
         REAL(r64) :: MixedAirTemp      ! Mixed air dry bulb temperature [C]
         REAL(r64) :: MixedAirHumRat    ! Mixed air humidity ratio [kg H2O/kg Air]
         REAL(r64) :: MixedAirEnthalpy  ! Mixed air enthalpy [J/kg]
         REAL(r64) :: CpAir        ! Specific heat [J/kg-C] reused in multiple places
!         REAL(r64) :: SpecHumOut   ! Specific humidity ratio of outlet air (kg moisture / kg moist air)
!         REAL(r64) :: SpecHumIn    ! Specific humidity ratio of inlet [zone] air (kg moisture / kg moist air)

           ! Sign convention: SysOutputProvided <0 Supply air is heated on entering zone (zone is cooled)
           !                  SysOutputProvided >0 Supply air is cooled on entering zone (zone is heated)
         InNodeNum = PurchAir(PurchAirNum)%ZoneSupplyAirNodeNum
         ZoneNodeNum = ZoneEquipConfig(ControlledZoneNum)%ZoneNode
         OANodeNum = PurchAir(PurchAirNum)%OutdoorAirNodeNum
         RecircNodeNum = PurchAir(PurchAirNum)%ZoneRecircAirNodeNum
         SupplyMassFlowRate = 0.0d0
         OAMassFlowRate = 0.0d0
         PurchAir(PurchAirNum)%MinOAMassFlowRate = 0.0d0
         PurchAir(PurchAirNum)%TimeEconoActive = 0.0d0
         PurchAir(PurchAirNum)%TimeHtRecActive = 0.0d0
         SysOutputProvided = 0.0d0
         MoistOutputProvided = 0.0d0
         CoolSensOutput = 0.0d0
         CoolLatOutput = 0.0d0
         CoolTotOutput = 0.0d0
         HeatSensOutput = 0.0d0
         LatOutput = 0.0d0


            ! default unit to ON
         UnitOn = .TRUE.
         EconoOn = .FALSE.
            ! get current zone requirements
         QZnHeatSP       = ZoneSysEnergyDemand(ActualZoneNum)%RemainingOutputReqToHeatSP
         QZnCoolSP       = ZoneSysEnergyDemand(ActualZoneNum)%RemainingOutputReqToCoolSP

         IF (ALLOCATED(ZoneComp)) THEN
           ZoneComp(PurchasedAir_Num)%ZoneCompAvailMgrs(PurchAirNum)%ZoneNum = ActualZoneNum
           PurchAir(PurchAirNum)%AvailStatus = ZoneComp(PurchasedAir_Num)%ZoneCompAvailMgrs(PurchAirNum)%AvailStatus
            ! Check if the hybrid ventilation availability manager is turning the unit off
           IF (PurchAir(PurchAirNum)%AvailStatus .EQ. ForceOFf) THEN
             UnitOn = .FALSE.
           END IF
         ENDIF

            ! Check if the unit is scheduled off
!         IF (PurchAir(PurchAirNum)%AvailSchedPtr > 0) THEN
             IF (GetCurrentScheduleValue(PurchAir(PurchAirNum)%AvailSchedPtr) <= 0) THEN
                 UnitOn = .FALSE.
             END IF
!         END IF
            ! Check if heating and cooling available
         HeatOn = .TRUE.
!         IF (PurchAir(PurchAirNum)%HeatSchedPtr > 0) THEN
             IF (GetCurrentScheduleValue(PurchAir(PurchAirNum)%HeatSchedPtr) <= 0) THEN
                 HeatOn = .FALSE.
             END IF
!         END IF
         CoolOn = .TRUE.
!         IF (PurchAir(PurchAirNum)%CoolSchedPtr > 0) THEN
             IF (GetCurrentScheduleValue(PurchAir(PurchAirNum)%CoolSchedPtr) <= 0) THEN
                 CoolOn = .FALSE.
             END IF
!         END IF

         IF (UnitON) THEN
             ! Calculate current minimum outdoor air flow rate based on design OA specifications and DCV or CO2 control
             CALL CalcPurchAirMinOAMassFlow(PurchAirNum, ActualZoneNum, OAMassFlowRate)

             ! EMS override point  Purch air outdoor air massflow rate.....
             IF (PurchAir(PurchAirNum)%EMSOverrideOAMdotOn) THEN
               OAMassFlowRate = PurchAir(PurchAirNum)%EMSValueOAMassFlowRate
             ENDIF

             ! Calculate minimum outdoor air sensible and latent load
             IF (PurchAir(PurchAirNum)%OutdoorAir) THEN
               CpAir = PsyCpAirFnWTdb(Node(OANodeNum)%HumRat,Node(OANodeNum)%Temp, 'CalcPurchAirLoads')
               MinOASensOutput = OAMassFlowRate * CpAir * (Node(OANodeNum)%Temp - Node(ZoneNodeNum)%Temp)
               MinOALatOutput  = OAMassFlowRate * (Node(OANodeNum)%HumRat - Node(ZoneNodeNum)%HumRat)
             ELSE
               MinOASensOutput = 0.0d0
               MinOALatOutput  = 0.0d0
             ENDIF
             SupplyMassFlowRate = OAMassFlowRate

             ! Check if cooling of the supply air stream is required

                                     ! Cooling operation
           IF ((MinOASensOutput >= QZnCoolSP) .AND. (TempControlType(ActualZoneNum) .NE. SingleHeatingSetPoint)) THEN
             OperatingMode = Cool
             ! Calculate supply mass flow, temp and humidity with the following constraints:
             !  Min cooling supply temp
             !  Max total cooling capacity
             !  Max cooling airflow
             !  Min cooling supply humrat  (and Max heating supply humrat)
             !  Min OA mass flow rate

             ! Check if OA flow rate greater than max cooling airflow limit
             IF (((PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRate) .OR. &
                  (PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRateAndCapacity)) &
                  .AND. (OAMassFlowRate .GT. PurchAir(PurchAirNum)%MaxCoolMassFlowRate)) THEN
               OAVolFlowRate = OAMassFlowRate / StdRhoAir
               IF (PurchAir(PurchAirNum)%OAFlowMaxCoolOutputError < 1) THEN
                 PurchAir(PurchAirNum)%OAFlowMaxCoolOutputError = PurchAir(PurchAirNum)%OAFlowMaxCoolOutputError + 1
                 Call ShowWarningError(TRIM(PurchAir(PurchAirNum)%cObjectName)//' "'//TRIM(PurchAir(PurchAirNum)%Name)//'"'&
                                       //' Requested outdoor air flow rate = '//TRIM(TrimSigDigits(OAVolFlowRate,5)) &
                                       //' [m3/s] exceeds limit.')
                 CALL ShowContinueError(' Will be reduced to the Maximum Cooling Air Flow Rate = ' &
                                        //TRIM(TrimSigDigits(PurchAir(PurchAirNum)%MaxCoolVolFlowRate,5))//' [m3/s]')
                 CALL ShowContinueErrorTimeStamp(' ')
               ELSE
                 CALL ShowRecurringWarningErrorAtEnd(TRIM(PurchAir(PurchAirNum)%cObjectName)//' "'&
                       //TRIM(PurchAir(PurchAirNum)%Name)//'"'//&
                       ' Requested outdoor air flow rate [m3/s] reduced to Maximum Cooling Air Flow Rate warning continues...' &
                       , PurchAir(PurchAirNum)%OAFlowMaxCoolOutputIndex, OAVolFlowRate)
               END IF
               OAMassFlowRate = PurchAir(PurchAirNum)%MaxCoolMassFlowRate

             ELSE
               ! Model economizer
               IF (PurchAir(PurchAirNum)%EconomizerType /= NoEconomizer) THEN
                 IF (((PurchAir(PurchAirNum)%EconomizerType == DifferentialDryBulb) &
                       .AND. (Node(OANodeNum)%Temp < Node(PurchAir(PurchAirNum)%ZoneRecircAirNodeNum)%Temp)) .OR. &
                     ((PurchAir(PurchAirNum)%EconomizerType == DifferentialEnthalpy) &
                       .AND. (Node(OANodeNum)%Enthalpy < Node(PurchAir(PurchAirNum)%ZoneRecircAirNodeNum)%Enthalpy))) THEN

                    ! Calculate supply MassFlowRate based on sensible load but limit to Max Cooling Supply Air Flow Rate if specified
                   CpAir = PsyCpAirFnWTdb(ZoneAirHumRat(ActualZoneNum),Node(ZoneNodeNum)%Temp, 'CalcPurchAirLoads')
                   DeltaT = (Node(OANodeNum)%Temp - Node(ZoneNodeNum)%Temp)
                   IF (DeltaT < -SmallTempDiff) THEN
                     SupplyMassFlowRate = QZnCoolSP/CPAir/DeltaT
                     IF (((PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRate) .OR. &
                          (PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRateAndCapacity)) &
                          .AND. (PurchAir(PurchAirNum)%MaxCoolMassFlowRate .GT. 0.0d0)) THEN
                       SupplyMassFlowRate = MIN(MAX(SupplyMassFlowRate,0.0d0),PurchAir(PurchAirNum)%MaxCoolMassFlowRate)
                     END IF
                     IF (SupplyMassFlowRate > OAMassFlowRate) THEN
                       EconoOn = .TRUE.
                       OAMassFlowRate = SupplyMassFlowRate
                       PurchAir(PurchAirNum)%TimeEconoActive = TimeStepSys
                     END IF
                   END IF
                 END IF
               END IF
             END IF

             ! Determine supply mass flow rate
                 ! Mass flow rate to meet sensible load, at Minimum Cooling Supply Air Temperature
             SupplyMassFlowRateForCool = 0.0d0
             IF (CoolOn) THEN
               CpAir = PsyCpAirFnWTdb(ZoneAirHumRat(ActualZoneNum),Node(ZoneNodeNum)%Temp, 'CalcPurchAirLoads')
               DeltaT = (PurchAir(PurchAirNum)%MinCoolSuppAirTemp - Node(ZoneNodeNum)%Temp)
               IF (DeltaT < -SmallTempDiff) THEN
                 SupplyMassFlowRateForCool = QZnCoolSP/CPAir/DeltaT
               ENDIF
             ENDIF

                 ! Mass flow rate to meet dehumidification load, if applicable, at Minimum Cooling Supply Humidity Ratio
             SupplyMassFlowRateForDehum = 0.0d0
             IF (CoolOn) THEN
               IF (PurchAir(PurchAirNum)%DehumidCtrlType .EQ. Humidistat) THEN
                 MdotZnDehumidSP= ZoneSysMoistureDemand(ActualZoneNum)%RemainingOutputReqToDehumidSP
                 DeltaHumRat = (PurchAir(PurchAirNum)%MinCoolSuppAirHumRat - Node(ZoneNodeNum)%HumRat)
                 IF ((DeltaHumRat < -SmallDeltaHumRat) .AND. (MdotZnDehumidSP .LT. 0.0d0)) THEN
                   SupplyMassFlowRateForDehum = MdotZnDehumidSP/DeltaHumRat
                 ENDIF
               ENDIF
             ENDIF

                 ! Mass flow rate to meet humidification load, if applicable, at Maximum Heating Supply Humidity Ratio
                 ! This section is the cooling section, so humidification should activate only if humidification control = humidistat
                 !   and if dehumidification control = humidistat or none
             SupplyMassFlowRateForHumid = 0.0d0
             IF (HeatOn) THEN
               IF (PurchAir(PurchAirNum)%HumidCtrlType .EQ. Humidistat) THEN
                 IF ((PurchAir(PurchAirNum)%DehumidCtrlType .EQ. Humidistat) .OR. &
                     (PurchAir(PurchAirNum)%DehumidCtrlType .EQ. None)) THEN
                   MdotZnHumidSP = ZoneSysMoistureDemand(ActualZoneNum)%RemainingOutputReqToHumidSP
                   DeltaHumRat = (PurchAir(PurchAirNum)%MaxHeatSuppAirHumRat - Node(ZoneNodeNum)%HumRat)
                   IF ((DeltaHumRat > SmallDeltaHumRat) .AND. (MdotZnHumidSP .GT. 0.0d0)) THEN
                     SupplyMassFlowRateForHumid = MdotZnHumidSP/DeltaHumRat
                   ENDIF
                 ENDIF
               ENDIF
             ENDIF

                 ! Supply mass flow is greatest of these, but limit to cooling max flow rate, if applicable
             SupplyMassFlowRate = MAX(0.0d0, OAMassFlowRate, SupplyMassFlowRateForCool, &
                                     SupplyMassFlowRateForDehum, SupplyMassFlowRateForHumid)
             ! EMS override point  Purch air massflow rate..... but only if unit is on, i.e. SupplyMassFlowRate>0.0
             IF ((PurchAir(PurchAirNum)%EMSOverrideMdotOn) .AND. (SupplyMassFlowRate > 0.0d0)) THEN
               SupplyMassFlowRate = PurchAir(PurchAirNum)%EMSValueMassFlowRate
               OAMassFlowRate = MIN(OAMassFlowRate,SupplyMassFlowRate)
             ENDIF
             IF (((PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRate) .OR. &
                  (PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRateAndCapacity)) &
                  .AND. (PurchAir(PurchAirNum)%MaxCoolMassFlowRate .GT. 0.0d0)) THEN
               SupplyMassFlowRate = MIN(SupplyMassFlowRate,PurchAir(PurchAirNum)%MaxCoolMassFlowRate)
             END IF

             IF (SupplyMassFlowRate <= VerySmallMassFlow) SupplyMassFlowRate = 0.0d0

             ! Calculate mixed air conditions
             CALL CalcPurchAirMixedAir(PurchAirNum, OAMassFlowRate, SupplyMassFlowRate, &
                                         MixedAirTemp, MixedAirHumRat, MixedAirEnthalpy, OperatingMode)

             ! Calculate supply air conditions using final massflow rate, imposing capacity limits if specified
             ! If capacity limits are exceeded, keep massflow rate where it is and adjust supply temp
             ! In general, in the cooling section, don't let SupplyTemp be set to something that results in heating
             IF (SupplyMassFlowRate .GT. 0.0d0) THEN
               ! Calculate supply temp at SupplyMassFlowRate and recheck limit on Minimum Cooling Supply Air Temperature
               CpAir = PsyCpAirFnWTdb(ZoneAirHumRat(ActualZoneNum),Node(ZoneNodeNum)%Temp, 'CalcPurchAirLoads')
               SupplyTemp = QZnCoolSP/(CPAir*SupplyMassFlowRate) + Node(ZoneNodeNum)%Temp
               SupplyTemp = MAX(SupplyTemp,PurchAir(PurchAirNum)%MinCoolSuppAirTemp)
               ! This is the cooling mode, so SupplyTemp can't be more than MixedAirTemp
               SupplyTemp = MIN(SupplyTemp,MixedAirTemp)
               SupplyHumRat = MixedAirHumRat
               SupplyEnthalpy = PsyHFnTdbW(SupplyTemp,SupplyHumRat, 'CalcPurchAirLoads')

               ! Check sensible load vs max total cooling capacity, if specified, and adjust supply temp before applying humidity controls
               ! Will check again later, too
               IF ((PurchAir(PurchAirNum)%CoolingLimit == LimitCapacity) .OR. &
                   (PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRateAndCapacity)) THEN
                 CpAir = PsyCpAirFnWTdb(MixedAirHumRat,MixedAirTemp, 'CalcPurchAirLoads')
                 CoolSensOutput = SupplyMassFlowRate * (MixedAirEnthalpy - SupplyEnthalpy)
                 IF (CoolSensOutput >= PurchAir(PurchAirNum)%MaxCoolTotCap) THEN
                   CoolSensOutput = PurchAir(PurchAirNum)%MaxCoolTotCap
                   SupplyEnthalpy = MixedAirEnthalpy - CoolSensOutput/SupplyMassFlowRate
                   SupplyTemp = PsyTdbFnHW(SupplyEnthalpy,SupplyHumRat, 'CalcPurchAirLoads')
                   ! This is the cooling mode, so SupplyTemp can't be more than MixedAirTemp
                   SupplyTemp = MIN(SupplyTemp,MixedAirTemp)
                 END IF ! Capacity limit exceeded
               END IF

               ! Set supply humidity ratio for cooling/dehumidification
               SupplyHumRat = MixedAirHumRat
               SELECT CASE(PurchAir(PurchAirNum)%DehumidCtrlType)
                 CASE(None)
                   SupplyHumRat = MixedAirHumRat
                 CASE(ConstantSensibleHeatRatio)
                   ! SHR = CoolSensOutput/CoolTotOutput
                   ! CoolTotOutput = CoolSensOutput/SHR
                   CpAir = PsyCpAirFnWTdb(MixedAirHumRat,MixedAirTemp, 'CalcPurchAirLoads')
                   CoolSensOutput = SupplyMassFlowRate * CpAir * (MixedAirTemp - SupplyTemp)
                   CoolTotOutput = CoolSensOutput/PurchAir(PurchAirNum)%CoolSHR
                   SupplyEnthalpy = MixedAirEnthalpy - CoolTotOutput/SupplyMassFlowRate
                   !  Limit for overdrying (avoid Pysch errors which occur if SupplyEnthalpy is too low for SupplyTemp)
                   SupplyEnthalpy = MAX(SupplyEnthalpy,PsyHFnTdbW(SupplyTemp,0.00001D0, 'CalcPurchAirLoads'))
                   SupplyHumRat = MIN(SupplyHumRat,PsyWFnTdbH(SupplyTemp,SupplyEnthalpy, 'CalcPurchAirLoads'))
                   ! Apply min cooling humidity ratio limit
                   SupplyHumRat = MAX(SupplyHumRat, PurchAir(PurchAirNum)%MinCoolSuppAirHumRat)
                   ! But don't let it be higher than incoming MixedAirHumRat
                   SupplyHumRat = MIN(SupplyHumRat,MixedAirHumRat)
                 CASE(Humidistat)
                   MdotZnDehumidSP= ZoneSysMoistureDemand(ActualZoneNum)%RemainingOutputReqToDehumidSP
                   SupplyHumRatForDehum = MdotZnDehumidSP/SupplyMassFlowRate + Node(ZoneNodeNum)%HumRat
                   SupplyHumRatForDehum = MIN(SupplyHumRatForDehum,PurchAir(PurchAirNum)%MinCoolSuppAirHumRat)
                   SupplyHumRat = MIN(MixedAirHumRat,SupplyHumRatForDehum)
                 CASE(ConstantSupplyHumidityRatio)
                   SupplyHumRat = PurchAir(PurchAirNum)%MinCoolSuppAirHumRat
                 CASE DEFAULT
                   SupplyHumRat = MixedAirHumRat
               END SELECT

                   ! Check supply humidity ratio for humidification (SupplyHumRatForHum should always be < SupplyHumRatForDehum)
                   ! This section is the cooling section, so humidification should activate only if humidification control = humidistat
                   !   and if dehumidification control = humidistat or none
               IF (HeatOn) THEN
                 IF (PurchAir(PurchAirNum)%HumidCtrlType .EQ. Humidistat) THEN
                   IF ((PurchAir(PurchAirNum)%DehumidCtrlType .EQ. Humidistat) .OR. &
                       (PurchAir(PurchAirNum)%DehumidCtrlType .EQ. None)) THEN
                     MdotZnHumidSP = ZoneSysMoistureDemand(ActualZoneNum)%RemainingOutputReqToHumidSP
                     SupplyHumRatForHumid = MdotZnHumidSP/SupplyMassFlowRate + Node(ZoneNodeNum)%HumRat
                     SupplyHumRatForHumid = MIN(SupplyHumRatForHumid,PurchAir(PurchAirNum)%MaxHeatSuppAirHumRat)
                     SupplyHumRat = MAX(SupplyHumRat,SupplyHumRatForHumid)
                   END IF
                 END IF
               END IF

               !   Limit supply humidity ratio to saturation at supply outlet temp
               SupplyHumRatOrig = SupplyHumRat
               SupplyHumRatSat  = PsyWFnTdbRhPb(SupplyTemp,1.0d0,OutBaroPress, 'CalcPurchAirLoads')
               SupplyHumRat = MIN(SupplyHumRatOrig,SupplyHumRatSat)
               SupplyEnthalpy = PsyHFnTdbW(SupplyTemp,SupplyHumRat, 'CalcPurchAirLoads')

               ! Check max total Cooling capacity, if specified
               IF ((PurchAir(PurchAirNum)%CoolingLimit == LimitCapacity) .OR. &
                   (PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRateAndCapacity)) THEN
                 ! If dehumidifying, compare total cooling to the limit
                 IF (SupplyHumRat < MixedAirHumRat) THEN ! Dehumidifying
                   CoolTotOutput = SupplyMassFlowRate * (MixedAirEnthalpy - SupplyEnthalpy)
                   IF ((CoolTotOutput) > PurchAir(PurchAirNum)%MaxCoolTotCap) THEN
                     CoolTotOutput = PurchAir(PurchAirNum)%MaxCoolTotCap
                     SupplyEnthalpy = MixedAirEnthalpy - CoolTotOutput/SupplyMassFlowRate
                     ! Adjust output based on dehumidification control type
                     SELECT CASE(PurchAir(PurchAirNum)%DehumidCtrlType)
                       CASE(ConstantSensibleHeatRatio)
                         ! Adjust both supply temp and humidity ratio to maintain SHR
                         ! SHR = CoolSensOutput/CoolTotOutput
                         ! CoolSensOutput = SHR*CoolTotOutput
                         CpAir = PsyCpAirFnWTdb(MixedAirHumRat,MixedAirTemp, 'CalcPurchAirLoads')
                         CoolSensOutput = CoolTotOutput * PurchAir(PurchAirNum)%CoolSHR
                         SupplyTemp = MixedAirTemp - CoolSensOutput/(CPAir*SupplyMassFlowRate)
                         ! This is the cooling mode, so SupplyTemp can't be more than MixedAirTemp
                         SupplyTemp = MIN(SupplyTemp,MixedAirTemp)
                         !  Limit for overdrying (avoid Pysch errors which occur if SupplyEnthalpy is too low for SupplyTemp)
                         SupplyEnthalpy = MAX(SupplyEnthalpy,PsyHFnTdbW(SupplyTemp,0.00001D0, 'CalcPurchAirLoads'))
                         SupplyHumRat = PsyWFnTdbH(SupplyTemp,SupplyEnthalpy, 'CalcPurchAirLoads')
                       CASE(Humidistat)
                         ! Keep supply temp and adjust humidity ratio to reduce load
                         SupplyHumRat = PsyWFnTdbH(SupplyTemp,SupplyEnthalpy, 'CalcPurchAirLoads')
                       CASE(None, ConstantSupplyHumidityRatio)
                         ! Keep humidity ratio and adjust supply temp
                         ! Check if latent output exceeds capacity
                         CpAir = PsyCpAirFnWTdb(MixedAirHumRat,MixedAirTemp, 'CalcPurchAirLoads')
                         CoolSensOutput = SupplyMassFlowRate * CpAir * (MixedAirTemp - SupplyTemp)
                         CoolLatOutput = CoolTotOutput - CoolSensOutput
                         IF (CoolLatOutput >= PurchAir(PurchAirNum)%MaxCoolTotCap) THEN
                           SupplyTemp   = MixedAirTemp
                           SupplyHumRat = PsyWFnTdbH(SupplyTemp,SupplyEnthalpy, 'CalcPurchAirLoads')
                           CoolLatOutput = PurchAir(PurchAirNum)%MaxCoolTotCap
                         ELSE
                           SupplyTemp = PsyTdbFnHW(SupplyEnthalpy,SupplyHumRat, 'CalcPurchAirLoads')
                           ! This is the cooling mode, so SupplyTemp can't be more than MixedAirTemp
                           SupplyTemp = MIN(SupplyTemp,MixedAirTemp)
                         END IF
                     END SELECT
                     ! Limit supply humidity ratio to saturation at supply outlet temp
                     ! If saturation exceeded, then honor capacity limit and set to dew point at supplyenthalpy
                     SupplyHumRatOrig = SupplyHumRat
                     SupplyHumRatSat  = PsyWFnTdbRhPb(SupplyTemp,1.0d0,OutBaroPress, 'CalcPurchAirLoads')
                     IF (SupplyHumRatSat < SupplyHumRatOrig) THEN
                       SupplyTemp = PsyTsatFnHPb(SupplyEnthalpy,OutBaroPress,'CalcPurchAirLoads')
                       ! This is the cooling mode, so SupplyTemp can't be more than MixedAirTemp
                       SupplyTemp = MIN(SupplyTemp,MixedAirTemp)
                       SupplyHumRat = PsyWFnTdbH(SupplyTemp,SupplyEnthalpy,'CalcPurchAirLoads')
                       SupplyEnthalpy = PsyHFnTdbW(SupplyTemp,SupplyHumRat, 'CalcPurchAirLoads')
                       ! CpAir = PsyCpAirFnWTdb(MixedAirHumRat,MixedAirTemp, 'CalcPurchAirLoads')
                       ! CoolSensOutput = SupplyMassFlowRate * CpAir * (MixedAirTemp - SupplyTemp)
                       ! CoolTotOutput = SupplyMassFlowRate * (MixedAirEnthalpy - SupplyEnthalpy)
                     END IF
                   END IF ! Capacity limit exceeded
                 ELSE  ! Not dehumidifying
                   ! If not dehumidifying, compare sensible cooling to the limit
                   ! This section will only increase supply temp, so no need to recheck for super-saturation
                   CpAir = PsyCpAirFnWTdb(MixedAirHumRat,MixedAirTemp, 'CalcPurchAirLoads')
                   CoolSensOutput = SupplyMassFlowRate * CpAir * (MixedAirTemp - SupplyTemp)
                   IF (CoolSensOutput >= PurchAir(PurchAirNum)%MaxCoolTotCap) THEN
                     CoolSensOutput = PurchAir(PurchAirNum)%MaxCoolTotCap
                     SupplyTemp = MixedAirTemp - CoolSensOutput/(SupplyMassFlowRate * CpAir)
                   END IF ! Capacity limit exceeded
                 END IF  ! Dehumidifying or not
               END IF  ! Capacity limit active

             ELSE ! SupplyMassFlowRate is zero
               SupplyEnthalpy = MixedAirEnthalpy
               SupplyHumRat   = MixedAirHumRat
               SupplyTemp     = MixedAirTemp
               CoolSensOutput = 0.0d0
               CoolTotOutput  = 0.0d0
             END IF
                                     ! Heating or no-load operation
           ELSE  ! Heating or no-load case
             IF ((MinOASensOutput .LT. QZnHeatSP) .AND. (TempControlType(ActualZoneNum) .NE. SingleCoolingSetPoint)) THEN
               OperatingMode = Heat
             ELSE ! Deadband mode shuts off heat recovery and economizer
               OperatingMode = Deadband
             END IF
             ! Calculate supply mass flow, temp and humidity with the following constraints:
             !  Max heating supply temp
             !  Max sensible heating capacity
             !  Max heating airflow
             !  Max heating supply humrat (and Min cooling supply humrat)
             !  Min OA mass flow rate

             ! Check if OA flow rate greater than max heating airflow limit
             IF (((PurchAir(PurchAirNum)%HeatingLimit == LimitFlowRate) .OR. &
                  (PurchAir(PurchAirNum)%HeatingLimit == LimitFlowRateAndCapacity)) &
                  .AND. (OAMassFlowRate .GT. PurchAir(PurchAirNum)%MaxHeatMassFlowRate)) THEN
               OAVolFlowRate = OAMassFlowRate / StdRhoAir
               IF (PurchAir(PurchAirNum)%OAFlowMaxHeatOutputError < 1) THEN
                 PurchAir(PurchAirNum)%OAFlowMaxHeatOutputError = PurchAir(PurchAirNum)%OAFlowMaxHeatOutputError + 1
                 Call ShowWarningError(TRIM(PurchAir(PurchAirNum)%cObjectName)//' "'//TRIM(PurchAir(PurchAirNum)%Name)//'"'&
                                       //' Requested outdoor air flow rate = '//TRIM(TrimSigDigits(OAVolFlowRate,5)) &
                                       //' [m3/s] exceeds limit.')
                 CALL ShowContinueError(' Will be reduced to the Maximum Heating Air Flow Rate = ' &
                                        //TRIM(TrimSigDigits(PurchAir(PurchAirNum)%MaxHeatVolFlowRate,5))//' [m3/s]')
                 CALL ShowContinueErrorTimeStamp(' ')
               ELSE
                 CALL ShowRecurringWarningErrorAtEnd(TRIM(PurchAir(PurchAirNum)%cObjectName)//' "'&
                       //TRIM(PurchAir(PurchAirNum)%Name)//'"'//&
                       ' Requested outdoor air flow rate [m3/s] reduced to Maximum Heating Air Flow Rate warning continues...' &
                       , PurchAir(PurchAirNum)%OAFlowMaxHeatOutputIndex, OAVolFlowRate)
               END IF
               OAMassFlowRate = PurchAir(PurchAirNum)%MaxHeatMassFlowRate
             ENDIF

             SupplyMassFlowRate = OAMassFlowRate

             ! Determine supply mass flow rate
                 ! Mass flow rate to meet sensible load, at Minimum Cooling Supply Air Temperature
             SupplyMassFlowRateForHeat = 0.0d0
             IF ((HeatOn) .AND. (OperatingMode == Heat)) THEN
               CpAir = PsyCpAirFnWTdb(ZoneAirHumRat(ActualZoneNum),Node(ZoneNodeNum)%Temp, 'CalcPurchAirLoads')
               DeltaT = (PurchAir(PurchAirNum)%MaxHeatSuppAirTemp - Node(ZoneNodeNum)%Temp)
               IF (DeltaT > SmallTempDiff) THEN
                 SupplyMassFlowRateForHeat = QZnHeatSP/CPAir/DeltaT
               ENDIF
             ENDIF

                 ! Mass flow rate to meet dehumidification load, if applicable, at Minimum Cooling Supply Humidity Ratio
                 ! This section is the heating/deadband section, so dehumidification should activate
                 !   only if dehumidification control = humidistat
                 !   and if humidification control = humidistat or none or if operating in deadband mode
             SupplyMassFlowRateForDehum = 0.0d0
             IF (CoolOn) THEN
               IF (PurchAir(PurchAirNum)%DehumidCtrlType .EQ. Humidistat) THEN
                 IF ((PurchAir(PurchAirNum)%HumidCtrlType .EQ. Humidistat) .OR. &
                     (PurchAir(PurchAirNum)%HumidCtrlType .EQ. None) .OR. &
                     (OperatingMode == Deadband)) THEN
                   MdotZnDehumidSP= ZoneSysMoistureDemand(ActualZoneNum)%RemainingOutputReqToDehumidSP
                   DeltaHumRat = (PurchAir(PurchAirNum)%MinCoolSuppAirHumRat - Node(ZoneNodeNum)%HumRat)
                   IF ((DeltaHumRat < -SmallDeltaHumRat) .AND. (MdotZnDehumidSP .LT. 0.0d0)) THEN
                     SupplyMassFlowRateForDehum = MdotZnDehumidSP/DeltaHumRat
                   ENDIF
                 ENDIF
               ENDIF
             ENDIF

                 ! Mass flow rate to meet humidification load, if applicable, at Maximum Heating Supply Humidity Ratio
             SupplyMassFlowRateForHumid = 0.0d0
             IF (HeatOn) THEN
               IF (PurchAir(PurchAirNum)%HumidCtrlType .EQ. Humidistat) THEN
                 MdotZnHumidSP = ZoneSysMoistureDemand(ActualZoneNum)%RemainingOutputReqToHumidSP
                 DeltaHumRat = (PurchAir(PurchAirNum)%MaxHeatSuppAirHumRat - Node(ZoneNodeNum)%HumRat)
                 IF ((DeltaHumRat > SmallDeltaHumRat) .AND. (MdotZnHumidSP .GT. 0.0d0)) THEN
                   SupplyMassFlowRateForHumid = MdotZnHumidSP/DeltaHumRat
                 ENDIF
               ENDIF
             ENDIF

                 ! Supply mass flow is greatest of these, but limit to heating max flow rate, if applicable
             SupplyMassFlowRate = MAX(0.0d0, OAMassFlowRate, SupplyMassFlowRateForHeat, &
                                     SupplyMassFlowRateForDehum, SupplyMassFlowRateForHumid)
             ! EMS override point  Purch air massflow rate..... but only if unit is on, i.e. SupplyMassFlowRate>0.0
             IF ((PurchAir(PurchAirNum)%EMSOverrideMdotOn) .AND. (SupplyMassFlowRate > 0.0d0)) THEN
               SupplyMassFlowRate = PurchAir(PurchAirNum)%EMSValueMassFlowRate
               OAMassFlowRate = MIN(OAMassFlowRate,SupplyMassFlowRate)
             ENDIF
             IF (((PurchAir(PurchAirNum)%HeatingLimit == LimitFlowRate) .OR. &
                  (PurchAir(PurchAirNum)%HeatingLimit == LimitFlowRateAndCapacity)) &
                  .AND. (PurchAir(PurchAirNum)%MaxHeatMassFlowRate .GT. 0.0d0)) THEN
               SupplyMassFlowRate = MIN(SupplyMassFlowRate,PurchAir(PurchAirNum)%MaxHeatMassFlowRate)
             END IF

             IF (SupplyMassFlowRate <= VerySmallMassFlow) SupplyMassFlowRate = 0.0d0


             ! Calculate mixed air conditions
             CALL CalcPurchAirMixedAir(PurchAirNum, OAMassFlowRate, SupplyMassFlowRate, &
                                         MixedAirTemp, MixedAirHumRat, MixedAirEnthalpy, OperatingMode)

             ! Calculate supply air conditions using final massflow rate, imposing capacity limits if specified
             ! If capacity limits are exceeded, keep massflow rate where it is and adjust supply temp
             IF (SupplyMassFlowRate .GT. 0.0d0) THEN
               IF ((HeatOn) .AND. (OperatingMode == Heat)) THEN
                 ! Calculate supply temp at SupplyMassFlowRate and check limit on Maximum Heating Supply Air Temperature
                 CpAir = PsyCpAirFnWTdb(ZoneAirHumRat(ActualZoneNum),Node(ZoneNodeNum)%Temp, 'CalcPurchAirLoads')
                 SupplyTemp = QZnHeatSP/(CPAir*SupplyMassFlowRate) + Node(ZoneNodeNum)%Temp
                 SupplyTemp = MIN(SupplyTemp,PurchAir(PurchAirNum)%MaxHeatSuppAirTemp)
                 ! This is the heating mode, so SupplyTemp can't be less than MixedAirTemp
                 SupplyTemp = MAX(SupplyTemp,MixedAirTemp)
                 ! Check max heating capacity, if specified
                 IF ((PurchAir(PurchAirNum)%HeatingLimit == LimitCapacity) .OR. &
                   (PurchAir(PurchAirNum)%HeatingLimit == LimitFlowRateAndCapacity)) THEN
                   CpAir = PsyCpAirFnWTdb(MixedAirHumRat,MixedAirTemp, 'CalcPurchAirLoads')
                   HeatSensOutput = SupplyMassFlowRate * CpAir * (SupplyTemp - MixedAirTemp)
                   IF (HeatSensOutput > PurchAir(PurchAirNum)%MaxHeatSensCap) THEN
                     SupplyTemp = PurchAir(PurchAirNum)%MaxHeatSensCap/(SupplyMassFlowRate * CpAir) + MixedAirTemp
                     HeatSensOutput = PurchAir(PurchAirNum)%MaxHeatSensCap
                   END IF
                 END IF
               ELSE ! Heat is off or operating mode is deadband (i.e. don't do any heating)
                 SupplyTemp = MixedAirTemp
               END IF

               ! Set supply humidity ratio first for heating/humidification
               SupplyHumRat = MixedAirHumRat
               SELECT CASE(PurchAir(PurchAirNum)%HumidCtrlType)
                 CASE(None)
                   SupplyHumRat = MixedAirHumRat
                 CASE(Humidistat)
                   MdotZnHumidSP = ZoneSysMoistureDemand(ActualZoneNum)%RemainingOutputReqToHumidSP
                   SupplyHumRatForHumid = MdotZnHumidSP/SupplyMassFlowRate + Node(ZoneNodeNum)%HumRat
                   SupplyHumRatForHumid = MIN(SupplyHumRatForHumid,PurchAir(PurchAirNum)%MaxHeatSuppAirHumRat)
                   SupplyHumRat = MAX(SupplyHumRat,SupplyHumRatForHumid)
                 CASE(ConstantSupplyHumidityRatio)
                   IF (OperatingMode == Heat) THEN
                     ! If this results in dehumidification, must check cooling capacity limit
                     IF (MixedAirHumRat > PurchAir(PurchAirNum)%MaxHeatSuppAirHumRat) THEN
                       IF ((PurchAir(PurchAirNum)%CoolingLimit == LimitCapacity) .OR. &
                           (PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRateAndCapacity)) THEN
                         SupplyHumRat = PurchAir(PurchAirNum)%MaxHeatSuppAirHumRat
                         SupplyEnthalpy = PsyHFnTdbW(SupplyTemp,SupplyHumRat, 'CalcPurchAirLoads')
                         CoolTotOutput = SupplyMassFlowRate * (MixedAirEnthalpy - SupplyEnthalpy)
                         CpAir = PsyCpAirFnWTdb(MixedAirHumRat,MixedAirTemp, 'CalcPurchAirLoads')
                         CoolSensOutput = SupplyMassFlowRate * CpAir * (MixedAirTemp - SupplyTemp)
                         CoolLatOutput = CoolTotOutput - CoolSensOutput
                         IF (CoolLatOutput >= PurchAir(PurchAirNum)%MaxCoolTotCap) THEN
                           CoolLatOutput = PurchAir(PurchAirNum)%MaxCoolTotCap
                           CoolTotOutput = CoolSensOutput + CoolLatOutput
                           SupplyEnthalpy = MixedAirEnthalpy - CoolTotOutput/SupplyMassFlowRate
                           SupplyHumRat = PsyWFnTdbH(SupplyTemp,SupplyEnthalpy, 'CalcPurchAirLoads')
                         END IF
                       ELSE
                         SupplyHumRat = PurchAir(PurchAirNum)%MaxHeatSuppAirHumRat
                       END IF
                     ELSE
                       SupplyHumRat = PurchAir(PurchAirNum)%MaxHeatSuppAirHumRat
                     END IF
                   ELSE
                     SupplyHumRat = MixedAirHumRat
                   END IF
                 CASE DEFAULT
                   SupplyHumRat = MixedAirHumRat
               END SELECT
               SupplyEnthalpy = PsyHFnTdbW(SupplyTemp,SupplyHumRat, 'CalcPurchAirLoads')

                 ! Check supply humidity ratio for dehumidification (SupplyHumRatForHumid should always be < SupplyHumRatForDehum)
                 ! This section is the heating/deadband section, so dehumidification should activate
                 !   only if dehumidification control = humidistat
                 !   and if humidification control = humidistat or none or if operating in deadband mode
               IF (CoolOn) THEN
                 IF (PurchAir(PurchAirNum)%DehumidCtrlType .EQ. Humidistat) THEN
                   IF ((PurchAir(PurchAirNum)%HumidCtrlType .EQ. Humidistat) .OR. &
                       (PurchAir(PurchAirNum)%HumidCtrlType .EQ. None) .OR. &
                       (OperatingMode == Deadband)) THEN
                     MdotZnDehumidSP= ZoneSysMoistureDemand(ActualZoneNum)%RemainingOutputReqToDehumidSP
                     SupplyHumRatForDehum = MdotZnDehumidSP/SupplyMassFlowRate + Node(ZoneNodeNum)%HumRat
                     SupplyHumRatForDehum = MAX(SupplyHumRatForDehum,PurchAir(PurchAirNum)%MinCoolSuppAirHumRat)
                     SupplyHumRat = MIN(SupplyHumRat, SupplyHumRatForDehum)
                     SupplyEnthalpy = PsyHFnTdbW(SupplyTemp,SupplyHumRat, 'CalcPurchAirLoads')
                     IF (SupplyHumRat < MixedAirHumRat) THEN
                       ! At this point, the system is heating or deadband but dehumidifying, check max cooling cap limit
                       CpAir = PsyCpAirFnWTdb(MixedAirHumRat,MixedAirTemp)
                       SensOutput = SupplyMassFlowRate * CpAir * (SupplyTemp - MixedAirTemp)
                       LatOutput = SupplyMassFlowRate * (SupplyEnthalpy - MixedAirEnthalpy) - SensOutput
                       IF ((PurchAir(PurchAirNum)%CoolingLimit == LimitCapacity) .OR. &
                           (PurchAir(PurchAirNum)%CoolingLimit == LimitFlowRateAndCapacity)) THEN
                         IF (LatOutput > PurchAir(PurchAirNum)%MaxCoolTotCap) THEN
                           LatOutput = PurchAir(PurchAirNum)%MaxCoolTotCap
                           SupplyEnthalpy = MixedAirEnthalpy + (LatOutput + SensOutput)/SupplyMassFlowRate
                           SupplyHumRat = PsyWFnTdbH(SupplyTemp,SupplyEnthalpy, 'CalcPurchAirLoads')
                         END IF
                       END IF
                     END IF
                   END IF
                 END IF
               END IF


                 !   Limit supply humidity ratio to saturation at supply outlet temp
               SupplyHumRatOrig = SupplyHumRat
               SupplyHumRat = MIN(SupplyHumRat,PsyWFnTdbRhPb(SupplyTemp,1.0d0,OutBaroPress, 'CalcPurchAirLoads'))
               SupplyEnthalpy = PsyHFnTdbW(SupplyTemp,SupplyHumRat, 'CalcPurchAirLoads')

             ELSE ! SupplyMassFlowRate is zero
               SupplyEnthalpy = MixedAirEnthalpy
               SupplyHumRat   = MixedAirHumRat
               SupplyTemp     = MixedAirTemp
               HeatSensOutput = 0.0d0
             END IF

           END IF ! Cooling or heating required

             ! EMS override point  Purch air supply temp and humidty ratio ..... but only if unit is on, SupplyMassFlowRate>0.0
           IF ((PurchAir(PurchAirNum)%EMSOverrideSupplyTempOn) .AND. (SupplyMassFlowRate > 0.0d0)) THEN
             SupplyTemp = PurchAir(PurchAirNum)%EMSValueSupplyTemp
           ENDIF
           IF ((PurchAir(PurchAirNum)%EMSOverrideSupplyHumRatOn) .AND. (SupplyMassFlowRate > 0.0d0)) THEN
             SupplyHumRat = PurchAir(PurchAirNum)%EMSValueSupplyHumRat
           ENDIF

           IF (SupplyMassFlowRate > 0.0d0) THEN
             PurchAir(PurchAirNum)%FinalMixedAirTemp = MixedAirtemp
             PurchAir(PurchAirNum)%FinalMixedAirHumRat = MixedAirHumRat
             ! compute coil loads
             IF ((SupplyHumRat == MixedAirHumRat) .AND. (SupplyTemp == MixedAirTemp)) THEN
               ! If no change in humrat or temp, then set loads to zero
               PurchAir(PurchAirNum)%SenCoilLoad = 0.0d0
               PurchAir(PurchAirNum)%LatCoilLoad = 0.0d0
             ELSE IF ((SupplyHumRat == MixedAirHumRat) .AND. (SupplyTemp .NE. MixedAirTemp)) THEN
               ! If no change in humrat, then set latent load to zero and use enthalpies to calculate sensible load
               PurchAir(PurchAirNum)%SenCoilLoad = SupplyMassFlowRate * (SupplyEnthalpy - MixedAirEnthalpy)
               PurchAir(PurchAirNum)%LatCoilLoad = 0.0d0
             ELSE
               CpAir = PsyCpAirFnWTdb(MixedAirHumRat,MixedAirTemp)
               PurchAir(PurchAirNum)%SenCoilLoad = SupplyMassFlowRate * CpAir * (SupplyTemp - MixedAirTemp)
               PurchAir(PurchAirNum)%LatCoilLoad = SupplyMassFlowRate * (SupplyEnthalpy - MixedAirEnthalpy) &
                                                         - PurchAir(PurchAirNum)%SenCoilLoad
             END IF

             ! Apply heating and cooling availability schedules to sensible load
             IF (((PurchAir(PurchAirNum)%SenCoilLoad > 0.0d0) .AND. .NOT. HeatOn) &
                                  .OR.                                                       &
                 ((PurchAir(PurchAirNum)%SenCoilLoad < 0.0d0) .AND. .NOT. CoolOn)) THEN
               ! Coil is off
               PurchAir(PurchAirNum)%SenCoilLoad = 0.0d0
               SupplyTemp = MixedAirTemp
             END IF

             ! Apply heating and cooling availability schedules to latent load
             IF (((PurchAir(PurchAirNum)%LatCoilLoad > 0.0d0) .AND. .NOT. HeatOn) &
                                  .OR.                                                       &
                 ((PurchAir(PurchAirNum)%LatCoilLoad < 0.0d0) .AND. .NOT. CoolOn)) THEN
               ! Coil is off
               PurchAir(PurchAirNum)%LatCoilLoad = 0.0d0
               SupplyHumRat = MixedAirHumRat
             END IF

             ! Double-check if saturation exceeded, then thow warning, shouldn't happen here, don't reset, just warn
             SupplyHumRatOrig = SupplyHumRat
             SupplyHumRatSat  = PsyWFnTdbRhPb(SupplyTemp,1.0d0,OutBaroPress, 'CalcPurchAirLoads')
             DeltaHumRat = SupplyHumRatOrig - SupplyHumRatSat
             IF (DeltaHumRat > SmallDeltaHumRat) THEN
               IF (PurchAir(PurchAirNum)%SaturationOutputError < 1) THEN
                 PurchAir(PurchAirNum)%SaturationOutputError = PurchAir(PurchAirNum)%SaturationOutputError + 1
                 Call ShowWarningError(TRIM(PurchAir(PurchAirNum)%cObjectName)//' "'//TRIM(PurchAir(PurchAirNum)%Name)//'"'&
                                       //' Supply humidity ratio = '//TRIM(TrimSigDigits(SupplyHumRatOrig,5)) &
                                       //' exceeds saturation limit '//TRIM(TrimSigDigits(SupplyHumRatSat,5))//  &
                                       ' [kgWater/kgDryAir]')
                 CALL ShowContinueError(' Simulation continuing . . . ')
                 CALL ShowContinueErrorTimeStamp(' ')
               ELSE
                 CALL ShowRecurringWarningErrorAtEnd(TRIM(PurchAir(PurchAirNum)%cObjectName)//' "'&
                       //TRIM(PurchAir(PurchAirNum)%Name)//'"'//&
                       ' Supply humidity ratio exceeds saturation limit warning continues, delta max/min [kgWater/kgDryAir]...' &
                       , PurchAir(PurchAirNum)%SaturationOutputIndex, DeltaHumRat, DeltaHumRat)
               END IF
             END IF

             SupplyEnthalpy = PsyHFnTdbW(SupplyTemp,SupplyHumRat, 'CalcPurchAirLoads')

             CpAir = PsyCpAirFnWTdb(ZoneAirHumRat(ActualZoneNum),Node(ZoneNodeNum)%Temp)
             SysOutputProvided = SupplyMassFlowRate * CpAir * (SupplyTemp - Node(ZoneNodeNum)%Temp)
             MoistOutputProvided = SupplyMassFlowRate * (SupplyHumRat - Node(ZoneNodeNum)%HumRat) ! Latent rate, kg/s

             PurchAir(PurchAirNum)%SenOutputToZone = SysOutputProvided
             PurchAir(PurchAirNum)%LatOutputToZone = SupplyMassFlowRate * (SupplyEnthalpy - Node(ZoneNodeNum)%Enthalpy) &
                                                       - PurchAir(PurchAirNum)%SenOutputToZone

             CpAir = PsyCpAirFnWTdb(ZoneAirHumRat(ActualZoneNum),Node(ZoneNodeNum)%Temp)
             IF (PurchAir(PurchAirNum)%OutdoorAir) THEN
               PurchAir(PurchAirNum)%OASenOutput = OAMassFlowRate * CpAir * (Node(OANodeNum)%Temp - Node(ZoneNodeNum)%Temp)
               PurchAir(PurchAirNum)%OALatOutput = OAMassFlowRate * (Node(OANodeNum)%Enthalpy - Node(ZoneNodeNum)%Enthalpy) &
                                                       - PurchAir(PurchAirNum)%OASenOutput
             ELSE
               PurchAir(PurchAirNum)%OASenOutput = 0.0d0
               PurchAir(PurchAirNum)%OALatOutput = 0.0d0
             ENDIF
             IF (Contaminant%CO2Simulation) THEN
               IF (PurchAir(PurchAirNum)%OutdoorAir) THEN
                 Node(InNodeNum)%CO2 = ((SupplyMassFlowRate - OAMassFlowRate)*Node(RecircNodeNum)%CO2 + &
                    OAMassFlowRate*Node(OANodeNum)%CO2) / SupplyMassFlowRate
               Else
                 Node(InNodeNum)%CO2 = Node(RecircNodeNum)%CO2
               End If
             END IF
             IF (Contaminant%GenericContamSimulation) THEN
               IF (PurchAir(PurchAirNum)%OutdoorAir) THEN
                 Node(InNodeNum)%GenContam = ((SupplyMassFlowRate - OAMassFlowRate)*Node(RecircNodeNum)%GenContam + &
                    OAMassFlowRate*Node(OANodeNum)%GenContam) / SupplyMassFlowRate
               Else
                 Node(InNodeNum)%GenContam = Node(RecircNodeNum)%GenContam
               End If
             END IF
           ELSE ! SupplyMassFlowRate = 0.0
             SysOutputProvided  = 0.0d0
             MoistOutputProvided  = 0.0d0

             PurchAir(PurchAirNum)%SenOutputToZone = 0.0d0
             PurchAir(PurchAirNum)%LatOutputToZone = 0.0d0
             PurchAir(PurchAirNum)%SenCoilLoad = 0.0d0
             PurchAir(PurchAirNum)%LatCoilLoad = 0.0d0
             PurchAir(PurchAirNum)%OASenOutput = 0.0d0
             PurchAir(PurchAirNum)%OALatOutput = 0.0d0
             PurchAir(PurchAirNum)%FinalMixedAirTemp = Node(RecircNodeNum)%Temp
             PurchAir(PurchAirNum)%FinalMixedAirHumRat = Node(RecircNodeNum)%HumRat
             IF (Contaminant%CO2Simulation) THEN
               Node(InNodeNum)%CO2        = Node(ZoneNodeNum)%CO2
             END IF
             IF (Contaminant%GenericContamSimulation) THEN
               Node(InNodeNum)%GenContam  = Node(ZoneNodeNum)%GenContam
             END IF
           END IF

           Node(InNodeNum)%Temp         = SupplyTemp
           Node(InNodeNum)%HumRat       = SupplyHumRat
           Node(InNodeNum)%Enthalpy     = SupplyEnthalpy
           Node(InNodeNum)%MassFlowRate = SupplyMassFlowRate
           IF (PurchAir(PurchAirNum)%OutdoorAir) Node(OANodeNum)%MassFlowRate = OAMassFlowRate

         ELSE ! purchased air OFF

           SysOutputProvided  = 0.0d0
           MoistOutputProvided  = 0.0d0
           SupplyMassFlowRate = 0.0d0
           OAMassFlowRate     = 0.0d0
           Node(InNodeNum)%Temp         = Node(ZoneNodeNum)%Temp
           Node(InNodeNum)%HumRat       = Node(ZoneNodeNum)%HumRat
           Node(InNodeNum)%Enthalpy     = Node(ZoneNodeNum)%Enthalpy
           IF (Contaminant%CO2Simulation) THEN
             Node(InNodeNum)%CO2        = Node(ZoneNodeNum)%CO2
           END IF
           IF (Contaminant%GenericContamSimulation) THEN
             Node(InNodeNum)%GenContam  = Node(ZoneNodeNum)%GenContam
           END IF

           Node(InNodeNum)%MassFlowRate = 0.0d0
           IF (PurchAir(PurchAirNum)%OutdoorAir) Node(OANodeNum)%MassFlowRate = 0.0d0
           PurchAir(PurchAirNum)%SenHeatRate = 0.0d0
           PurchAir(PurchAirNum)%SenCoolRate = 0.0d0
           PurchAir(PurchAirNum)%TotCoolRate = 0.0d0

           PurchAir(PurchAirNum)%SenOutputToZone = 0.0d0
           PurchAir(PurchAirNum)%LatOutputToZone = 0.0d0
           PurchAir(PurchAirNum)%SenCoilLoad = 0.0d0
           PurchAir(PurchAirNum)%LatCoilLoad = 0.0d0
           PurchAir(PurchAirNum)%OASenOutput = 0.0d0
           PurchAir(PurchAirNum)%OALatOutput = 0.0d0
           PurchAir(PurchAirNum)%FinalMixedAirTemp = Node(RecircNodeNum)%Temp
           PurchAir(PurchAirNum)%FinalMixedAirHumRat = Node(RecircNodeNum)%HumRat

         END IF

         PurchAir(PurchAirNum)%OutdoorAirMassFlowRate = OAMassFlowRate

         RETURN

    END SUBROUTINE CalcPurchAirLoads

    SUBROUTINE CalcPurchAirMinOAMassFlow(PurchAirNum, ActualZoneNum, OAMassFlowRate)

              ! SUBROUTINE INFORMATION:
              !       AUTHOR         M. Witte (GARD)
              !       DATE WRITTEN   Jun 2011 (taken from HVACSingleDuctSystem.f90 and adapted for Ideal Loads System)
              !       MODIFIED       na
              !       RE-ENGINEERED  na

              ! PURPOSE OF THIS SUBROUTINE:
              ! Calculates the amount of outside air required based on optional user input.
              ! Zone multipliers have been applied in GetInput.

              ! METHODOLOGY EMPLOYED:
              ! User input defines method used to calculate OA.

              ! REFERENCES:

              ! USE STATEMENTS:
        USE DataHeatBalance,   ONLY: ZoneIntGain, Zone
        USE DataEnvironment,   ONLY: StdRhoAir
        USE DataSizing, ONLY: OAFlowPPer, OAFlow, OAFlowPerArea, OAFlowACH, OAFlowSum, OAFlowMax
        USE DataContaminantBalance, ONLY: ZoneSysContDemand
        USE DataZoneEquipment, ONLY: CalcDesignSpecificationOutdoorAir

        IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

              ! SUBROUTINE ARGUMENT DEFINITIONS:
        INTEGER, INTENT(IN)      :: PurchAirNum    ! index to ideal loads unit
        INTEGER, INTENT(IN)      :: ActualZoneNum  ! index to actual zone number
        REAL(r64), INTENT(OUT)   :: OAMassFlowRate ! outside air mass flow rate [kg/s] from volume flow using std density

              ! FUNCTION PARAMETER DEFINITIONS:
        LOGICAL, PARAMETER   :: UseMinOASchFlag = .TRUE. ! Always use min OA schedule in calculations.

              ! INTERFACE BLOCK SPECIFICATIONS
              ! na

              ! DERIVED TYPE DEFINITIONS
              ! na

              ! FUNCTION LOCAL VARIABLE DECLARATIONS:
        LOGICAL   :: UseOccSchFlag     ! TRUE = use actual occupancy, FALSE = use total zone people
        REAL(r64) :: OAVolumeFlowRate  ! outside air flow rate (m3/s)

        IF (PurchAir(PurchAirNum)%OutdoorAir) THEN

          IF(PurchAir(PurchAirNum)%DCVType == OccupancySchedule)THEN
            UseOccSchFlag = .TRUE.
          ELSE
            UseOccSchFlag = .FALSE.
          END IF
          OAVolumeFlowRate = CalcDesignSpecificationOutdoorAir(PurchAir(PurchAirNum)%OARequirementsPtr, &
                                                                ActualZoneNum, UseOccSchFlag, UseMinOASchFlag)
          OAMassFlowRate = OAVolumeFlowRate * StdRhoAir

          ! If DCV with CO2Setpoint then check required OA flow to meet CO2 setpoint
          IF (PurchAir(PurchAirNum)%DCVType == CO2Setpoint) THEN
            OAMassFlowRate = Max(OAMassFlowRate, ZoneSysContDemand(ActualZoneNum)%OutputRequiredToCO2SP)
          END IF

          IF (OAMassFlowRate <= VerySmallMassFlow) OAMassFlowRate = 0.0d0

        ELSE !No outdoor air
          OAMassFlowRate = 0.0d0
        END IF
        PurchAir(PurchAirNum)%MinOAMassFlowRate = OAMassFlowRate

        RETURN

    END SUBROUTINE CalcPurchAirMinOAMassFlow


    SUBROUTINE CalcPurchAirMixedAir(PurchAirNum, OAMassFlowRate, SupplyMassFlowRate, &
                                         MixedAirTemp, MixedAirHumRat, MixedAirEnthalpy, OperatingMode)

              ! SUBROUTINE INFORMATION:
              !       AUTHOR         M. Witte (GARD)
              !       DATE WRITTEN   Sep 2011
              !       MODIFIED       na
              !       RE-ENGINEERED  na

              ! PURPOSE OF THIS SUBROUTINE:
              ! Calculates the mixed air conditions, accounting for heat recovery.

              ! METHODOLOGY EMPLOYED:
              ! na

              ! REFERENCES:

              ! USE STATEMENTS:
        USE DataLoopNode, ONLY: Node

        IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

              ! SUBROUTINE ARGUMENT DEFINITIONS:
        INTEGER, INTENT(IN)      :: PurchAirNum        ! index to ideal loads unit
        INTEGER, INTENT(IN)      :: OperatingMode      ! current operating mode, Off, Heating, Cooling, or Deadband
        REAL(r64), INTENT(IN)    :: OAMassFlowRate     ! outside air mass flow rate [kg/s]
        REAL(r64), INTENT(IN)    :: SupplyMassFlowRate ! supply air mass flow rate [kg/s]
        REAL(r64), INTENT(OUT)   :: MixedAirTemp       ! Mixed air dry bulb temperature [C]
        REAL(r64), INTENT(OUT)   :: MixedAirHumRat     ! Mixed air humidity ratio [kg H2O/kg Air]
        REAL(r64), INTENT(OUT)   :: MixedAirEnthalpy   ! Mixed air enthalpy [J/kg]

              ! SUBROUTINE PARAMETER DEFINITIONS:
              ! na

              ! INTERFACE BLOCK SPECIFICATIONS
              ! na

              ! DERIVED TYPE DEFINITIONS
              ! na

              ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
         INTEGER   :: RecircNodeNum     ! Zone return air node
         INTEGER   :: OANodeNum         ! Outdoor air inlet node
         REAL(r64) :: RecircTemp        ! Recirculated air from zone dry bulb temperature [C]
         REAL(r64) :: RecircHumRat      ! Recirculated air from zone humidity ratio [kg H2O/kg Air]
         REAL(r64) :: RecircEnthalpy    ! Recirculated air from zone enthalpy [J/kg]
         REAL(r64) :: RecircMassFlowRate ! Recirculated air mass flow rate [kg/s]
         REAL(r64) :: OAInletTemp       ! Outdoor air inlet dry bulb temperature [C]
         REAL(r64) :: OAInletHumRat     ! Outdoor air inlet humidity ratio [kg H2O/kg Air]
         REAL(r64) :: OAInletEnthalpy   ! Outdoor air inlet enthalpy [J/kg]
         REAL(r64) :: OAAfterHtRecTemp     ! Outdoor air after heat recovery to mixing box dry bulb temperature [C]
         REAL(r64) :: OAAfterHtRecHumRat   ! Outdoor air after heat recovery to mixing box humidity ratio [kg H2O/kg Air]
         REAL(r64) :: OAAfterHtRecEnthalpy ! Outdoor air after heat recovery to mixing box enthalpy [J/kg]
         LOGICAL   :: HeatRecOn
         REAL(r64) :: CpAir             ! Specific heat [J/kg-C] reused in multiple places

             ! Initializations
         OANodeNum     = PurchAir(PurchAirNum)%OutdoorAirNodeNum
         RecircNodeNum = PurchAir(PurchAirNum)%ZoneRecircAirNodeNum

         RecircMassFlowRate = 0.0d0
         RecircTemp      = Node(RecircNodeNum)%Temp
         RecircHumRat    = Node(RecircNodeNum)%HumRat
         RecircEnthalpy  = Node(RecircNodeNum)%Enthalpy
         IF (PurchAir(PurchAirNum)%OutdoorAir) THEN
           OAInletTemp     = Node(OANodeNum)%Temp
           OAInletHumRat   = Node(OANodeNum)%HumRat
           OAInletEnthalpy = Node(OANodeNum)%Enthalpy
           OAAfterHtRecTemp     = OAInletTemp
           OAAfterHtRecHumRat   = OAInletHumRat
           OAAfterHtRecEnthalpy = OAInletEnthalpy
         ELSE
           OAInletTemp     = 0.0d0
           OAInletHumRat   = 0.0d0
           OAInletEnthalpy = 0.0d0
           OAAfterHtRecTemp     = OAInletTemp
           OAAfterHtRecHumRat   = OAInletHumRat
           OAAfterHtRecEnthalpy = OAInletEnthalpy
         ENDIF
         HeatRecOn = .FALSE.

         IF (PurchAir(PurchAirNum)%OutdoorAir .AND. (OAMassFlowRate > 0.0d0)) THEN
             ! Determine if heat recovery is beneficial
             IF ((PurchAir(PurchAirNum)%HtRecType == Sensible) ) THEN
               IF ((OperatingMode == Heat) .AND. (RecircTemp > OAInletTemp)) HeatRecOn = .TRUE.
               IF ((OperatingMode == Cool) .AND. (RecircTemp < OAInletTemp)) HeatRecOn = .TRUE.
             END IF
             IF ((PurchAir(PurchAirNum)%HtRecType == Enthalpy)) THEN
               IF ((OperatingMode == Heat) .AND. (RecircEnthalpy > OAInletEnthalpy)) HeatRecOn = .TRUE.
               IF ((OperatingMode == Cool) .AND. (RecircEnthalpy < OAInletEnthalpy)) HeatRecOn = .TRUE.
             END IF
             ! Calculate heat recovery if active
             IF (HeatRecOn) THEN
               PurchAir(PurchAirNum)%TimeHtRecActive = TimeStepSys
               OAAfterHtRecTemp = OAInletTemp + PurchAir(PurchAirNum)%HtRecSenEff*(RecircTemp - OAInletTemp)
               IF (PurchAir(PurchAirNum)%HtRecType == Enthalpy) &
                 OAAfterHtRecHumRat = OAInletHumRat + PurchAir(PurchAirNum)%HtRecLatEff*(RecircHumRat - OAInletHumRat)
               OAAfterHtRecEnthalpy = PsyHFnTdbW(OAAfterHtRecTemp,OAAfterHtRecHumRat, 'CalcPurchAirMixedAir')
               !   Check for saturation in supply outlet and reset temp, then humidity ratio at constant enthalpy
               IF (PsyTsatFnHPb(OAAfterHtRecEnthalpy,OutBaroPress, 'CalcPurchAirMixedAir') > OAAfterHtRecTemp) THEN
                 OAAfterHtRecTemp   = PsyTsatFnHPb(OAAfterHtRecEnthalpy,OutBaroPress, 'CalcPurchAirMixedAir')
                 OAAfterHtRecHumRat = PsyWFnTdbH(OAAfterHtRecTemp,OAAfterHtRecEnthalpy, 'CalcPurchAirMixedAir')
               END IF
             END IF

             IF (SupplyMassFlowRate .GT. OAMassFlowRate) THEN
               RecircMassFlowRate = SupplyMassFlowRate - OAMassFlowRate
               MixedAirEnthalpy = (RecircMassFlowRate*Node(RecircNodeNum)%Enthalpy + OAMassFlowRate*OAAfterHtRecEnthalpy) / &
                                    SupplyMassFlowRate
               MixedAirHumRat   = (RecircMassFlowRate*Node(RecircNodeNum)%HumRat + OAMassFlowRate*OAAfterHtRecHumRat) / &
                                    SupplyMassFlowRate
               ! Mixed air temperature is calculated from the mixed air enthalpy and humidity ratio.
               MixedAirTemp = PsyTdbFnHW(MixedAirEnthalpy,MixedAirHumRat, 'CalcPurchAirMixedAir')
             ELSE
               RecircMassFlowRate   = 0.0d0
               MixedAirEnthalpy = OAAfterHtRecEnthalpy
               MixedAirHumRat   = OAAfterHtRecHumRat
               MixedAirTemp     = OAAfterHtRecTemp
             END IF

               ! Calculate OA and heat recovery sensible and latent rates
             CpAir = PsyCpAirFnWTdb(OAInletHumRat,OAInletTemp)
             PurchAir(PurchAirNum)%HtRecSenOutput = OAMassFlowRate * CPAir * (OAAfterHtRecTemp - OAInletTemp)
             PurchAir(PurchAirNum)%HtRecLatOutput = OAMassFlowRate * (OAAfterHtRecEnthalpy - OAInletEnthalpy) &
                                                       - PurchAir(PurchAirNum)%HtRecSenOutput

         ELSE ! No outdoor air
           RecircMassFlowRate = SupplyMassFlowRate
           MixedAirTemp     = RecircTemp
           MixedAirHumRat   = RecircHumRat
           MixedAirEnthalpy = RecircEnthalpy
           PurchAir(PurchAirNum)%HtRecSenOutput = 0.0d0
           PurchAir(PurchAirNum)%HtRecLatOutput = 0.0d0
         END IF
        ! If exhaust node is specified, then set massflow on exhaust node, otherwise return node sets its own massflow
        IF (PurchAir(PurchAirNum)%ZoneExhaustAirNodeNum .GT. 0) THEN
          Node(RecircNodeNum)%MassFlowRate = RecircMassFlowRate
        END IF

        RETURN

    END SUBROUTINE CalcPurchAirMixedAir


    SUBROUTINE UpdatePurchasedAir(PurchAirNum)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         M. J. Witte
          !       DATE WRITTEN   Sep 2011
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Update node data for Ideal Loads (purchased air) system

          ! METHODOLOGY EMPLOYED:

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
          ! na

      IMPLICIT NONE

          ! SUBROUTINE ARGUMENT DEFINITIONS:
         INTEGER, INTENT(IN) :: PurchAirNum

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
          ! na

      RETURN

    END SUBROUTINE UpdatePurchasedAir

    SUBROUTINE ReportPurchasedAir(PurchAirNum)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Russ Taylor
          !       DATE WRITTEN   Nov 1997
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Calculate values of report variables, if necessary.

          ! METHODOLOGY EMPLOYED:

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
      USE DataHVACGlobals, ONLY: TimeStepSys

      IMPLICIT NONE

          ! SUBROUTINE ARGUMENT DEFINITIONS:
      INTEGER, INTENT(IN) :: PurchAirNum

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
      REAL(r64) :: ReportingConstant

          ! Sort out heating and cooling rates
      PurchAir(PurchAirNum)%SenHeatRate = MAX(PurchAir(PurchAirNum)%SenCoilLoad,0.0d0)
      PurchAir(PurchAirNum)%SenCoolRate = ABS(MIN(PurchAir(PurchAirNum)%SenCoilLoad,0.0d0))
      PurchAir(PurchAirNum)%LatHeatRate = MAX(PurchAir(PurchAirNum)%LatCoilLoad,0.0d0)
      PurchAir(PurchAirNum)%LatCoolRate = ABS(MIN(PurchAir(PurchAirNum)%LatCoilLoad,0.0d0))
      PurchAir(PurchAirNum)%TotHeatRate = PurchAir(PurchAirNum)%SenHeatRate + PurchAir(PurchAirNum)%LatHeatRate
      PurchAir(PurchAirNum)%TotCoolRate = PurchAir(PurchAirNum)%SenCoolRate + PurchAir(PurchAirNum)%LatCoolRate

      PurchAir(PurchAirNum)%ZoneSenHeatRate = MAX(PurchAir(PurchAirNum)%SenOutputToZone,0.0d0)
      PurchAir(PurchAirNum)%ZoneSenCoolRate = ABS(MIN(PurchAir(PurchAirNum)%SenOutputToZone,0.0d0))
      PurchAir(PurchAirNum)%ZoneLatHeatRate = MAX(PurchAir(PurchAirNum)%LatOutputToZone,0.0d0)
      PurchAir(PurchAirNum)%ZoneLatCoolRate = ABS(MIN(PurchAir(PurchAirNum)%LatOutputToZone,0.0d0))
      PurchAir(PurchAirNum)%ZoneTotHeatRate = PurchAir(PurchAirNum)%ZoneSenHeatRate + PurchAir(PurchAirNum)%ZoneLatHeatRate
      PurchAir(PurchAirNum)%ZoneTotCoolRate = PurchAir(PurchAirNum)%ZoneSenCoolRate + PurchAir(PurchAirNum)%ZoneLatCoolRate

         ! Sort out outdoor air "loads"
         ! OASenOutput = Outdoor air sensible output relative to zone conditions [W], <0 means OA is cooler than zone air
         ! OALatOutput  = Outdoor air latent output relative to zone conditions [W], <0 means OA is drier than zone air
      IF (PurchAir(PurchAirNum)%SenCoilLoad > 0.0d0) THEN ! Heating is active
        PurchAir(PurchAirNum)%OASenHeatRate = ABS(MIN(PurchAir(PurchAirNum)%OASenOutput,0.0d0))
      ELSE
        PurchAir(PurchAirNum)%OASenHeatRate = 0.0d0
      END IF
      IF (PurchAir(PurchAirNum)%SenCoilLoad < 0.0d0) THEN ! Cooling is active
        PurchAir(PurchAirNum)%OASenCoolRate = MAX(PurchAir(PurchAirNum)%OASenOutput,0.0d0)
      ELSE
        PurchAir(PurchAirNum)%OASenCoolRate = 0.0d0
      END IF
      IF (PurchAir(PurchAirNum)%LatCoilLoad > 0.0d0) THEN ! Humidification is active
        PurchAir(PurchAirNum)%OALatHeatRate =  ABS(MIN(PurchAir(PurchAirNum)%OALatOutput,0.0d0))
      ELSE
        PurchAir(PurchAirNum)%OALatHeatRate = 0.0d0
      END IF
      IF (PurchAir(PurchAirNum)%LatCoilLoad < 0.0d0) THEN ! Dehumidification is active
        PurchAir(PurchAirNum)%OALatCoolRate = MAX(PurchAir(PurchAirNum)%OALatOutput,0.0d0)
      ELSE
        PurchAir(PurchAirNum)%OALatCoolRate = 0.0d0
      ENDIF

      PurchAir(PurchAirNum)%OATotHeatRate = PurchAir(PurchAirNum)%OASenHeatRate + PurchAir(PurchAirNum)%OALatHeatRate
      PurchAir(PurchAirNum)%OATotCoolRate = PurchAir(PurchAirNum)%OASenCoolRate + PurchAir(PurchAirNum)%OALatCoolRate

      PurchAir(PurchAirNum)%HtRecSenHeatRate = MAX(PurchAir(PurchAirNum)%HtRecSenOutput,0.0d0)
      PurchAir(PurchAirNum)%HtRecSenCoolRate = ABS(MIN(PurchAir(PurchAirNum)%HtRecSenOutput,0.0d0))
      PurchAir(PurchAirNum)%HtRecLatHeatRate = MAX(PurchAir(PurchAirNum)%HtRecLatOutput,0.0d0)
      PurchAir(PurchAirNum)%HtRecLatCoolRate = ABS(MIN(PurchAir(PurchAirNum)%HtRecLatOutput,0.0d0))
      PurchAir(PurchAirNum)%HtRecTotHeatRate = PurchAir(PurchAirNum)%HtRecSenHeatRate+PurchAir(PurchAirNum)%HtRecLatHeatRate
      PurchAir(PurchAirNum)%HtRecTotCoolRate = PurchAir(PurchAirNum)%HtRecSenCoolRate+PurchAir(PurchAirNum)%HtRecLatCoolRate

      ReportingConstant = TimeStepSys*SecInHour

      PurchAir(PurchAirNum)%SenHeatEnergy = PurchAir(PurchAirNum)%SenHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%SenCoolEnergy = PurchAir(PurchAirNum)%SenCoolRate * ReportingConstant
      PurchAir(PurchAirNum)%LatHeatEnergy = PurchAir(PurchAirNum)%LatHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%LatCoolEnergy = PurchAir(PurchAirNum)%LatCoolRate * ReportingConstant
      PurchAir(PurchAirNum)%TotHeatEnergy = PurchAir(PurchAirNum)%TotHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%TotCoolEnergy = PurchAir(PurchAirNum)%TotCoolRate * ReportingConstant

      PurchAir(PurchAirNum)%ZoneSenHeatEnergy = PurchAir(PurchAirNum)%ZoneSenHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%ZoneSenCoolEnergy = PurchAir(PurchAirNum)%ZoneSenCoolRate * ReportingConstant
      PurchAir(PurchAirNum)%ZoneLatHeatEnergy = PurchAir(PurchAirNum)%ZoneLatHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%ZoneLatCoolEnergy = PurchAir(PurchAirNum)%ZoneLatCoolRate * ReportingConstant
      PurchAir(PurchAirNum)%ZoneTotHeatEnergy = PurchAir(PurchAirNum)%ZoneTotHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%ZoneTotCoolEnergy = PurchAir(PurchAirNum)%ZoneTotCoolRate * ReportingConstant

      PurchAir(PurchAirNum)%OASenHeatEnergy = PurchAir(PurchAirNum)%OASenHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%OASenCoolEnergy = PurchAir(PurchAirNum)%OASenCoolRate * ReportingConstant
      PurchAir(PurchAirNum)%OALatHeatEnergy = PurchAir(PurchAirNum)%OALatHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%OALatCoolEnergy = PurchAir(PurchAirNum)%OALatCoolRate * ReportingConstant
      PurchAir(PurchAirNum)%OATotHeatEnergy = PurchAir(PurchAirNum)%OATotHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%OATotCoolEnergy = PurchAir(PurchAirNum)%OATotCoolRate * ReportingConstant

      PurchAir(PurchAirNum)%HtRecSenHeatEnergy = PurchAir(PurchAirNum)%HtRecSenHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%HtRecSenCoolEnergy = PurchAir(PurchAirNum)%HtRecSenCoolRate * ReportingConstant
      PurchAir(PurchAirNum)%HtRecLatHeatEnergy = PurchAir(PurchAirNum)%HtRecLatHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%HtRecLatCoolEnergy = PurchAir(PurchAirNum)%HtRecLatCoolRate * ReportingConstant
      PurchAir(PurchAirNum)%HtRecTotHeatEnergy = PurchAir(PurchAirNum)%HtRecTotHeatRate * ReportingConstant
      PurchAir(PurchAirNum)%HtRecTotCoolEnergy = PurchAir(PurchAirNum)%HtRecTotCoolRate * ReportingConstant

      RETURN
    END SUBROUTINE ReportPurchasedAir

FUNCTION GetPurchasedAirOutAirMassFlow(PurchAirNum) RESULT(OutAirMassFlow)

          ! FUNCTION INFORMATION:
          !       AUTHOR         B Griffith
          !       DATE WRITTEN   Dec  2006
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS FUNCTION:
          ! lookup function for OA inlet mass flow for ventilation rate reporting

          ! METHODOLOGY EMPLOYED:
          ! most analagous functions look up an outside air node but this function
          ! gets the actual mass flow of outdoor air, following the features of the model

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
          ! na

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! FUNCTION ARGUMENT DEFINITIONS:
  INTEGER, INTENT (IN)  :: PurchAirNum          !
  REAL(r64)             :: OutAirMassFlow

          ! FUNCTION PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! FUNCTION LOCAL VARIABLE DECLARATIONS:
          ! na
  IF (GetPurchAirInputFlag ) THEN
    CALL GetPurchasedAir
    GetPurchAirInputFlag = .FALSE.
  END IF

  OutAirMassFlow = PurchAir(PurchAirNum)%OutdoorAirMassFlowRate

  RETURN

END FUNCTION GetPurchasedAirOutAirMassFlow

INTEGER FUNCTION GetPurchasedAirZoneInletAirNode(PurchAirNum)

          ! FUNCTION INFORMATION:
          !       AUTHOR         B Griffith
          !       DATE WRITTEN   Dec  2006
          !       MODIFIED       Adapted for purchased air by M.J. Witte, Oct 2013
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS FUNCTION:
          ! lookup function for zone inlet node for ventilation rate reporting

          ! METHODOLOGY EMPLOYED:
          ! <description>

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
          ! na

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! FUNCTION ARGUMENT DEFINITIONS:
  INTEGER, INTENT (IN)  :: PurchAirNum          !

          ! FUNCTION PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! FUNCTION LOCAL VARIABLE DECLARATIONS:
          ! na

  IF (GetPurchAirInputFlag ) THEN
    CALL GetPurchasedAir
    GetPurchAirInputFlag = .FALSE.
  END IF

  GetPurchasedAirZoneInletAirNode = 0
  IF (PurchAirNum > 0 .and. PurchAirNum <= NumPurchAir) THEN
    GetPurchasedAirZoneInletAirNode =  PurchAir(PurchAirNum)%ZoneSupplyAirNodeNum
  ENDIF

  RETURN

END FUNCTION GetPurchasedAirZoneInletAirNode


INTEGER FUNCTION GetPurchasedAirReturnAirNode(PurchAirNum)

          ! FUNCTION INFORMATION:
          !       AUTHOR         B Griffith
          !       DATE WRITTEN   Dec  2006
          !       MODIFIED       Adapted for purchased air by M.J. Witte, Oct 2013
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS FUNCTION:
          ! lookup function for recirculation air node for ventilation rate reporting

          ! METHODOLOGY EMPLOYED:
          ! <description>

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
          ! na

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! FUNCTION ARGUMENT DEFINITIONS:
  INTEGER, INTENT (IN)  :: PurchAirNum          !

          ! FUNCTION PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! FUNCTION LOCAL VARIABLE DECLARATIONS:
          ! na

  IF (GetPurchAirInputFlag ) THEN
    CALL GetPurchasedAir
    GetPurchAirInputFlag = .FALSE.
  END IF

  GetPurchasedAirReturnAirNode = 0
  IF (PurchAirNum > 0 .and. PurchAirNum <= NumPurchAir) THEN
    GetPurchasedAirReturnAirNode =  PurchAir(PurchAirNum)%ZoneRecircAirNodeNum
  ENDIF

  RETURN

END FUNCTION GetPurchasedAirReturnAirNode

FUNCTION GetPurchasedAirMixedAirTemp(PurchAirNum) RESULT(MixedAirTemp)

          ! FUNCTION INFORMATION:
          !       AUTHOR         B Griffith
          !       DATE WRITTEN   Dec  2006
          !       MODIFIED       Adapted for purchased air by M.J. Witte, Oct 2013
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS FUNCTION:
          ! lookup function for mixed air Temp for ventilation rate reporting

          ! METHODOLOGY EMPLOYED:
          ! most analagous functions look up an outside air node but this function
          ! gets the actual mass flow of outdoor air, following the features of the model

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
          ! na

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! FUNCTION ARGUMENT DEFINITIONS:
  INTEGER, INTENT (IN)  :: PurchAirNum          !
  REAL(r64)             :: MixedAirTemp

          ! FUNCTION PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! FUNCTION LOCAL VARIABLE DECLARATIONS:
          ! na
  IF (GetPurchAirInputFlag ) THEN
    CALL GetPurchasedAir
    GetPurchAirInputFlag = .FALSE.
  END IF

  MixedAirTemp = PurchAir(PurchAirNum)%FinalMixedAirTemp

  RETURN

END FUNCTION GetPurchasedAirMixedAirTemp

FUNCTION GetPurchasedAirMixedAirHumRat(PurchAirNum) RESULT(MixedAirHumRat)

          ! FUNCTION INFORMATION:
          !       AUTHOR         B Griffith
          !       DATE WRITTEN   Dec  2006
          !       MODIFIED       Adapted for purchased air by M.J. Witte, Oct 2013
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS FUNCTION:
          ! lookup function for mixed air HumRat for ventilation rate reporting

          ! METHODOLOGY EMPLOYED:
          ! most analagous functions look up an outside air node but this function
          ! gets the actual mass flow of outdoor air, following the features of the model

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
          ! na

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! FUNCTION ARGUMENT DEFINITIONS:
  INTEGER, INTENT (IN)  :: PurchAirNum          !
  REAL(r64)             :: MixedAirHumRat

          ! FUNCTION PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! FUNCTION LOCAL VARIABLE DECLARATIONS:
          ! na
  IF (GetPurchAirInputFlag ) THEN
    CALL GetPurchasedAir
    GetPurchAirInputFlag = .FALSE.
  END IF

  MixedAirHumRat = PurchAir(PurchAirNum)%FinalMixedAirHumRat

  RETURN

END FUNCTION GetPurchasedAirMixedAirHumRat

!     NOTICE
!
!     Copyright © 1996-2013 The Board of Trustees of the University of Illinois
!     and The Regents of the University of California through Ernest Orlando Lawrence
!     Berkeley National Laboratory.  All rights reserved.
!
!     Portions of the EnergyPlus software package have been developed and copyrighted
!     by other individuals, companies and institutions.  These portions have been
!     incorporated into the EnergyPlus software package under license.   For a complete
!     list of contributors, see "Notice" located in EnergyPlus.f90.
!
!     NOTICE: The U.S. Government is granted for itself and others acting on its
!     behalf a paid-up, nonexclusive, irrevocable, worldwide license in this data to
!     reproduce, prepare derivative works, and perform publicly and display publicly.
!     Beginning five (5) years after permission to assert copyright is granted,
!     subject to two possible five year renewals, the U.S. Government is granted for
!     itself and others acting on its behalf a paid-up, non-exclusive, irrevocable
!     worldwide license in this data to reproduce, prepare derivative works,
!     distribute copies to the public, perform publicly and display publicly, and to
!     permit others to do so.
!
!     TRADEMARKS: EnergyPlus is a trademark of the US Department of Energy.
!

END MODULE PurchasedAirManager

AirflowNetworkBalanceManager.f90 AirflowNetworkSolver.f90 BaseboardRadiator.f90 BaseboardRadiatorElectric.f90 BaseboardRadiatorSteam.f90 BaseboardRadiatorWater.f90 BranchInputManager.f90 BranchNodeConnections.f90 ConductionTransferFunctionCalc.f90 CoolTower.f90 CostEstimateManager.f90 CurveManager.f90 CVFOnlyRoutines.f90 DataAirflowNetwork.f90 DataAirLoop.f90 DataAirSystems.f90 DataBranchAirLoopPlant.f90 DataBranchNodeConnections.f90 DataBSDFWindow.f90 DataComplexFenestration.f90 DataContaminantBalance.f90 DataConvergParams.f90 DataConversions.f90 DataCostEstimate.f90 DataDaylighting.f90 DataDaylightingDevices.f90 Datadefineequip.f90 DataDElight.f90 DataEnvironment.f90 DataEquivalentLayerWindow.f90 DataErrorTracking.f90 DataGenerators.f90 DataGlobalConstants.f90 DataGlobals.f90 DataHeatBalance.f90 DataHeatBalFanSys.f90 DataHeatBalSurface.f90 DataHVACControllers.f90 DataHVACGlobals.f90 DataInterfaces.f90 DataIPShortCuts.f90 DataLoopNode.f90 DataMoistureBalance.f90 DataMoistureBalanceEMPD.f90 DataOutputs.f90 DataPhotovoltaics.f90 DataPlant.f90 DataPlantPipingSystems.f90 DataPrecisionGlobals.f90 DataReportingFlags.f90 DataRoomAir.f90 DataRootFinder.f90 DataRuntimeLanguage.f90 DataShadowingCombinations.f90 DataSizing.f90 DataStringGlobals.f90 DataSurfaceColors.f90 DataSurfaceLists.f90 DataSurfaces.f90 DataSystemVariables.f90 DataTimings.f90 DataUCSDSharedData.f90 DataVectorTypes.f90 DataViewFactorInformation.f90 DataWater.f90 DataZoneControls.f90 DataZoneEnergyDemands.f90 DataZoneEquipment.f90 DaylightingDevices.f90 DaylightingManager.f90 DElightManagerF.f90 DElightManagerF_NO.f90 DemandManager.f90 DesiccantDehumidifiers.f90 DirectAir.f90 DisplayRoutines.f90 DXCoil.f90 EarthTube.f90 EconomicLifeCycleCost.f90 EconomicTariff.f90 EcoRoof.f90 ElectricPowerGenerators.f90 ElectricPowerManager.f90 EMSManager.f90 EnergyPlus.f90 ExteriorEnergyUseManager.f90 ExternalInterface_NO.f90 FanCoilUnits.f90 FaultsManager.f90 FluidProperties.f90 General.f90 GeneralRoutines.f90 GlobalNames.f90 HeatBalanceAirManager.f90 HeatBalanceConvectionCoeffs.f90 HeatBalanceHAMTManager.f90 HeatBalanceInternalHeatGains.f90 HeatBalanceIntRadExchange.f90 HeatBalanceManager.f90 HeatBalanceMovableInsulation.f90 HeatBalanceSurfaceManager.f90 HeatBalFiniteDifferenceManager.f90 HeatRecovery.f90 Humidifiers.f90 HVACControllers.f90 HVACCooledBeam.f90 HVACDualDuctSystem.f90 HVACDuct.f90 HVACDXSystem.f90 HVACEvapComponent.f90 HVACFanComponent.f90 HVACFurnace.f90 HVACHeatingCoils.f90 HVACHXAssistedCoolingCoil.f90 HVACInterfaceManager.f90 HVACManager.f90 HVACMixerComponent.f90 HVACMultiSpeedHeatPump.f90 HVACSingleDuctInduc.f90 HVACSingleDuctSystem.f90 HVACSplitterComponent.f90 HVACStandAloneERV.f90 HVACSteamCoilComponent.f90 HVACTranspiredCollector.f90 HVACUnitaryBypassVAV.f90 HVACUnitarySystem.f90 HVACVariableRefrigerantFlow.f90 HVACWaterCoilComponent.f90 HVACWatertoAir.f90 HVACWatertoAirMultiSpeedHP.f90 InputProcessor.f90 MatrixDataManager.f90 MixedAir.f90 MoistureBalanceEMPDManager.f90 NodeInputManager.f90 NonZoneEquipmentManager.f90 OutAirNodeManager.f90 OutdoorAirUnit.f90 OutputProcessor.f90 OutputReportPredefined.f90 OutputReports.f90 OutputReportTabular.f90 PackagedTerminalHeatPump.f90 PackagedThermalStorageCoil.f90 Photovoltaics.f90 PhotovoltaicThermalCollectors.f90 PlantAbsorptionChillers.f90 PlantBoilers.f90 PlantBoilersSteam.f90 PlantCentralGSHP.f90 PlantChillers.f90 PlantCondLoopOperation.f90 PlantCondLoopTowers.f90 PlantEIRChillers.f90 PlantEvapFluidCoolers.f90 PlantExhaustAbsorptionChiller.f90 PlantFluidCoolers.f90 PlantGasAbsorptionChiller.f90 PlantGroundHeatExchangers.f90 PlantHeatExchanger.f90 PlantIceThermalStorage.f90 PlantLoadProfile.f90 PlantLoopEquipment.f90 PlantLoopSolver.f90 PlantManager.f90 PlantOutsideEnergySources.f90 PlantPipeHeatTransfer.f90 PlantPipes.f90 PlantPipingSystemManager.f90 PlantPondGroundHeatExchanger.f90 PlantPressureSystem.f90 PlantPumps.f90 PlantSolarCollectors.f90 PlantSurfaceGroundHeatExchanger.f90 PlantUtilities.f90 PlantValves.f90 PlantWaterSources.f90 PlantWaterThermalTank.f90 PlantWatertoWaterGSHP.f90 PlantWaterUse.f90 PollutionAnalysisModule.f90 PoweredInductionUnits.f90 PsychRoutines.f90 Purchasedairmanager.f90 RadiantSystemHighTemp.f90 RadiantSystemLowTemp.f90 RefrigeratedCase.f90 ReportSizingManager.f90 ReturnAirPath.f90 RoomAirManager.f90 RoomAirModelCrossVent.f90 RoomAirModelDisplacementVent.f90 RoomAirModelMundt.f90 RoomAirModelUFAD.f90 RoomAirModelUserTempPattern.f90 RootFinder.f90 RuntimeLanguageProcessor.f90 ScheduleManager.f90 SetPointManager.f90 SimAirServingZones.f90 SimulationManager.f90 SizingManager.f90 SolarReflectionManager.f90 SolarShading.f90 SortAndStringUtilities.f90 sqlite3.c SQLiteCRoutines.c SQLiteFortranRoutines.f90 SQLiteFortranRoutines_NO.f90 StandardRatings.f90 SurfaceGeometry.f90 SystemAvailabilityManager.f90 SystemReports.f90 TarcogComplexFenestration.f90 ThermalChimney.f90 ThermalComfort.f90 UnitHeater.f90 UnitVentilator.f90 UserDefinedComponents.f90 UtilityRoutines.f90 VectorUtilities.f90 VentilatedSlab.f90 WaterManager.f90 WeatherManager.f90 WindowAC.f90 WindowComplexManager.f90 WindowEquivalentLayer.f90 WindowManager.f90 WindTurbine.f90 Zoneairloopequipmentmanager.f90 ZoneContaminantPredictorCorrector.f90 ZoneDehumidifier.f90 Zoneequipmentmanager.f90 ZonePlenumComponent.f90 ZoneTempPredictorCorrector.f90