SUBROUTINE InitFurnace(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, ZoneLoad, MoistureLoad, FirstHVACIteration)
! SUBROUTINE INFORMATION:
! AUTHOR Richard J. Liesen
! DATE WRITTEN Feb 2001
! MODIFIED Oct 2001, Richard Raustad
! Sep 2008, R. Raustad - revised logic to determine load to be met
! Bereket Nigusse, June 2010 - added a procedure to calculate supply air flow fraction
! through controlled zone
! Bo Shen, March 2012 - for VS WSHP
! Bo Shen, ORNL, July 2012 - added variable-speed air source heat pump cooling and heating coils, using curve-fits
! RE-ENGINEERED na
! PURPOSE OF THIS SUBROUTINE:
! This subroutine is for initializations of the Furnace Components.
! METHODOLOGY EMPLOYED:
! Uses the status flags to trigger initializations.
! The HeatCool furnace/unitarysystem and air-to-air heat pump may have alternate air flow rates
! in cooling, heating, and when no cooling or heating is needed. Set up the coil (comp) ON and OFF
! air flow rates during InitFurnace. Use these flow rates during the Calc routines to set the
! average mass flow rates based on PLR.
! REFERENCES:
! USE STATEMENTS:
USE Fans, ONLY: GetFanDesignVolumeFlowRate, GetFanSpeedRatioCurveIndex
USE General, ONLY: RoundSigDigits, TrimSigDigits
USE ReportSizingManager, ONLY: ReportSizingOutput
USE DataSizing, ONLY: AutoSize
USE DataAirLoop, ONLY: LoopHeatingCoilMaxRTF, AirLoopControlInfo
USE DataZoneEnergyDemands, ONLY: ZoneSysEnergyDemand, ZoneSysMoistureDemand, CurDeadbandOrSetback
USE DataHeatBalFanSys, ONLY: TempControlType
USE DataHeatBalance, ONLY: Zone
USE DataAirflowNetwork, ONLY: SimulateAirflowNetwork, AirflowNetworkControlMultizone
USE DataAirLoop , ONLY: AirToZoneNodeInfo
USE DataPlant, ONLY: TypeOf_CoilSteamAirHeating, ScanPlantLoopsForObject, TypeOf_CoilWaterSimpleHeating, &
PlantLoop
USE SteamCoils, ONLY: SimulateSteamCoilComponents, GetCoilMaxSteamFlowRate=>GetCoilMaxSteamFlowRate, &
GetSteamCoilCapacity=>GetCoilCapacity
USE WaterCoils, ONLY: GetCoilMaxWaterFlowRate, SimulateWaterCoilComponents
USE FluidProperties, ONLY: GetDensityGlycol, GetSatDensityRefrig
USE PlantUtilities, ONLY: SetComponentFlowRate, InitComponentNodes
USE Fans, ONLY: GetFanVolFlow
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! SUBROUTINE ARGUMENT DEFINITIONS:
INTEGER, INTENT(IN) :: FurnaceNum ! index to Furnace
INTEGER, INTENT(IN) :: AirLoopNum ! index to air loop
REAL(r64), INTENT(INOUT) :: OnOffAirFlowRatio ! ratio of on to off air mass flow rate
INTEGER, INTENT(INOUT) :: OpMode ! fan operating mode
REAL(r64), INTENT(INOUT) :: ZoneLoad ! zone sensible load to be met (modified here as needed) (W)
REAL(r64), INTENT(INOUT) :: MoistureLoad ! zone moisture load (W)
LOGICAL, INTENT (IN) :: FirstHVACIteration ! TRUE if first HVAC iteration
! SUBROUTINE PARAMETER DEFINITIONS:
REAL(r64), PARAMETER :: Small5WLoad = 5.0D0
! INTERFACE BLOCK SPECIFICATIONS
! na
! DERIVED TYPE DEFINITIONS
! na
! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
LOGICAL, SAVE :: MyOneTimeFlag = .TRUE. ! one time allocation flag
LOGICAL, ALLOCATABLE,SAVE, DIMENSION(:) :: MyEnvrnFlag ! environment flag
LOGICAL, ALLOCATABLE,SAVE, DIMENSION(:) :: MySecondOneTimeFlag ! additional one time flag
LOGICAL, ALLOCATABLE,SAVE, DIMENSION(:) :: MyFanFlag ! used for sizing fan inputs one time
LOGICAL, ALLOCATABLE,SAVE, DIMENSION(:) :: MyCheckFlag ! Used to obtain the zone inlet node number in the controlled zone
LOGICAL, ALLOCATABLE,SAVE, DIMENSION(:) :: MyFlowFracFlag ! Used for calculatig flow fraction once
LOGICAL, ALLOCATABLE,SAVE, DIMENSION(:) :: MyPlantScanFlag ! used to initializa plant comp for water and steam heating coils
LOGICAL, ALLOCATABLE,SAVE, DIMENSION(:) :: MySuppCoilPlantScanFlag ! used to initialize plant comp for water and steam heating coils
LOGICAL :: ErrFlag ! error flag for mining functions
REAL(r64) :: FanVolFlowRate ! fan volumetric flow rate (m3/s)
REAL(r64) :: QZnReq ! furnace load based on control zone frac (W)
REAL(r64) :: PartLoadRatio ! furnace part-load ratio
REAL(r64) :: SensibleOutput ! no load sensible output (coils off) (W)
REAL(r64) :: LatentOutput ! no load latent output (coils off) (W)
REAL(r64) :: QToCoolSetPt ! sensible load to cooling setpoint (W)
REAL(r64) :: QToHeatSetPt ! sensible load to heating setpoint (W)
INTEGER :: ZoneInNode ! Zone inlet node number in the controlled zone
REAL(r64) :: MinHumRat ! Minimum humidity ratio for sensible capacity
! calculation (kg/kg)
REAL(r64) :: DeltaMassRate ! Difference of mass flow rate between
! inlet node and system outlet node
INTEGER :: i,j,k ! index to get the zone inlet node
REAL(r64) :: MassFlowRate ! mass flow rate to calculate loss
REAL(r64) :: MaxTemp ! Maximum temperature used in latent loss calculation
CHARACTER(len=MaxNameLength) :: FanType ! used in warning messages
CHARACTER(len=MaxNameLength) :: FanName ! used in warning messages
INTEGER :: ZoneInSysIndex = 0 ! number of zone inlet nodes counter in an airloop
INTEGER :: NumAirLoopZones = 0 ! number of zone inlet nodes in an air loop
INTEGER :: ZoneInletNodeNum = 0 ! zone inlet nodes node number
LOGICAL :: FlowFracFlagReady = .TRUE. ! one time flag for calculating flow fraction through controlled zone
REAL(r64) :: SumOfMassFlowRateMax = 0.0d0 ! the sum of mass flow rates at inlet to zones in an airloop
REAL(r64) :: CntrlZoneTerminalUnitMassFlowRateMax = 0.0d0 ! Maximum mass flow rate through controlled zone terminal unit
INTEGER :: EquipNum = 0 ! local do loop index for equipment listed for a zone
INTEGER :: InletNodeNum = 0 ! local do loop index for inlet nodes to a zone
LOGICAL :: ErrorsFound =.FALSE. ! flag returned from mining call
REAL(r64) :: mdot =0.0d0 ! local temporary for mass flow rate (kg/s)
REAL(r64) :: rho =0.0d0 ! local for fluid density
INTEGER :: SteamIndex =0 ! index of steam quality for steam heating coil
REAL(r64) :: SteamDensity =0.0d0 ! density of steam at 100C, used for steam heating coils
REAL(r64) :: CoilMaxVolFlowRate =0.0d0 ! coil fluid maximum volume flow rate
REAL(r64) :: QACTUAL =0.0d0 ! coil actual capacity
REAL(r64) :: SUPHEATERLOAD =0.0d0 ! SUPPLEMENTAL HEATER LOAD
INTEGER :: NumOfSpeedCooling ! Number of speeds for cooling
INTEGER :: NumOfSpeedHeating ! Number of speeds for heating
INTEGER :: InNode ! Inlet node number in MSHP loop
INTEGER :: OutNode ! Outlet node number in MSHP loop
REAL(r64) :: RhoAir ! Air density at InNode
LOGICAL, SAVE :: MyAirLoopPass = .TRUE. ! one time allocation flag
InNode = Furnace(FurnaceNum)%FurnaceInletNodeNum
OutNode = Furnace(FurnaceNum)%FurnaceOutletNodeNum
! FLOW:
IF (MyOneTimeFlag) THEN
! initialize the environment and sizing flags
ALLOCATE(MyEnvrnFlag(NumFurnaces))
ALLOCATE(MySizeFlag(NumFurnaces))
ALLOCATE(MySecondOneTimeFlag(NumFurnaces))
ALLOCATE(MyFanFlag(NumFurnaces))
ALLOCATE(MyCheckFlag(NumFurnaces))
ALLOCATE(MyFlowFracFlag(NumFurnaces))
ALLOCATE(MyPlantScanFlag(NumFurnaces))
ALLOCATE(MySuppCoilPlantScanFlag(NumFurnaces))
MyEnvrnFlag = .TRUE.
MySizeFlag = .TRUE.
MySecondOneTimeFlag=.TRUE.
MyFanFlag = .TRUE.
MyCheckFlag = .TRUE.
MyFlowFracFlag = .TRUE.
MyOneTimeFlag = .FALSE.
MyPlantScanFlag = .TRUE.
MySuppCoilPlantScanFlag = .TRUE.
END IF
IF (BeginEnvrnFlag .and. MyAirLoopPass) THEN
AirLoopPass = 0
MyAirLoopPass = .FALSE.
End If
IF (.not. BeginEnvrnFlag) THEN
MyAirLoopPass = .TRUE.
End If
AirLoopPass = AirLoopPass + 1
If (AirLoopPass > 2) AirLoopPass = 1
IF ( .NOT. SysSizingCalc .AND. MySizeFlag(FurnaceNum)) THEN
! for each furnace, do the sizing once.
CALL SizeFurnace(FurnaceNum,FirstHVACIteration)
Furnace(FurnaceNum)%ControlZoneMassFlowFrac = 1.0d0
MySizeFlag(FurnaceNum) = .FALSE.
! Pass the fan cycling schedule index up to the air loop. Set the air loop unitary system flag.
AirLoopControlInfo(AirLoopNum)%CycFanSchedPtr = Furnace(FurnaceNum)%FanSchedPtr
AirLoopControlInfo(AirLoopNum)%UnitarySys = .TRUE.
AirLoopControlInfo(AirLoopNum)%FanOpMode = Furnace(FurnaceNum)%OpMode
!Check that heat pump heating capacity is within 20% of cooling capacity
IF (Furnace(FurnaceNum)%FurnaceType_Num == UnitarySys_HeatPump_AirToAir) THEN
IF(ABS(Furnace(FurnaceNum)%DesignCoolingCapacity-&
Furnace(FurnaceNum)%DesignHeatingCapacity)/&
Furnace(FurnaceNum)%DesignCoolingCapacity .GT. 0.2d0) THEN
CALL ShowWarningError(TRIM(cFurnaceTypes(Furnace(FurnaceNum)%FurnaceType_Num))//' "'//TRIM(Furnace(FurnaceNum)%Name)//&
'" heating capacity is disproportionate (> 20% different) to total cooling capacity')
END IF
END IF
END IF
IF (.not. DoingSizing .and. MySecondOneTimeFlag(FurnaceNum)) THEN
! sizing all done. check fan air flow rates
ErrFlag=.FALSE.
FanVolFlowRate = &
GetFanDesignVolumeFlowRate(Blank,Blank,ErrFlag,Furnace(FurnaceNum)%FanIndex)
Furnace(FurnaceNum)%ActualFanVolFlowRate = FanVolFlowRate
IF (ErrFlag) THEN
CALL ShowContinueError('...occurs in '//TRIM(cFurnaceTypes(Furnace(FurnaceNum)%FurnaceType_Num))// &
' ='//TRIM(Furnace(FurnaceNum)%Name))
ENDIF
IF (FanVolFlowRate /= AutoSize) THEN
IF (Furnace(FurnaceNum)%DesignFanVolFlowRate > FanVolFlowRate) THEN
CALL ShowWarningError(TRIM(cFurnaceTypes(Furnace(FurnaceNum)%FurnaceType_Num))//'='//TRIM(Furnace(FurnaceNum)%Name)// &
' has a Design Fan Volume Flow Rate > Max Fan Volume Flow Rate, should be <=')
CALL ShowContinueError('... Entered value='//TRIM(RoundSigDigits(Furnace(FurnaceNum)%DesignFanVolFlowRate,2))// &
'... Fan ['//TRIM(cFanTypes(Furnace(FurnaceNum)%FanType_Num))// &
'] Max Value='//TRIM(RoundSigDigits(FanVolFlowRate,2)))
ENDIF
IF (Furnace(FurnaceNum)%DesignFanVolFlowRate <= 0.0d0) THEN
CALL ShowSevereError(TRIM(cFurnaceTypes(Furnace(FurnaceNum)%FurnaceType_Num))//'='//TRIM(Furnace(FurnaceNum)%Name)// &
' has a Design Fan Volume Flow Rate <= 0.0, it must be >0.0')
CALL ShowContinueError('... Entered value='//TRIM(RoundSigDigits(Furnace(FurnaceNum)%DesignFanVolFlowRate,2)))
ENDIF
MySecondOneTimeFlag(FurnaceNum)=.FALSE.
ENDIF
ENDIF
! Scan hot water and steam heating coil plant components for one time initializations
IF (MyPlantScanFlag(FurnaceNum) .AND. ALLOCATED(PlantLoop)) THEN
IF ( (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingWater) .OR. &
(Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingSteam) ) THEN
IF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingWater) THEN
ERRFlag=.false.
CALL ScanPlantLoopsForObject( Furnace(FurnaceNum)%HeatingCoilName, &
TypeOf_CoilWaterSimpleHeating , &
Furnace(FurnaceNum)%LoopNum, &
Furnace(FurnaceNum)%LoopSide, &
Furnace(FurnaceNum)%BranchNum, &
Furnace(FurnaceNum)%CompNum, &
ERRFlag=errFlag)
IF (errFlag) THEN
CALL ShowFatalError('InitFurnace: Program terminated for previous conditions.')
ENDIF
Furnace(FurnaceNum)%MaxHeatCoilFluidFlow = GetCoilMaxWaterFlowRate('Coil:Heating:Water', &
Furnace(FurnaceNum)%HeatingCoilName,ErrorsFound)
IF(Furnace(FurnaceNum)%MaxHeatCoilFluidFlow .GT. 0.0d0)THEN
rho = GetDensityGlycol(PlantLoop(Furnace(FurnaceNum)%LoopNum)%FluidName, &
InitConvTemp, &
PlantLoop(Furnace(FurnaceNum)%LoopNum)%FluidIndex, &
'InitFurnace')
Furnace(FurnaceNum)%MaxHeatCoilFluidFlow = Furnace(FurnaceNum)%MaxHeatCoilFluidFlow * rho
END IF
ELSEIF (Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingSteam) THEN
errFlag=.false.
CALL ScanPlantLoopsForObject( Furnace(FurnaceNum)%HeatingCoilName, &
TypeOf_CoilSteamAirHeating , &
Furnace(FurnaceNum)%LoopNum, &
Furnace(FurnaceNum)%LoopSide, &
Furnace(FurnaceNum)%BranchNum, &
Furnace(FurnaceNum)%CompNum, &
errFlag=errFlag)
IF (errFlag) THEN
CALL ShowFatalError('InitFurnace: Program terminated for previous conditions.')
ENDIF
Furnace(FurnaceNum)%MaxHeatCoilFluidFlow = &
GetCoilMaxSteamFlowRate(Furnace(FurnaceNum)%HeatingCoilIndex,ErrorsFound)
IF(Furnace(FurnaceNum)%MaxHeatCoilFluidFlow .GT. 0.0d0)THEN
SteamIndex = 0 ! Function GetSatDensityRefrig will look up steam index if 0 is passed
SteamDensity=GetSatDensityRefrig('STEAM',TempSteamIn,1.0d0,SteamIndex,'InitFurnace')
Furnace(FurnaceNum)%MaxHeatCoilFluidFlow = Furnace(FurnaceNum)%MaxHeatCoilFluidFlow * SteamDensity
END IF
ENDIF
! fill outlet node for coil
Furnace(FurnaceNum)%CoilOutletNode = &
PlantLoop(Furnace(FurnaceNum)%LoopNum)%LoopSide(Furnace(FurnaceNum)%LoopSide) &
%Branch(Furnace(FurnaceNum)%BranchNum)%Comp(Furnace(FurnaceNum)%CompNum)%NodeNumOut
MyPlantScanFlag(FurnaceNum) = .FALSE.
ELSE ! pthp not connected to plant
MyPlantScanFlag(FurnaceNum) = .FALSE.
ENDIF
ELSEIF (MyPlantScanFlag(FurnaceNum) .AND. .NOT. AnyPlantInModel) THEN
MyPlantScanFlag(FurnaceNum) = .FALSE.
ENDIF
! Scan Supplemental hot water and steam heating coil plant components for one time initializations
IF (MySuppCoilPlantScanFlag(FurnaceNum) .AND. ALLOCATED(PlantLoop)) THEN
IF ( (Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingWater) .OR. &
(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingSteam) ) THEN
IF (Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingWater) THEN
errFlag=.false.
CALL ScanPlantLoopsForObject( Furnace(FurnaceNum)%SuppHeatCoilName, &
TypeOf_CoilWaterSimpleHeating , &
Furnace(FurnaceNum)%LoopNumSupp, &
Furnace(FurnaceNum)%LoopSideSupp, &
Furnace(FurnaceNum)%BranchNumSupp, &
Furnace(FurnaceNum)%CompNumSupp, &
errFlag=errFlag)
IF (errFlag) THEN
CALL ShowFatalError('InitFurnace: Program terminated for previous conditions.')
ENDIF
Furnace(FurnaceNum)%MaxSuppCoilFluidFlow = GetCoilMaxWaterFlowRate('Coil:Heating:Water', &
Furnace(FurnaceNum)%SuppHeatCoilName,ErrorsFound)
IF(Furnace(FurnaceNum)%MaxSuppCoilFluidFlow .GT. 0.0d0)THEN
rho = GetDensityGlycol(PlantLoop(Furnace(FurnaceNum)%LoopNumSupp)%FluidName, &
InitConvTemp, &
PlantLoop(Furnace(FurnaceNum)%LoopNumSupp)%FluidIndex, &
'InitFurnace')
Furnace(FurnaceNum)%MaxSuppCoilFluidFlow = Furnace(FurnaceNum)%MaxSuppCoilFluidFlow * rho
END IF
ELSEIF (Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingSteam) THEN
errFlag=.false.
CALL ScanPlantLoopsForObject(Furnace(FurnaceNum)%SuppHeatCoilName, &
TypeOf_CoilSteamAirHeating , &
Furnace(FurnaceNum)%LoopNumSupp, &
Furnace(FurnaceNum)%LoopSideSupp, &
Furnace(FurnaceNum)%BranchNumSupp, &
Furnace(FurnaceNum)%CompNumSupp, &
errFlag=errFlag)
IF (errFlag) THEN
CALL ShowFatalError('InitFurnace: Program terminated for previous conditions.')
ENDIF
Furnace(FurnaceNum)%MaxSuppCoilFluidFlow = GetCoilMaxSteamFlowRate(Furnace(FurnaceNum)%SuppHeatCoilIndex,ErrorsFound)
IF(Furnace(FurnaceNum)%MaxSuppCoilFluidFlow .GT. 0.0d0)THEN
SteamIndex = 0 ! Function GetSatDensityRefrig will look up steam index if 0 is passed
SteamDensity=GetSatDensityRefrig('STEAM',TempSteamIn,1.0d0,SteamIndex,'InitFurnace')
Furnace(FurnaceNum)%MaxSuppCoilFluidFlow = Furnace(FurnaceNum)%MaxSuppCoilFluidFlow * SteamDensity
END IF
ENDIF
! fill outlet node for coil
Furnace(FurnaceNum)%SuppCoilOutletNode = &
PlantLoop(Furnace(FurnaceNum)%LoopNumSupp)%LoopSide(Furnace(FurnaceNum)%LoopSideSupp) &
%Branch(Furnace(FurnaceNum)%BranchNumSupp)%Comp(Furnace(FurnaceNum)%CompNumSupp)%NodeNumOut
MySuppCoilPlantScanFlag(FurnaceNum) = .FALSE.
ELSE ! pthp not connected to plant
MySuppCoilPlantScanFlag(FurnaceNum) = .FALSE.
ENDIF
ELSEIF (MySuppCoilPlantScanFlag(FurnaceNum) .AND. .NOT. AnyPlantInModel) THEN
MySuppCoilPlantScanFlag(FurnaceNum) = .FALSE.
ENDIF
! Do the Begin Environment initializations
IF (BeginEnvrnFlag .and. MyEnvrnFlag(FurnaceNum)) THEN
!Change the Volume Flow Rates to Mass Flow Rates
Furnace(FurnaceNum)%DesignMassFlowRate = Furnace(FurnaceNum)%DesignFanVolFlowRate * StdRhoAir
Furnace(FurnaceNum)%MaxCoolAirMassFlow = Furnace(FurnaceNum)%MaxCoolAirVolFlow * StdRhoAir
Furnace(FurnaceNum)%MaxHeatAirMassFlow = Furnace(FurnaceNum)%MaxHeatAirVolFlow * StdRhoAir
Furnace(FurnaceNum)%MaxNoCoolHeatAirMassFlow = Furnace(FurnaceNum)%MaxNoCoolHeatAirVolFlow * StdRhoAir
Furnace(FurnaceNum)%SenLoadLoss = 0.0d0
IF (Furnace(FurnaceNum)%Humidistat) Then
Furnace(FurnaceNum)%LatLoadLoss = 0.0d0
END IF
! set fluid-side hardware limits
IF(Furnace(FurnaceNum)%CoilControlNode .GT. 0)THEN
IF(Furnace(FurnaceNum)%MaxHeatCoilFluidFlow .EQ. Autosize)THEN
! If water coil max water flow rate is autosized, simulate once in order to mine max flow rate
IF(Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingWater) THEN
CALL SimulateWaterCoilComponents(Furnace(FurnaceNum)%HeatingCoilName,FirstHVACIteration, &
Furnace(FurnaceNum)%HeatingCoilIndex)
CoilMaxVolFlowRate = GetCoilMaxWaterFlowRate('Coil:Heating:Water', &
Furnace(FurnaceNum)%HeatingCoilName,ErrorsFound)
IF(CoilMaxVolFlowRate .NE. Autosize) THEN
rho = GetDensityGlycol(PlantLoop(Furnace(FurnaceNum)%LoopNum)%fluidName, &
InitConvTemp, &
PlantLoop(Furnace(FurnaceNum)%LoopNum)%fluidIndex, &
'InitFurnace')
Furnace(FurnaceNum)%MaxHeatCoilFluidFlow = CoilMaxVolFlowRate * rho
ENDIF
ENDIF
! If steam coil max steam flow rate is autosized, simulate once in order to mine max flow rate
IF(Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingSteam) THEN
CALL SimulateSteamCoilComponents(Furnace(FurnaceNum)%HeatingCoilName, &
FirstHVACIteration, &
1.0d0, & !QCoilReq, simulate any load > 0 to get max capacity
Furnace(FurnaceNum)%HeatingCoilIndex, QActual)
CoilMaxVolFlowRate = GetCoilMaxSteamFlowRate(Furnace(FurnaceNum)%HeatingCoilIndex,ErrorsFound)
IF(CoilMaxVolFlowRate .NE. Autosize) THEN
SteamIndex = 0 ! Function GetSatDensityRefrig will look up steam index if 0 is passed
SteamDensity=GetSatDensityRefrig('STEAM',TempSteamIn,1.0d0,SteamIndex,'InitFurnace')
Furnace(FurnaceNum)%MaxHeatCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity
ENDIF
ENDIF
ENDIF
Call InitComponentNodes(0.d0, Furnace(FurnaceNum)%MaxHeatCoilFluidFlow, &
Furnace(FurnaceNum)%CoilControlNode, &
Furnace(FurnaceNum)%CoilOutletNode, &
Furnace(FurnaceNum)%LoopNum, &
Furnace(FurnaceNum)%LoopSide, &
Furnace(FurnaceNum)%BranchNum, &
Furnace(FurnaceNum)%CompNum )
ENDIF
IF(Furnace(FurnaceNum)%SuppCoilControlNode .GT. 0)THEN
IF(Furnace(FurnaceNum)%MaxSuppCoilFluidFlow .EQ. Autosize)THEN
IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingWater) THEN
! If water coil max water flow rate is autosized, simulate once in order to mine max flow rate
CALL SimulateWaterCoilComponents(Furnace(FurnaceNum)%SuppHeatCoilName,FirstHVACIteration, &
Furnace(FurnaceNum)%SuppHeatCoilIndex)
CoilMaxVolFlowRate = GetCoilMaxWaterFlowRate('Coil:Heating:Water', &
Furnace(FurnaceNum)%SuppHeatCoilName,ErrorsFound)
IF(CoilMaxVolFlowRate .NE. Autosize) THEN
rho = GetDensityGlycol(PlantLoop(Furnace(FurnaceNum)%LoopNumSupp)%fluidName, &
InitConvTemp, &
PlantLoop(Furnace(FurnaceNum)%LoopNumSupp)%fluidIndex, &
'InitFurnace')
Furnace(FurnaceNum)%MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * rho
ENDIF
ENDIF
IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingSteam) THEN
CALL SimulateSteamCoilComponents(Furnace(FurnaceNum)%SuppHeatCoilName, &
FirstHVACIteration, &
1.0d0, & !QCoilReq, simulate any load > 0 to get max capacity
Furnace(FurnaceNum)%SuppHeatCoilIndex, QActual)
CoilMaxVolFlowRate = GetCoilMaxSteamFlowRate(Furnace(FurnaceNum)%SuppHeatCoilIndex,ErrorsFound)
IF(CoilMaxVolFlowRate .NE. Autosize) THEN
SteamIndex = 0 ! Function GetSatDensityRefrig will look up steam index if 0 is passed
SteamDensity=GetSatDensityRefrig('STEAM',TempSteamIn,1.0d0,SteamIndex,'InitFurnace')
Furnace(FurnaceNum)%MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity
ENDIF
ENDIF
Call InitComponentNodes(0.d0, Furnace(FurnaceNum)%MaxSuppCoilFluidFlow, &
Furnace(FurnaceNum)%SuppCoilControlNode, &
Furnace(FurnaceNum)%SuppCoilOutletNode, &
Furnace(FurnaceNum)%LoopNumSupp, &
Furnace(FurnaceNum)%LoopSideSupp, &
Furnace(FurnaceNum)%BranchNumSupp, &
Furnace(FurnaceNum)%CompNumSupp )
ENDIF
ENDIF
MyEnvrnFlag(FurnaceNum) = .FALSE.
END IF
IF (.not. BeginEnvrnFlag) THEN
MyEnvrnFlag(FurnaceNum) = .TRUE.
ENDIF
IF(MyFanFlag(FurnaceNum))THEN
IF(Furnace(FurnaceNum)%ActualFanVolFlowRate /= Autosize)THEN
IF(Furnace(FurnaceNum)%ActualFanVolFlowRate .GT. 0.0d0)THEN
Furnace(FurnaceNum)%HeatingSpeedRatio = Furnace(FurnaceNum)%MaxHeatAirVolFlow/Furnace(FurnaceNum)%ActualFanVolFlowRate
Furnace(FurnaceNum)%CoolingSpeedRatio = Furnace(FurnaceNum)%MaxCoolAirVolFlow/Furnace(FurnaceNum)%ActualFanVolFlowRate
Furnace(FurnaceNum)%NoHeatCoolSpeedRatio = &
Furnace(FurnaceNum)%MaxNoCoolHeatAirVolFlow/Furnace(FurnaceNum)%ActualFanVolFlowRate
END IF
IF(GetFanSpeedRatioCurveIndex(FanType,FanName,Furnace(FurnaceNum)%FanIndex) .GT. 0)THEN
IF(Furnace(FurnaceNum)%ActualFanVolFlowRate .EQ. Furnace(FurnaceNum)%MaxHeatAirVolFlow .AND. &
Furnace(FurnaceNum)%ActualFanVolFlowRate .EQ. Furnace(FurnaceNum)%MaxCoolAirVolFlow .AND. &
Furnace(FurnaceNum)%ActualFanVolFlowRate .EQ. Furnace(FurnaceNum)%MaxNoCoolHeatAirVolFlow)THEN
CALL ShowWarningError(TRIM(cFurnaceTypes(Furnace(FurnaceNum)%FurnaceType_Num))// &
' "'//TRIM(Furnace(FurnaceNum)%Name)//'"')
CALL ShowContinueError('...For fan type and name = '//TRIM(FanType)//' "'//TRIM(FanName)//'"')
CALL ShowContinueError('...Fan power ratio function of speed ratio curve has no impact if fan volumetric '// &
'flow rate is the same as the unitary system volumetric flow rate.')
CALL ShowContinueError('...Fan volumetric flow rate = '// &
TRIM(RoundSigDigits(Furnace(FurnaceNum)%ActualFanVolFlowRate,5))//' m3/s.')
CALL ShowContinueError('...Unitary system volumetric flow rate = '// &
TRIM(RoundSigDigits(Furnace(FurnaceNum)%MaxHeatAirVolFlow,5))//' m3/s.')
END IF
END IF
MyFanFlag(FurnaceNum) = .FALSE.
ELSE
Furnace(FurnaceNum)%ActualFanVolFlowRate = &
GetFanDesignVolumeFlowRate(Blank,Blank,ErrFlag,Furnace(FurnaceNum)%FanIndex)
END IF
END IF
! Get the zone inlet node
IF (ALLOCATED(ZoneEquipConfig) .AND. MyCheckFlag(FurnaceNum)) THEN
DO i=1,NumOfZones
IF (AirLoopNum .NE. ZoneEquipConfig(i)%AirLoopNum) CYCLE
IF (Furnace(FurnaceNum)%ControlZoneNum .EQ. ZoneEquipConfig(i)%ActualZoneNum) Then
Do j=1, ZoneEquipConfig(i)%NumInletNodes
If (Furnace(FurnaceNum)%ZoneInletNode .EQ. 0) Then
Do k=1,ZoneEquipConfig(i)%NumInletNodes
If (ZoneEquipConfig(i)%InletNode(j) .EQ. ZoneEquipConfig(i)%AirDistUnitCool(k)%OutNode) Then
Furnace(FurnaceNum)%ZoneInletNode = ZoneEquipConfig(i)%InletNode(j)
Exit
End If
end do
End If
If (Furnace(FurnaceNum)%ZoneInletNode .EQ. 0) Then
Do k=1,ZoneEquipConfig(i)%NumInletNodes
If (ZoneEquipConfig(i)%InletNode(j) .EQ. ZoneEquipConfig(i)%AirDistUnitHeat(k)%OutNode) Then
Furnace(FurnaceNum)%ZoneInletNode = ZoneEquipConfig(i)%InletNode(j)
Exit
End If
End do
End If
End Do
!setup furnace zone equipment sequence information based on finding an air terminal
IF (ZoneEquipConfig(i)%EquipListIndex > 0) THEN
DO EquipNum = 1, ZoneEquipList(ZoneEquipConfig(i)%EquipListIndex)%NumOfEquipTypes
IF ((ZoneEquipList(ZoneEquipConfig(i)%EquipListIndex)%EquipType_Num(EquipNum) == AirDistUnit_Num) &
.OR. (ZoneEquipList(ZoneEquipConfig(i)%EquipListIndex)%EquipType_Num(EquipNum) == DirectAir_Num) ) THEN
Furnace(FurnaceNum)%ZoneSequenceCoolingNum = &
ZoneEquipList(ZoneEquipConfig(i)%EquipListIndex)%CoolingPriority(EquipNum)
Furnace(FurnaceNum)%ZoneSequenceHeatingNum = &
ZoneEquipList(ZoneEquipConfig(i)%EquipListIndex)%HeatingPriority(EquipNum)
ENDIF
ENDDO
ENDIF
END IF
END DO
MyCheckFlag(FurnaceNum) = .FALSE.
If (Furnace(FurnaceNum)%ZoneInletNode .EQ. 0) Then
CALL ShowSevereError(TRIM(cFurnaceTypes(Furnace(FurnaceNum)%FurnaceType_Num))//' "'//TRIM(Furnace(FurnaceNum)%Name)// &
'": The zone inlet node in the controlled zone (' &
//Trim(Zone(Furnace(FurnaceNum)%ControlZoneNum)%Name) //') is not found.')
CALL ShowFatalError('Subroutine InitFurnace: '//'Errors found in getting '// &
TRIM(cFurnaceTypes(Furnace(FurnaceNum)%FurnaceType_Num))//' input. '//'Preceding condition(s) causes termination.')
End If
END IF
! Find the number of zones (zone Inlet Nodes) attached to an air loop from the air loop number
NumAirLoopZones = AirToZoneNodeInfo(AirLoopNum)%NumZonesCooled + AirToZoneNodeInfo(AirLoopNum)%NumZonesHeated
IF (ALLOCATED(AirToZoneNodeInfo) .AND. MyFlowFracFlag(FurnaceNum)) THEN
FlowFracFlagReady = .TRUE.
ZonesLoop: DO ZoneInSysIndex = 1, NumAirLoopZones
! zone inlet nodes for cooling
IF (AirToZoneNodeInfo(AirLoopNum)%NumZonesCooled > 0) THEN
IF( AirToZoneNodeInfo(AirLoopNum)%TermUnitCoolInletNodes(ZoneInSysIndex) == -999 )THEN
! the data structure for the zones inlet nodes has not been filled
FlowFracFlagReady = .FALSE.
ENDIF
ENDIF
! zone inlet nodes for heating
IF (AirToZoneNodeInfo(AirLoopNum)%NumZonesHeated > 0) THEN
IF( AirToZoneNodeInfo(AirLoopNum)%TermUnitHeatInletNodes(ZoneInSysIndex) == -999 ) THEN
! the data structure for the zones inlet nodes has not been filled
FlowFracFlagReady = .FALSE.
ENDIF
ENDIF
END DO ZonesLoop
ENDIF
IF (ALLOCATED(AirToZoneNodeInfo) .AND. FlowFracFlagReady ) THEN
SumOfMassFlowRateMax = 0.0d0 ! initialize the sum of the maximum flows
DO ZoneInSysIndex = 1, NumAirLoopZones
ZoneInletNodeNum = AirToZoneNodeInfo(AirLoopNum)%TermUnitCoolInletNodes(ZoneInSysIndex)
SumOfMassFlowRateMax = SumOfMassFlowRateMax + Node(ZoneInletNodeNum)%MassFlowRateMax
IF(AirToZoneNodeInfo(AirLoopNum)%CoolCtrlZoneNums(ZoneInSysIndex) == Furnace(FurnaceNum)%ControlZoneNum )THEN
CntrlZoneTerminalUnitMassFlowRateMax = Node(ZoneInletNodeNum)%MassFlowRateMax
ENDIF
END DO
IF (SumOfMassFlowRateMax /= 0.0d0 .AND. MyFlowFracFlag(FurnaceNum)) THEN
IF (CntrlZoneTerminalUnitMassFlowRateMax >= SmallAirVolFlow ) THEN
Furnace(FurnaceNum)%ControlZoneMassFlowFrac = CntrlZoneTerminalUnitMassFlowRateMax/SumOfMassFlowRateMax
ELSE
CALL ShowSevereError(TRIM(cFurnaceTypes(Furnace(FurnaceNum)%FurnaceType_Num))//' = '//TRIM(Furnace(FurnaceNum)%Name))
CALL ShowContinueError(' The Fraction of Supply Air Flow That Goes Through the Controlling Zone is set to 1.')
END IF
CALL ReportSizingOutput(cFurnaceTypes(Furnace(FurnaceNum)%FurnaceType_Num),Furnace(FurnaceNum)%Name, &
'Fraction of Supply Air Flow That Goes Through the Controlling Zone', &
Furnace(FurnaceNum)%ControlZoneMassFlowFrac)
MyFlowFracFlag(FurnaceNum) = .FALSE.
ENDIF
ENDIF
! Calcuate air distribution losses
IF (.NOT. FirstHVACIteration .AND. AirLoopPass .eq. 1) Then
ZoneInNode = Furnace(FurnaceNum)%ZoneInletNode
MinHumRat = Node(ZoneInNode)%HumRat
MassFlowRate = Node(ZoneInNode)%MassFlowrate/Furnace(FurnaceNum)%ControlZoneMassFlowFrac
IF(Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%Temp .LT. Node(Furnace(FurnaceNum)%NodeNumofControlledZone)%Temp ) &
MinHumRat = Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%HumRat
If (SimulateAirflowNetwork > AirflowNetworkControlMultizone) Then
DeltaMassRate = Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%MassFlowrate - &
Node(ZoneInNode)%MassFlowrate/Furnace(FurnaceNum)%ControlZoneMassFlowFrac
If (DeltaMassRate .LT. 0.0d0) DeltaMassRate = 0.0d0
Else
MassFlowRate = Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%MassFlowrate
DeltaMassRate = 0.0d0
End If
Furnace(FurnaceNum)%SenLoadLoss = MassFlowRate * (PsyHFnTdbW(Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%Temp,MinHumRat)- &
PsyHFnTdbW(Node(ZoneInNode)%Temp,MinHumRat)) + DeltaMassRate * &
(PsyHFnTdbW(Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%Temp,MinHumRat) - &
PsyHFnTdbW(Node(Furnace(FurnaceNum)%NodeNumofControlledZone)%Temp,MinHumRat))
If (ABS(Furnace(FurnaceNum)%SensibleLoadMet) > 0.0d0) Then
If (ABS(Furnace(FurnaceNum)%SenLoadLoss/Furnace(FurnaceNum)%SensibleLoadMet) < 0.001d0) &
Furnace(FurnaceNum)%SenLoadLoss = 0.0d0
End If
IF(Furnace(FurnaceNum)%Humidistat)THEN
MaxTemp = Node(Furnace(FurnaceNum)%NodeNumofControlledZone)%Temp
Furnace(FurnaceNum)%LatLoadLoss = MassFlowRate*(PsyHFnTdbW(MaxTemp,Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%HumRat)- &
PsyHFnTdbW(MaxTemp,Node(ZoneInNode)%HumRat)) + DeltaMassRate * &
(PsyHFnTdbW(MaxTemp,Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%HumRat) - &
PsyHFnTdbW(MaxTemp,Node(Furnace(FurnaceNum)%NodeNumofControlledZone)%HumRat))
If (ABS(Furnace(FurnaceNum)%LatentLoadMet) > 0.0d0) Then
If (ABS(Furnace(FurnaceNum)%LatLoadLoss/Furnace(FurnaceNum)%LatentLoadMet) < 0.001d0) &
Furnace(FurnaceNum)%LatLoadLoss = 0.0d0
End If
End If
End If
IF (Furnace(FurnaceNum)%FanSchedPtr .GT. 0) THEN
IF (GetCurrentScheduleValue(Furnace(FurnaceNum)%FanSchedPtr) .EQ. 0.0d0) THEN
Furnace(FurnaceNum)%OpMode = CycFanCycCoil
ELSE
Furnace(FurnaceNum)%OpMode = ContFanCycCoil
END IF
END IF
OpMode = Furnace(FurnaceNum)%OpMode
EconomizerFlag = AirLoopControlInfo(AirLoopNum)%EconoActive
IF(Furnace(FurnaceNum)%ControlZoneMassFlowFrac .GT. 0.0d0)THEN
QZnReq = ZoneLoad/Furnace(FurnaceNum)%ControlZoneMassFlowFrac
MoistureLoad = MoistureLoad/Furnace(FurnaceNum)%ControlZoneMassFlowFrac
ZoneLoad = QZnReq
ELSE
QZnReq = ZoneLoad
END IF
! Original thermostat control logic (works only for cycling fan systems)
IF(QZnReq .GT. SmallLoad .AND. QZnReq .GT. (Small5WLoad/Furnace(FurnaceNum)%ControlZoneMassFlowFrac) &
.AND. .NOT. CurDeadbandOrSetback(Furnace(FurnaceNum)%ControlZoneNum))THEN
HeatingLoad = .TRUE.
CoolingLoad = .FALSE.
ELSE IF(QZnReq .LT. (-1.d0 * SmallLoad) .AND. ABS(QZnReq) .GT. (Small5WLoad/Furnace(FurnaceNum)%ControlZoneMassFlowFrac) &
.AND. .NOT. CurDeadbandOrSetback(Furnace(FurnaceNum)%ControlZoneNum))THEN
HeatingLoad = .FALSE.
CoolingLoad = .TRUE.
ELSE
HeatingLoad = .FALSE.
CoolingLoad = .FALSE.
END IF
IF (Furnace(FurnaceNum)%FurnaceType_Num == UnitarySys_HeatPump_AirToAir .OR. &
(Furnace(FurnaceNum)%FurnaceType_Num == UnitarySys_HeatPump_WaterToAir .AND. &
(Furnace(FurnaceNum)%WatertoAirHPType == WatertoAir_Simple .OR. &
Furnace(FurnaceNum)%WatertoAirHPType == WatertoAir_VarSpeedEquationFit) )) THEN
IF (MoistureLoad .LT. 0.d0 .AND. Furnace(FurnaceNum)%DehumidControlType_Num .EQ. DehumidControl_CoolReheat) THEN
HPDehumidificationLoadFlag = .TRUE.
HeatingLoad = .FALSE.
CoolingLoad = .TRUE.
ELSE
HPDehumidificationLoadFlag = .FALSE.
ENDIF
ENDIF
! Check for heat only furnace
IF(Furnace(FurnaceNum)%FurnaceType_Num .NE. Furnace_HeatOnly .AND. &
Furnace(FurnaceNum)%FurnaceType_Num .NE. UnitarySys_HeatOnly)THEN
IF (GetCurrentScheduleValue(Furnace(FurnaceNum)%SchedPtr) .gt. 0.0d0) THEN
IF ( (HeatingLoad .OR. CoolingLoad) .OR. &
(Furnace(FurnaceNum)%Humidistat .AND. MoistureLoad .LT. 0.0d0) ) THEN
PartLoadRatio = 1.0d0
ELSE
PartLoadRatio = 0.0d0
END IF
ELSE
PartLoadRatio = 0.0d0
END IF
ELSE
PartLoadRatio = 1.0d0
END IF
! get current time step operating capacity of water and steam coils
! (dependent on entering water and steam temperature)
IF(FirstHVACIteration) THEN
IF(Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingWater) THEN
! set water-side mass flow rates
Node(Furnace(FurnaceNum)%HWCoilAirInletNode)%MassFlowRate = CompOnMassFlow
mdot = Furnace(FurnaceNum)%MaxHeatCoilFluidFlow
CALL SetComponentFlowRate(mdot, &
Furnace(FurnaceNum)%CoilControlNode, &
Furnace(FurnaceNum)%CoilOutletNode, &
Furnace(FurnaceNum)%LoopNum, &
Furnace(FurnaceNum)%LoopSide, &
Furnace(FurnaceNum)%BranchNum, &
Furnace(FurnaceNum)%CompNum )
! simulate water coil to find operating capacity
CALL SimulateWaterCoilComponents(Furnace(FurnaceNum)%HeatingCoilName,FirstHVACIteration, &
Furnace(FurnaceNum)%HeatingCoilIndex, QActual)
Furnace(FurnaceNum)%DesignHeatingCapacity = QActual
END IF ! from IF(Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingWater) THEN
IF(Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingSteam) THEN
! set air-side and steam-side mass flow rates
Node(Furnace(FurnaceNum)%HWCoilAirInletNode)%MassFlowRate = CompOnMassFlow
mdot = Furnace(FurnaceNum)%MaxHeatCoilFluidFlow
CALL SetComponentFlowRate(mdot, &
Furnace(FurnaceNum)%CoilControlNode, &
Furnace(FurnaceNum)%CoilOutletNode, &
Furnace(FurnaceNum)%LoopNum, &
Furnace(FurnaceNum)%LoopSide, &
Furnace(FurnaceNum)%BranchNum, &
Furnace(FurnaceNum)%CompNum )
! simulate steam coil to find operating capacity
CALL SimulateSteamCoilComponents(Furnace(FurnaceNum)%HeatingCoilName, &
FirstHVACIteration, &
1.0d0, & !QCoilReq, simulate any load > 0 to get max capacity of steam coil
Furnace(FurnaceNum)%HeatingCoilIndex, QActual)
Furnace(FurnaceNum)%DesignHeatingCapacity = GetSteamCoilCapacity(Furnace(FurnaceNum)%HeatingCoilType, &
Furnace(FurnaceNum)%HeatingCoilName,ErrorsFound)
END IF ! from IF(Furnace(FurnaceNum)%HeatingCoilType_Num == Coil_HeatingSteam) THEN
IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingWater) THEN
! set air-side and steam-side mass flow rates
Node(Furnace(FurnaceNum)%SuppCoilAirInletNode)%MassFlowRate = CompOnMassFlow
mdot = Furnace(FurnaceNum)%MaxSuppCoilFluidFlow
CALL SetComponentFlowRate(mdot, &
Furnace(FurnaceNum)%SuppCoilControlNode, &
Furnace(FurnaceNum)%SuppCoilOutletNode, &
Furnace(FurnaceNum)%LoopNumSupp, &
Furnace(FurnaceNum)%LoopSideSupp, &
Furnace(FurnaceNum)%BranchNumSupp, &
Furnace(FurnaceNum)%CompNumSupp )
! simulate water coil to find operating capacity
CALL SimulateWaterCoilComponents(Furnace(FurnaceNum)%SuppHeatCoilName,FirstHVACIteration, &
Furnace(FurnaceNum)%SuppHeatCoilIndex, QActual)
Furnace(FurnaceNum)%DesignSuppHeatingCapacity = QActual
END IF ! from IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingWater) THEN
!
IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingSteam) THEN
! set air-side and steam-side mass flow rates
Node(Furnace(FurnaceNum)%SuppCoilAirInletNode)%MassFlowRate = CompOnMassFlow
mdot = Furnace(FurnaceNum)%MaxSuppCoilFluidFlow
CALL SetComponentFlowRate(mdot, &
Furnace(FurnaceNum)%SuppCoilControlNode, &
Furnace(FurnaceNum)%SuppCoilOutletNode, &
Furnace(FurnaceNum)%LoopNumSupp, &
Furnace(FurnaceNum)%LoopSideSupp, &
Furnace(FurnaceNum)%BranchNumSupp, &
Furnace(FurnaceNum)%CompNumSupp )
! simulate steam coil to find operating capacity
CALL SimulateSteamCoilComponents(Furnace(FurnaceNum)%SuppHeatCoilName, &
FirstHVACIteration, &
1.0d0, & !QCoilReq, simulate any load > 0 to get max capacity of steam coil
Furnace(FurnaceNum)%SuppHeatCoilIndex, QActual)
Furnace(FurnaceNum)%DesignSuppHeatingCapacity = &
GetSteamCoilCapacity(Furnace(FurnaceNum)%SuppHeatCoilType,Furnace(FurnaceNum)%SuppHeatCoilName,ErrorsFound)
END IF ! from IF(Furnace(FurnaceNum)%SuppHeatCoilType_Num == Coil_HeatingSteam) THEN
END IF ! from IF( FirstHVACIteration ) THEN
IF( Furnace(FurnaceNum)%NumOfSpeedCooling > 0 ) THEN !BoS, variable-speed water source hp
!Furnace(FurnaceNum)%IdleMassFlowRate = RhoAir*Furnace(FurnaceNum)%IdleVolumeAirRate
NumOfSpeedCooling = Furnace(FurnaceNum)%NumOfSpeedCooling
NumOfSpeedHeating = Furnace(FurnaceNum)%NumOfSpeedHeating
! IF MSHP system was not autosized and the fan is autosized, check that fan volumetric flow rate is greater than MSHP flow rates
IF(Furnace(FurnaceNum)%CheckFanFlow)THEN
CurrentModuleObject = 'AirLoopHVAC:UnitaryHeatPump:VariableSpeed'
CALL GetFanVolFlow(Furnace(FurnaceNum)%FanIndex,Furnace(FurnaceNum)%FanVolFlow)
IF(Furnace(FurnaceNum)%FanVolFlow .NE. AutoSize)THEN
! Check fan versus system supply air flow rates
IF(Furnace(FurnaceNum)%FanVolFlow + 1d-10 .LT. &
Furnace(FurnaceNum)%CoolVolumeFlowRate(NumOfSpeedCooling))THEN
CALL ShowWarningError(TRIM(CurrentModuleObject)//' - air flow rate = ' &
//TRIM(TrimSigDigits(Furnace(FurnaceNum)%FanVolFlow,7))//' in fan object ' &
//' is less than the MSHP system air flow rate' &
//' when cooling is required ('// &
TRIM(TrimSigDigits(Furnace(FurnaceNum)%CoolVolumeFlowRate(NumOfSpeedCooling),7))//').')
CALL ShowContinueError(' The MSHP system flow rate when cooling is required is reset to the' &
//' fan flow rate and the simulation continues.')
CALL ShowContinueError(' Occurs in '//TRIM(CurrentModuleObject)//' = '//TRIM(Furnace(FurnaceNum)%Name))
Furnace(FurnaceNum)%CoolVolumeFlowRate(NumOfSpeedCooling) = Furnace(FurnaceNum)%FanVolFlow
! Check flow rates in other speeds and ensure flow rates are not above the max flow rate
Do i=NumOfSpeedCooling-1,1,-1
If (Furnace(FurnaceNum)%CoolVolumeFlowRate(i) .GT. Furnace(FurnaceNum)%CoolVolumeFlowRate(i+1)) Then
CALL ShowContinueError(' The MSHP system flow rate when cooling is required is reset to the' &
//' flow rate at higher speed and the simulation continues at Speed'//TrimSigDigits(i,0)//'.')
CALL ShowContinueError(' Occurs in '//TRIM(CurrentModuleObject)//' = '//TRIM(Furnace(FurnaceNum)%Name))
Furnace(FurnaceNum)%CoolVolumeFlowRate(i) = Furnace(FurnaceNum)%CoolVolumeFlowRate(i+1)
End If
End Do
END IF
IF(Furnace(FurnaceNum)%FanVolFlow + 1d-10 .LT. &
Furnace(FurnaceNum)%HeatVolumeFlowRate(NumOfSpeedHeating))THEN
CALL ShowWarningError(TRIM(CurrentModuleObject)//' - air flow rate = ' &
//TRIM(TrimSigDigits(Furnace(FurnaceNum)%FanVolFlow,7))//' in fan object ' &
//' is less than the MSHP system air flow rate' &
//' when heating is required ('// &
TRIM(TrimSigDigits(Furnace(FurnaceNum)%HeatVolumeFlowRate(NumOfSpeedHeating),7))//').')
CALL ShowContinueError(' The MSHP system flow rate when heating is required is reset to the' &
//' fan flow rate and the simulation continues.')
CALL ShowContinueError(' Occurs in '//TRIM(CurrentModuleObject)//' = '//TRIM(Furnace(FurnaceNum)%Name))
Furnace(FurnaceNum)%HeatVolumeFlowRate(NumOfSpeedHeating) = Furnace(FurnaceNum)%FanVolFlow
Do i=NumOfSpeedHeating-1,1,-1
If (Furnace(FurnaceNum)%HeatVolumeFlowRate(i) .GT. Furnace(FurnaceNum)%HeatVolumeFlowRate(i+1)) Then
CALL ShowContinueError(' The MSHP system flow rate when heating is required is reset to the' &
//' flow rate at higher speed and the simulation continues at Speed'//TrimSigDigits(i,0)//'.')
CALL ShowContinueError(' Occurs in '//TRIM(CurrentModuleObject)//' system = '//TRIM(Furnace(FurnaceNum)%Name))
Furnace(FurnaceNum)%HeatVolumeFlowRate(i) = Furnace(FurnaceNum)%HeatVolumeFlowRate(i+1)
End If
End Do
END IF
IF(Furnace(FurnaceNum)%FanVolFlow .LT. Furnace(FurnaceNum)%IdleVolumeAirRate .AND. &
Furnace(FurnaceNum)%IdleVolumeAirRate .NE. 0.0d0)THEN
CALL ShowWarningError(TRIM(CurrentModuleObject)//' - air flow rate = ' &
//TRIM(TrimSigDigits(Furnace(FurnaceNum)%FanVolFlow,7))//' in fan object ' &
//' is less than the MSHP system air flow rate when no ' &
//'heating or cooling is needed ('//TRIM(TrimSigDigits(Furnace(FurnaceNum)%IdleVolumeAirRate,7))//').')
CALL ShowContinueError(' The MSHP system flow rate when no heating or cooling is needed is reset to the' &
//' fan flow rate and the simulation continues.')
CALL ShowContinueError(' Occurs in '//TRIM(CurrentModuleObject)//' = '//TRIM(Furnace(FurnaceNum)%Name))
Furnace(FurnaceNum)%IdleVolumeAirRate = Furnace(FurnaceNum)%FanVolFlow
END IF
RhoAir = StdRhoAir
! set the mass flow rates from the reset volume flow rates
Do I=1,NumOfSpeedCooling
Furnace(FurnaceNum)%CoolMassFlowRate(i) = RhoAir*Furnace(FurnaceNum)%CoolVolumeFlowRate(i)
IF(Furnace(FurnaceNum)%FanVolFlow .GT. 0.0d0)THEN
Furnace(FurnaceNum)%MSCoolingSpeedRatio(i) = &
Furnace(FurnaceNum)%CoolVolumeFlowRate(i)/Furnace(FurnaceNum)%FanVolFlow
END IF
End Do
Do I=1,NumOfSpeedHeating
Furnace(FurnaceNum)%HeatMassFlowRate(i) = RhoAir*Furnace(FurnaceNum)%HeatVolumeFlowRate(i)
IF(Furnace(FurnaceNum)%FanVolFlow .GT. 0.0d0)THEN
Furnace(FurnaceNum)%MSHeatingSpeedRatio(i) = &
Furnace(FurnaceNum)%HeatVolumeFlowRate(i)/Furnace(FurnaceNum)%FanVolFlow
END IF
End Do
Furnace(FurnaceNum)%IdleMassFlowRate = RhoAir*Furnace(FurnaceNum)%IdleVolumeAirRate
IF(Furnace(FurnaceNum)%FanVolFlow .GT. 0.0d0)THEN
Furnace(FurnaceNum)%IdleSpeedRatio = &
Furnace(FurnaceNum)%IdleVolumeAirRate / Furnace(FurnaceNum)%FanVolFlow
END IF
! set the node max and min mass flow rates based on reset volume flow rates
Node(InNode)%MassFlowRateMax = MAX(Furnace(FurnaceNum)%CoolMassFlowRate(NumOfSpeedCooling), &
Furnace(FurnaceNum)%HeatMassFlowRate(NumOfSpeedHeating))
Node(InNode)%MassFlowRateMaxAvail = MAX(Furnace(FurnaceNum)%CoolMassFlowRate(NumOfSpeedCooling), &
Furnace(FurnaceNum)%HeatMassFlowRate(NumOfSpeedHeating))
Node(InNode)%MassFlowRateMin = 0.0d0
Node(InNode)%MassFlowRateMinAvail = 0.0d0
Node(OutNode) = Node(InNode)
END IF
END IF
Furnace(FurnaceNum)%CheckFanFlow = .FALSE.
! CALL SetOnOffMassFlowRateVSCoil(FurnaceNum, Furnace(FurnaceNum)%ControlZoneNum, FirstHVACIteration, &
! AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
ELSE
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
END IF
! Check ventilation/fan load for constant fan systems to see if load to be met changes
! Same IF logic used in Subroutine SetAverageAirFlow to determine if unit is ON or OFF
IF(OpMode .EQ. ContFanCycCoil .AND. GetCurrentScheduleValue(Furnace(FurnaceNum)%SchedPtr) .GT. 0.0d0 .AND. &
( (GetCurrentScheduleValue(Furnace(FurnaceNum)%FanAvailSchedPtr) .GT. 0.0d0 .OR. TurnFansOn) &
.AND. .NOT. TurnFansOff) )THEN
IF(Furnace(FurnaceNum)%NumOfSpeedCooling > 0) THEN
CALL CalcVarSpeedHeatPump(FurnaceNum,.FALSE.,off,1,0.0d0,0.0d0,SensibleOutput,LatentOutput, &
0.0d0, 0.0d0, OnOffAirFlowRatio, SUPHEATERLOAD)
ELSE
CALL CalcFurnaceOutput(FurnaceNum,.FALSE.,0,Off,0.0d0,0.0d0,0.0d0,0.0d0,SensibleOutput, &
LatentOutput,OnOffAirFlowRatio,.FALSE.)
END IF
IF(Furnace(FurnaceNum)%ControlZoneMassFlowFrac .GT. 0.0d0)THEN
IF (Furnace(FurnaceNum)%ZoneSequenceCoolingNum > 0 .and. Furnace(FurnaceNum)%ZoneSequenceHeatingNum > 0) THEN
QToCoolSetPt=ZoneSysEnergyDemand(Furnace(FurnaceNum)%ControlZoneNum)% &
SequencedOutputRequiredToCoolingSP(Furnace(FurnaceNum)%ZoneSequenceCoolingNum)/ &
Furnace(FurnaceNum)%ControlZoneMassFlowFrac
QToHeatSetPt=ZoneSysEnergyDemand(Furnace(FurnaceNum)%ControlZoneNum)% &
SequencedOutputRequiredToHeatingSP(Furnace(FurnaceNum)%ZoneSequenceHeatingNum)/ &
Furnace(FurnaceNum)%ControlZoneMassFlowFrac
ELSE
QToCoolSetPt=ZoneSysEnergyDemand(Furnace(FurnaceNum)%ControlZoneNum)%OutputRequiredToCoolingSP/ &
Furnace(FurnaceNum)%ControlZoneMassFlowFrac
QToHeatSetPt=ZoneSysEnergyDemand(Furnace(FurnaceNum)%ControlZoneNum)%OutputRequiredToHeatingSP/ &
Furnace(FurnaceNum)%ControlZoneMassFlowFrac
ENDIF
! If the furnace has a net cooling capacity (SensibleOutput < 0) and
! the zone temp is above the Tstat heating setpoint (QToHeatSetPt < 0) and
! the net cooling capacity does not just offset the cooling load
IF(SensibleOutput .LT. 0.0d0 .AND. QToHeatSetPt .LT. 0.0d0 .AND. &
ABS(QToCoolSetPt - SensibleOutput) .GT. (Small5WLoad/Furnace(FurnaceNum)%ControlZoneMassFlowFrac))THEN
! Only switch modes when humidistat is not used or no moisture load exists, otherwise let
! reheat coil pick up load
! IF((SensibleOutput .LT. QToHeatSetPt .AND. .NOT. Furnace(FurnaceNum)%Humidistat) .OR. &
! (SensibleOutput .LT. QToHeatSetPt .AND. Furnace(FurnaceNum)%Humidistat .AND. MoistureLoad .GE. 0.0))THEN
IF((SensibleOutput .LT. QToHeatSetPt .AND. .NOT. Furnace(FurnaceNum)%Humidistat) .OR. &
(SensibleOutput .LT. QToHeatSetPt .AND. Furnace(FurnaceNum)%Humidistat .AND. MoistureLoad .GE. 0.0d0))THEN
QZnReq = QToHeatSetPt
CoolingLoad = .FALSE.
! Don't set mode TRUE unless mode is allowed. Also check for floating zone.
IF(TempControlType(Furnace(FurnaceNum)%ControlZoneNum) .EQ. SingleCoolingSetPoint .OR. &
TempControlType(Furnace(FurnaceNum)%ControlZoneNum) .EQ. 0)THEN
HeatingLoad = .FALSE.
ELSE
HeatingLoad = .TRUE.
END IF
IF(Furnace(FurnaceNum)%NumOfSpeedCooling > 0) THEN
!CALL SetOnOffMassFlowRateVSCoil(FurnaceNum, Furnace(FurnaceNum)%ControlZoneNum, FirstHVACIteration, &
! AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
CALL CalcVarSpeedHeatPump(FurnaceNum,.FALSE.,off,1,0.0d0,0.0d0,SensibleOutput,LatentOutput, &
0.0d0, 0.0d0, OnOffAirFlowRatio, SUPHEATERLOAD)
ELSE
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
CALL CalcFurnaceOutput(FurnaceNum,.FALSE.,0,Off,0.0d0,0.0d0,0.0d0,0.0d0,SensibleOutput,LatentOutput, &
OnOffAirFlowRatio,.FALSE.)
END IF
IF(SensibleOutput .GT. QToHeatSetPt)THEN
! If changing operating mode (flow rates) does not overshoot heating setpoint, turn off heating
QZnReq = 0.0d0
HeatingLoad = .FALSE.
IF(Furnace(FurnaceNum)%NumOfSpeedCooling > 0) THEN
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
! CALL SetOnOffMassFlowRateVSCoil(FurnaceNum, Furnace(FurnaceNum)%ControlZoneNum, FirstHVACIteration, &
! AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
ELSE
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
END IF
END IF
ELSE IF(SensibleOutput .LT. QZnReq)THEN
! If the net cooling capacity meets the zone cooling load but does not overshoot heating setpoint, turn off cooling
! (dehumidification may still occur)
QZnReq = 0.0d0
CoolingLoad = .FALSE.
IF (HPDehumidificationLoadFlag) THEN
CoolingLoad = .TRUE.
HeatingLoad = .FALSE.
ENDIF
IF(Furnace(FurnaceNum)%NumOfSpeedCooling > 0) THEN
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, &
MoistureLoad, PartLoadRatio)
! CALL SetOnOffMassFlowRateVSCoil(FurnaceNum, Furnace(FurnaceNum)%ControlZoneNum, FirstHVACIteration, &
! AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
ELSE
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad,PartLoadRatio)
END IF
END IF
! the net cooling capacity just offsets the cooling load, turn off cooling
ELSE IF(SensibleOutput .LT. 0.0d0 .AND. QToCoolSetPt .LT. 0.0d0 .AND. &
ABS(QToCoolSetPt - SensibleOutput) .LT. (Small5WLoad/Furnace(FurnaceNum)%ControlZoneMassFlowFrac))THEN
CoolingLoad = .FALSE.
IF (HPDehumidificationLoadFlag) THEN
CoolingLoad = .TRUE.
HeatingLoad = .FALSE.
ENDIF
END IF ! SensibleOutput .LT. 0.0d0 .AND. QToHeatSetPt .LT. 0.0d0
! If the furnace has a net heating capacity and the zone temp is below the Tstat cooling setpoint and
! the net heating capacity does not just offset the heating load
IF(SensibleOutput .GT. 0.0d0 .AND. QToCoolSetPt .GT. 0.0d0 .AND. &
ABS(SensibleOutput - QToHeatSetPt) .GT. (Small5WLoad/Furnace(FurnaceNum)%ControlZoneMassFlowFrac))THEN
IF(SensibleOutput .GT. QToCoolSetPt)THEN
QZnReq = QToCoolSetPt
! Don't set mode TRUE unless mode is allowed. Also check for floating zone.
IF(TempControlType(Furnace(FurnaceNum)%ControlZoneNum) .EQ. SingleHeatingSetPoint .OR. &
TempControlType(Furnace(FurnaceNum)%ControlZoneNum) .EQ. 0)THEN
CoolingLoad = .FALSE.
ELSE
CoolingLoad = .TRUE.
END IF
HeatingLoad = .FALSE.
IF(Furnace(FurnaceNum)%NumOfSpeedCooling > 0) THEN
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, &
MoistureLoad, PartLoadRatio)
! CALL SetOnOffMassFlowRateVSCoil(FurnaceNum, Furnace(FurnaceNum)%ControlZoneNum, FirstHVACIteration, &
! AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
CALL CalcVarSpeedHeatPump(FurnaceNum,.FALSE.,off,1,0.0d0,0.0d0,SensibleOutput,LatentOutput, &
0.0d0, 0.0d0, OnOffAirFlowRatio, SUPHEATERLOAD)
ELSE
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad,PartLoadRatio)
CALL CalcFurnaceOutput(FurnaceNum,.FALSE.,0,Off,0.0d0,0.0d0,0.0d0,0.0d0,SensibleOutput,LatentOutput, &
OnOffAirFlowRatio,.FALSE.)
END IF
IF(SensibleOutput .LT. QToCoolSetPt)THEN
! If changing operating mode (flow rates) does not overshoot cooling setpoint, turn off cooling
IF (HPDehumidificationLoadFlag) THEN
CoolingLoad = .TRUE.
HeatingLoad = .FALSE.
ELSE
QZnReq = 0.0d0
CoolingLoad = .FALSE.
ENDIF
IF(Furnace(FurnaceNum)%NumOfSpeedCooling > 0) THEN
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, &
QZnReq, MoistureLoad, PartLoadRatio)
! CALL SetOnOffMassFlowRateVSCoil(FurnaceNum, Furnace(FurnaceNum)%ControlZoneNum, FirstHVACIteration, &
! AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
ELSE
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad,PartLoadRatio)
END IF
END IF
ELSE IF(SensibleOutput .GT. QZnReq)THEN
! If the net heating capacity meets the zone heating load but does not overshoot, turn off heating
QZnReq = 0.0d0
HeatingLoad = .FALSE.
IF(Furnace(FurnaceNum)%NumOfSpeedCooling > 0) THEN
! CALL SetOnOffMassFlowRateVSCoil(FurnaceNum, Furnace(FurnaceNum)%ControlZoneNum, FirstHVACIteration, &
! AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, &
OpMode, QZnReq, MoistureLoad, PartLoadRatio)
ELSE
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad,PartLoadRatio)
END IF
END IF
! the net heating capacity just offsets the heating load, turn off heating
ELSE IF (SensibleOutput .GT. 0.0d0 .AND. QToHeatSetPt .GT. 0.0d0 .AND. &
ABS(SensibleOutput - QToHeatSetPt) .LT. (Small5WLoad/Furnace(FurnaceNum)%ControlZoneMassFlowFrac))THEN
HeatingLoad = .FALSE.
END IF ! SensibleOutput .GT. 0.0d0 .AND. QToCoolSetPt .GT. 0.0d0
END IF ! Furnace(FurnaceNum)%ControlZoneMassFlowFrac .GT. 0.0d0
ZoneLoad = QZnReq
END IF ! OpMode .EQ. ContFanCycCoil
! EMS override point
IF (Furnace(FurnaceNum)%EMSOverrideSensZoneLoadRequest) ZoneLoad = Furnace(FurnaceNum)%EMSSensibleZoneLoadValue
IF (Furnace(FurnaceNum)%EMSOverrideMoistZoneLoadRequest) MoistureLoad = Furnace(FurnaceNum)%EMSMoistureZoneLoadValue
IF (Furnace(FurnaceNum)%EMSOverrideSensZoneLoadRequest .OR. Furnace(FurnaceNum)%EMSOverrideMoistZoneLoadRequest) THEN
IF ((ZoneLoad /= 0.0D0) .AND. (Furnace(FurnaceNum)%EMSOverrideSensZoneLoadRequest)) THEN
PartLoadRatio = 1.0D0
ELSEIF ((MoistureLoad /= 0.0D0) .AND. (Furnace(FurnaceNum)%EMSOverrideMoistZoneLoadRequest)) THEN
PartLoadRatio = 1.0D0
ELSE
PartLoadRatio = 0.0D0
ENDIF
IF(Furnace(FurnaceNum)%NumOfSpeedCooling > 0) THEN
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, &
QZnReq, MoistureLoad, PartLoadRatio)
! CALL SetOnOffMassFlowRateVSCoil(FurnaceNum, Furnace(FurnaceNum)%ControlZoneNum, FirstHVACIteration, &
! AirLoopNum, OnOffAirFlowRatio, OpMode, QZnReq, MoistureLoad, PartLoadRatio)
ELSE
CALL SetOnOffMassFlowRate(FurnaceNum, AirLoopNum, OnOffAirFlowRatio, OpMode, ZoneLoad, MoistureLoad,PartLoadRatio)
END IF
ENDIF
! AirflowNetwork global variable
LoopHeatingCoilMaxRTF = 0.0d0
RETURN
END SUBROUTINE InitFurnace