Nodes of different colours represent the following:
Solid arrows point from a parent (sub)module to the submodule which is descended from it. Dashed arrows point from a module being used to the module or program unit using it. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | PTUnitNum | |||
logical, | intent(in) | :: | FirstHVACIteration | |||
integer, | intent(in) | :: | CompOp | |||
integer, | intent(in) | :: | OpMode | |||
real(kind=r64), | intent(in) | :: | QZnReq | |||
real(kind=r64), | intent(in) | :: | QLatReq | |||
integer, | intent(in) | :: | ZoneNum | |||
integer, | intent(out) | :: | SpeedNum | |||
real(kind=r64), | intent(out) | :: | SpeedRatio | |||
real(kind=r64), | intent(out) | :: | PartLoadFrac | |||
real(kind=r64), | intent(inout) | :: | OnOffAirFlowRatio | |||
real(kind=r64), | intent(inout) | :: | SupHeaterLoad | |||
logical, | intent(in) | :: | HXUnitOn |
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed arrows point from an interface to procedures which implement that interface. This could include the module procedures in a generic interface or the implementation in a submodule of an interface in a parent module. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed arrows point from an interface to procedures which implement that interface. This could include the module procedures in a generic interface or the implementation in a submodule of an interface in a parent module. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
SUBROUTINE ControlVSHPOutput(PTUnitNum, FirstHVACIteration,CompOp,OpMode,&
QZnReq, QLatReq, ZoneNum,SpeedNum,SpeedRatio,PartLoadFrac, &
OnOffAirFlowRatio,SupHeaterLoad, HXUnitOn )
! SUBROUTINE INFORMATION:
! AUTHOR Bo Shen, based on HVACMultiSpeedHeatPump:ControlMSHPOutput
! DATE WRITTEN March, 2012
! MODIFIED na
! RE-ENGINEERED
! PURPOSE OF THIS SUBROUTINE:
! Determine the part load fraction at low speed, and speed ratio at high speed for this time step.
! METHODOLOGY EMPLOYED:
! Use RegulaFalsi technique to iterate on part-load ratio until convergence is achieved.
! REFERENCES:
! na
! USE STATEMENTS:
USE General, ONLY: SolveRegulaFalsi, RoundSigDigits, TrimSigDigits
USE DataGlobals, ONLY: WarmUpFlag,CurrentTime
USE HeatingCoils, ONLY: SimulateHeatingCoilComponents
USE Psychrometrics, ONLY: PsyCpAirFnWTdb
USE SteamCoils, ONLY: SimulateSteamCoilComponents
USE WaterCoils, ONLY: SimulateWaterCoilComponents
USE PlantUtilities, ONLY: SetComponentFlowRate
USE DataEnvironment, ONLY: OutDryBulbTemp
USE DataZoneEnergyDemands, ONLY: CurDeadbandOrSetback
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! SUBROUTINE ARGUMENT DEFINITIONS:
INTEGER, INTENT (IN) :: PTUnitNum ! Unit index in fan coil array
LOGICAL, INTENT (IN) :: FirstHVACIteration ! flag for 1st HVAC iteration in the time step
INTEGER, INTENT (IN) :: CompOp ! compressor operation; 1=on, 0=off
INTEGER, INTENT (IN) :: OpMode ! operating mode: CycFanCycCoil | ContFanCycCoil
INTEGER, INTENT (OUT) :: SpeedNum ! Speed number
REAL(r64) , INTENT (IN) :: QZnReq ! cooling or heating output needed by zone [W]
REAL(r64) , INTENT (IN) :: QLatReq ! latent cooling output needed by zone [W]
INTEGER, INTENT (IN) :: ZoneNum ! Index to zone number
REAL(r64) , INTENT (OUT) :: SpeedRatio ! unit speed ratio for DX coils
REAL(r64) , INTENT (OUT) :: PartLoadFrac ! unit part load fraction
REAL(r64) , INTENT (INOUT) :: OnOffAirFlowRatio ! ratio of compressor ON airflow to AVERAGE airflow over timestep
REAL(r64) , INTENT (INOUT) :: SupHeaterLoad ! Supplemental heater load [W]
LOGICAL, INTENT (IN) :: HXUnitOn ! flag to enable heat exchanger
! SUBROUTINE PARAMETER DEFINITIONS:
!
INTEGER, PARAMETER :: MaxIte = 500 ! maximum number of iterations
REAL(r64), PARAMETER :: MinPLF = 0.0d0 ! minimum part load factor allowed
! INTERFACE BLOCK SPECIFICATIONS
! na
! DERIVED TYPE DEFINITIONS
! na
! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
REAL(r64) :: FullOutput ! unit full output when compressor is operating [W]
REAL(r64) :: LowOutput ! unit full output at low speed [W]
REAL(r64) :: TempOutput ! unit output when iteration limit exceeded [W]
REAL(r64) :: NoCompOutput ! output when no active compressor [W]
REAL(r64) :: LatOutput ! latent capacity output
REAL(r64) :: ErrorToler ! error tolerance
INTEGER :: SolFla ! Flag of RegulaFalsi solver
REAL(r64), DIMENSION(11) :: Par ! Parameters passed to RegulaFalsi
REAL(r64) :: CpAir ! air specific heat
REAL(r64) :: QCoilActual ! coil load actually delivered returned to calling component
INTEGER :: i ! Speed index
INTEGER,SAVE :: ErrCountCyc=0 ! Counter used to minimize the occurrence of output warnings
INTEGER,SAVE :: ErrCountVar=0 ! Counter used to minimize the occurrence of output warnings
REAL(r64) :: mdot ! coil fluid mass flow rate (kg/s)
! FLOW
SupHeaterLoad = 0.0d0
PartLoadFrac = 0.0d0
SpeedRatio = 0.0d0
SpeedNum = 1
LatOutput = 0.0d0
ErrorToler = 0.001d0 !Error tolerance for convergence from input deck
IF (GetCurrentScheduleValue(PTUnit(PTUnitNum)%SchedPtr) .EQ. 0.0d0) RETURN
! Get result when DX coil is off
CALL CalcVarSpeedHeatPump(PTUnitNum,ZoneNum, FirstHVACIteration,CompOp,SpeedNum,SpeedRatio,PartLoadFrac,NoCompOutput, LatOutput, &
QZnReq, QLatReq, OnOffAirFlowRatio,SupHeaterLoad, HXUnitOn)
! If cooling and NoCompOutput < QZnReq, the coil needs to be off
! If heating and NoCompOutput > QZnReq, the coil needs to be off
IF ((QZnReq < (-1.d0*SmallLoad) .AND. NoCompOutput < QZnReq) .OR. (QZnReq > SmallLoad .AND. NoCompOutput > QZnReq) &
.OR. (ABS(QZnReq) <= SmallLoad .AND. ABS(QLatReq) <= SmallLoad ) .OR. CurDeadbandOrSetback(ZoneNum)) THEN
RETURN
END IF
! Get full load result
PartLoadFrac = 1.0d0
SpeedRatio = 1.0d0
If (PTUnit(PTUnitNum)%HeatCoolMode == HeatingMode) Then
IF (PTUnit(PTUnitNum)%UnitType_Num .EQ. PTACUnit) THEN
SpeedNum = PTUnit(PTUnitNum)%NumOfSpeedCooling
ELSE
SpeedNum = PTUnit(PTUnitNum)%NumOfSpeedHeating
END IF
Else If (PTUnit(PTUnitNum)%HeatCoolMode == CoolingMode) Then
SpeedNum = PTUnit(PTUnitNum)%NumOfSpeedCooling
ELSE
SpeedNum = 1
PartLoadFrac = 0.0d0
End If
CALL CalcVarSpeedHeatPump(PTUnitNum,ZoneNum, FirstHVACIteration,CompOp,SpeedNum,SpeedRatio,PartLoadFrac,FullOutput, LatOutput, &
QZnReq, QLatReq, OnOffAirFlowRatio,SupHeaterLoad, HXUnitOn)
IF(QLatReq < 0.0d0 ) THEN !dehumidification mode
! ! If the QLatReq <= LatOutput the unit needs to run full out
IF (QLatReq <= LatOutput) THEN
PartLoadFrac = 1.0d0
SpeedRatio = 1.0d0
PTUnit(PTUnitNum)%CompPartLoadRatio = PartLoadFrac
PTUnit(PTUnitNum)%CompSpeedRatio = SpeedRatio
PTUnit(PTUnitNum)%CompSpeedNum = SpeedNum
RETURN
END IF
ErrorToler = 0.001d0 !Error tolerance for convergence from input deck
ELSE IF (QZnReq .LT. (-1.d0*SmallLoad) .AND. .NOT. CurDeadbandorSetback(ZoneNum)) THEN
! Since we are cooling, we expect FullOutput to be < 0 and FullOutput < NoCompOutput
! Check that this is the case; if not set PartLoadFrac = 0.0 (off) and return
IF (FullOutput >= 0.0d0 .OR. FullOutput >= NoCompOutput) THEN
PartLoadFrac = 0.0d0
SpeedRatio = 0.0d0
SpeedNum = 1
RETURN
END IF
! ! If the QZnReq <= FullOutput the unit needs to run full out
IF (QZnReq <= FullOutput) THEN
PartLoadFrac = 1.0d0
SpeedRatio = 1.0d0
PTUnit(PTUnitNum)%CompPartLoadRatio = PartLoadFrac
PTUnit(PTUnitNum)%CompSpeedRatio = SpeedRatio
PTUnit(PTUnitNum)%CompSpeedNum = SpeedNum
RETURN
END IF
ErrorToler = 0.001d0 !Error tolerance for convergence from input deck
ELSEIF (QZnReq > SmallLoad .AND. .NOT. CurDeadbandorSetback(ZoneNum)) THEN
! Since we are heating, we expect FullOutput to be > 0 and FullOutput > NoCompOutput
! Check that this is the case; if not set PartLoadFrac = 0.0 (off)
IF (FullOutput <= 0.0d0 .OR. FullOutput <= NoCompOutput) THEN
PartLoadFrac = 0.0d0
SpeedRatio = 0.0d0
SpeedNum = 1
! may need supplemental heating so don't return in heating mode
END IF
IF (QZnReq >= FullOutput) THEN
PartLoadFrac = 1.0d0
SpeedRatio = 1.0d0
! may need supplemental heating so don't return in heating mode
END IF
ErrorToler = 0.001d0 !Error tolerance for convergence from input deck
ELSE ! no load
PartLoadFrac = 0.0d0
SpeedRatio = 0.0d0
SpeedNum = 1
END IF
! Calculate the part load fraction
IF (((QZnReq .GT. SmallLoad .AND. QZnReq < FullOutput) .OR. (QZnReq .LT. (-1.d0*SmallLoad) .AND. QZnReq > FullOutput) &
.OR. (QLatReq < (-1.d0*SmallLoad))) .AND. .NOT. CurDeadbandorSetback(ZoneNum)) THEN
Par(1) = PTUnitNum
Par(2) = ZoneNum
IF (FirstHVACIteration) THEN
Par(3) = 1.0d0
ELSE
Par(3) = 0.0d0
END IF
Par(4) = OpMode
Par(5) = QZnReq
Par(6) = OnOffAirFlowRatio
Par(7) = SupHeaterLoad
Par(9) = CompOp
Par(10) = 1.0d0
IF(HXUnitOn)THEN
Par(11) = 1.0d0
ELSE
Par(11) = 0.0d0
END IF
! Check whether the low speed coil can meet the load or not
CALL CalcVarSpeedHeatPump(PTUnitNum, ZoneNum, FirstHVACIteration,CompOp,1, 0.0d0, 1.0d0,LowOutput, LatOutput, &
QZnReq, QLatReq, OnOffAirFlowRatio,SupHeaterLoad, HXUnitOn)
IF (((QZnReq .GT. SmallLoad .AND. QZnReq <= LowOutput) .OR. (QZnReq .LT. (-1.d0*SmallLoad) .AND. QZnReq >= LowOutput) &
.OR. (QLatReq < (-1.d0*SmallLoad) .AND. QLatReq > LatOutput)) .AND. .NOT. CurDeadbandorSetback(ZoneNum)) THEN
SpeedRatio = 0.0d0
SpeedNum = 1
IF(QLatReq < 0.0d0) THEN !calculate latent heat residual
Par(10) = 0.0d0
Par(5) = QLatReq
END IF
CALL SolveRegulaFalsi(ErrorToler, MaxIte, SolFla, PartLoadFrac, VSHPCyclingResidual, 0.0d0, 1.0d0, Par)
IF (SolFla == -1) THEN
If ( .NOT. WarmupFlag) Then
IF (ErrCountCyc .eq. 0) THEN
ErrCountCyc = ErrCountCyc+1
CALL ShowWarningError('Iteration limit exceeded calculating VS WSHP unit cycling ratio, for unit='// &
TRIM(PTUnit(PTUnitNum)%Name))
CALL ShowContinueErrorTimeStamp('Cycling ratio returned='//RoundSigDigits(PartLoadFrac,2))
Else
ErrCountCyc = ErrCountCyc+1
CALL ShowRecurringWarningErrorAtEnd(TRIM(PTUnit(PTUnitNum)%Name)//'":'//&
' Iteration limit warning exceeding calculating DX unit cycling ratio continues...' &
,PTUnit(PTUnitNum)%ErrIndexCyc , PartLoadFrac, PartLoadFrac)
End If
End If
ELSE IF (SolFla == -2) THEN
CALL ShowFatalError('VS WSHP unit cycling ratio calculation failed: cycling limits exceeded, for unit='// &
TRIM(PTUnit(PTUnitNum)%Name))
END IF
Else
! Check to see which speed to meet the load
PartLoadFrac = 1.0d0
SpeedRatio = 1.0d0
! Cooling
If (((QZnReq .LT. (-1.d0*SmallLoad)) .OR. (QLatReq < (-1.d0*SmallLoad))).AND. .NOT. CurDeadbandorSetback(ZoneNum)) Then
DO I=2,PTUnit(PTUnitNum)%NumOfSpeedCooling
CALL CalcVarSpeedHeatPump(PTUnitNum,ZoneNum, FirstHVACIteration,CompOp,I,SpeedRatio,PartLoadFrac,TempOutput, LatOutput,&
QZnReq,QLatReq, OnOffAirFlowRatio,SupHeaterLoad, HXUnitOn )
IF(QLatReq < 0.0d0) THEN
IF(QLatReq > LatOutput) THEN
SpeedNum = I
Exit
END IF
ELSE IF (QZnReq >= TempOutput) THEN
SpeedNum = I
Exit
END IF
END DO
ELSE
DO I=2,PTUnit(PTUnitNum)%NumOfSpeedHeating
CALL CalcVarSpeedHeatPump(PTUnitNum,ZoneNum, FirstHVACIteration,CompOp,I,SpeedRatio,PartLoadFrac,TempOutput, LatOutput,&
QZnReq,QLatReq,OnOffAirFlowRatio,SupHeaterLoad, HXUnitOn )
If (QZnReq <= TempOutput) Then
SpeedNum = I
Exit
End If
END DO
END IF
Par(8) = SpeedNum
IF(QLatReq < (-1.d0*SmallLoad)) THEN !calculate latent heat residual
Par(10) = 0.0d0
Par(5) = QLatReq
END IF
CALL SolveRegulaFalsi(ErrorToler, MaxIte, SolFla, SpeedRatio, VSHPSpeedResidual, 1.0d-10, 1.0d0, Par)
IF (SolFla == -1) THEN
If ( .NOT. WarmupFlag) Then
IF (ErrCountVar .eq. 0) THEN
ErrCountVar = ErrCountVar+1
CALL ShowWarningError('Iteration limit exceeded calculating VS WSHP unit speed ratio, for unit='// &
TRIM(PTUnit(PTUnitNum)%Name))
CALL ShowContinueErrorTimeStamp('Speed ratio returned=['//trim(RoundSigDigits(SpeedRatio,2))//'], Speed number =' &
//trim(RoundSigDigits(SpeedNum,0)))
Else
ErrCountVar = ErrCountVar+1
CALL ShowRecurringWarningErrorAtEnd(TRIM(PTUnit(PTUnitNum)%Name)//'":'//&
' Iteration limit warning exceeding calculating DX unit speed ratio continues...' &
,PTUnit(PTUnitNum)%ErrIndexVar, SpeedRatio, SpeedRatio)
End If
End If
ELSE IF (SolFla == -2) THEN
CALL ShowFatalError('VS WSHP unit compressor speed calculation failed: speed limits exceeded, for unit='// &
TRIM(PTUnit(PTUnitNum)%Name))
END IF
End If
End If
! if the DX heating coil cannot meet the load, trim with supplemental heater
! occurs with constant fan mode when compressor is on or off
! occurs with cycling fan mode when compressor PLR is equal to 1
IF (HeatingLoad .AND. QZnReq .GT. FullOutput .AND. PTUnit(PTUnitNum)%SuppHeatCoilIndex .GT. 0)THEN
PartLoadFrac = 1.0d0
SpeedRatio = 1.0d0
IF(PTUnit(PTUnitNum)%NumOfSpeedHeating > 0) &
SpeedNum = PTUnit(PTUnitNum)%NumOfSpeedHeating !maximum heating speed, avoid zero
IF (OutDryBulbTemp .LE. PTUnit(PTUnitNum)%MaxOATSupHeat) THEN
SupHeaterLoad = QZnReq - FullOutput
ELSE
SupHeaterLoad = 0.0d0
END IF
CALL CalcVarSpeedHeatPump(PTUnitNum, ZoneNum, FirstHVACIteration,CompOp,&
SpeedNum,SpeedRatio,PartLoadFrac,TempOutput, LatOutput,QZnReq, &
QLatReq, OnOffAirFlowRatio,SupHeaterLoad, HXUnitOn)
END IF
! check the outlet of the supplemental heater to be lower than the maximum supplemental heater supply air temperature
IF(PTUnit(PTUnitNum)%SuppHeatCoilIndex .GT. 0)THEN
IF (Node(PTUnit(PTUnitNum)%AirOutNode)%Temp .GT. PTUnit(PTUnitNum)%MaxSATSupHeat .AND. SupHeaterLoad .GT. 0.0d0) THEN
! If supply air temperature is to high, turn off the supplemental heater to recalculate the outlet temperature
SupHeaterLoad = 0.0d0
Select Case (PTUnit(PTUnitNum)%SuppHeatCoilType_Num)
Case (Coil_HeatingGas,Coil_HeatingElectric )
CALL SimulateHeatingCoilComponents(PTUnit(PTUnitNum)%SuppHeatCoilName,FirstHVACIteration, &
SupHeaterLoad, PTUnit(PTUnitNum)%SuppHeatCoilIndex)
Case (Coil_HeatingWater)
mdot = 0.d0
Call SetComponentFlowRate( mdot , &
PTUnit(PTUnitNum)%HotWaterControlNode, &
PTUnit(PTUnitNum)%PlantCoilOutletNode, &
PTUnit(PTUnitNum)%LoopNum, &
PTUnit(PTUnitNum)%LoopSide, &
PTUnit(PTUnitNum)%BranchNum, &
PTUnit(PTUnitNum)%CompNum)
CALL SimulateWaterCoilComponents(PTUnit(PTUnitNum)%SuppHeatCoilName,FirstHVACIteration, &
PTUnit(PTUnitNum)%SuppHeatCoilIndex, SupHeaterLoad, &
PTUnit(PTUnitNum)%OpMode, PartLoadFrac)
Case (Coil_HeatingSteam)
mdot = 0.d0
CALL SetComponentFlowRate( mdot , &
PTUnit(PTUnitNum)%HWCoilSteamInletNode, &
PTUnit(PTUnitNum)%PlantCoilOutletNode, &
PTUnit(PTUnitNum)%LoopNum, &
PTUnit(PTUnitNum)%LoopSide, &
PTUnit(PTUnitNum)%BranchNum, &
PTUnit(PTUnitNum)%CompNum)
CALL SimulateSteamCoilComponents(PTUnit(PTUnitNum)%SuppHeatCoilName, &
FirstHVACIteration, SupHeaterLoad, &
PTUnit(PTUnitNum)%SuppHeatCoilIndex )
END Select
! If the outlet temperature is below the maximum supplemental heater supply air temperature, reduce the load passed to
! the supplemental heater, otherwise leave the supplemental heater off. If the supplemental heater is to be turned on,
! use the outlet conditions when the supplemental heater was off (CALL above) as the inlet conditions for the calculation
! of supplemental heater load to just meet the maximum supply air temperature from the supplemental heater.
IF (Node(PTUnit(PTUnitNum)%AirOutNode)%Temp .LT. PTUnit(PTUnitNum)%MaxSATSupHeat) THEN
CpAir = PsyCpAirFnWTdb(Node(PTUnit(PTUnitNum)%AirOutNode)%HumRat,Node(PTUnit(PTUnitNum)%AirOutNode)%Temp)
SupHeaterLoad = Node(PTUnit(PTUnitNum)%AirInNode)%MassFlowRate * CpAir * &
(PTUnit(PTUnitNum)%MaxSATSupHeat - Node(PTUnit(PTUnitNum)%AirOutNode)%Temp)
ELSE
SupHeaterLoad = 0.0d0
END IF
END IF
END IF
PTUnit(PTUnitNum)%CompPartLoadRatio = PartLoadFrac
PTUnit(PTUnitNum)%CompSpeedRatio = SpeedRatio
PTUnit(PTUnitNum)%CompSpeedNum = SpeedNum
RETURN
END SUBROUTINE ControlVSHPOutput