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) | :: | FurnaceNum | |||
logical, | intent(in) | :: | FirstHVACIteration | |||
integer, | intent(in) | :: | CompOp | |||
integer, | intent(in) | :: | OpMode | |||
real(kind=r64), | intent(inout) | :: | QZnReq | |||
real(kind=r64), | intent(inout) | :: | 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 |
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(FurnaceNum,FirstHVACIteration,CompOp,OpMode,QZnReq,QLatReq,ZoneNum,SpeedNum, &
SpeedRatio,PartLoadFrac,OnOffAirFlowRatio,SupHeaterLoad)
! 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 DataEnvironment, ONLY: OutDryBulbTemp
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! SUBROUTINE ARGUMENT DEFINITIONS:
INTEGER, INTENT (IN) :: FurnaceNum ! Unit index of engine driven heat pump
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 (INOUT) :: QZnReq ! cooling or heating output needed by zone [W]
REAL(r64) , INTENT (INOUT) :: 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]
! 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(10) :: 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
! 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
!dehumidification load has the priority
IF((GetCurrentScheduleValue(Furnace(FurnaceNum)%SchedPtr) .gt. 0.0d0 .and. CoolingLoad) .AND. &
(Furnace(FurnaceNum)%Humidistat .AND. &
Furnace(FurnaceNum)%DehumidControlType_Num == DehumidControl_CoolReheat .and. &
(QLatReq.lt.0.0d0))) THEN
QZnReq = 0.0d0
ELSE
QLatReq = 0.0d0
END IF
IF (GetCurrentScheduleValue(Furnace(FurnaceNum)%SchedPtr) .EQ. 0.0d0) RETURN
! Get result when DX coil is off
SupHeaterLoad = 0.0d0
CALL CalcVarSpeedHeatPump(FurnaceNum,FirstHVACIteration,CompOp,SpeedNum,SpeedRatio,PartLoadFrac,NoCompOutput, LatOutput, &
0.0d0, 0.0d0, OnOffAirFlowRatio,SupHeaterLoad)
! 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. (QLatReq < (-1.d0*SmallLoad) .AND. LatOutput < QLatReq)) THEN
RETURN
END IF
! Get full load result
PartLoadFrac = 1.0d0
SpeedRatio = 1.0d0
If (Furnace(FurnaceNum)%HeatCoolMode == HeatingMode) Then
IF (Furnace(FurnaceNum)%FurnaceType_Num == UnitarySys_HeatCool) THEN
SpeedNum = Furnace(FurnaceNum)%NumOfSpeedCooling
ELSE
SpeedNum = Furnace(FurnaceNum)%NumOfSpeedHeating
END IF
Else If (Furnace(FurnaceNum)%HeatCoolMode == CoolingMode) Then
SpeedNum = Furnace(FurnaceNum)%NumOfSpeedCooling
ELSE
SpeedNum = 1
PartLoadFrac = 0.0d0
End If
CALL CalcVarSpeedHeatPump(FurnaceNum,FirstHVACIteration,CompOp,SpeedNum,SpeedRatio,PartLoadFrac,FullOutput, LatOutput, &
QZnReq, QLatReq, OnOffAirFlowRatio,SupHeaterLoad)
IF(QLatReq < (-1.d0*SmallLoad) ) THEN !dehumidification mode
! ! If the QLatReq <= LatOutput the unit needs to run full out
IF (QLatReq <= LatOutput) THEN
PartLoadFrac = 1.0d0
SpeedRatio = 1.0d0
Furnace(FurnaceNum)%CompPartLoadRatio = PartLoadFrac
Furnace(FurnaceNum)%CompSpeedRatio = SpeedRatio
Furnace(FurnaceNum)%CompSpeedNum = SpeedNum
RETURN
END IF
ErrorToler = 0.001d0 !Error tolerance for convergence from input deck
ELSE IF (QZnReq .LT. (-1.d0*SmallLoad)) 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
Furnace(FurnaceNum)%CompPartLoadRatio = PartLoadFrac
Furnace(FurnaceNum)%CompSpeedRatio = SpeedRatio
Furnace(FurnaceNum)%CompSpeedNum = SpeedNum
RETURN
END IF
ErrorToler = 0.001d0 !Error tolerance for convergence from input deck
ELSE
! 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
END IF
IF ((QZnReq .GT. SmallLoad .AND. QZnReq < FullOutput) .OR. (QZnReq .LT. (-1.d0*SmallLoad) .AND. QZnReq > FullOutput) &
.OR. (QLatReq < (-1.d0*SmallLoad)) ) THEN
Par(1) = FurnaceNum
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
! Check whether the low speed coil can meet the load or not
CALL CalcVarSpeedHeatPump(FurnaceNum, FirstHVACIteration,CompOp,1, 0.0d0, 1.0d0,LowOutput, LatOutput, &
QZnReq, QLatReq, OnOffAirFlowRatio,SupHeaterLoad)
IF ((QZnReq .GT. SmallLoad .AND. QZnReq <= LowOutput) .OR. (QZnReq .LT. (-1.d0*SmallLoad) .AND. QZnReq >= LowOutput) &
.OR. (QLatReq < (-1.d0*SmallLoad) .AND. QLatReq > LatOutput)) THEN
! Calculate the part load fraction
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(Furnace(FurnaceNum)%Name))
CALL ShowContinueErrorTimeStamp('Cycling ratio returned='//RoundSigDigits(PartLoadFrac,2))
Else
ErrCountCyc = ErrCountCyc+1
CALL ShowRecurringWarningErrorAtEnd(TRIM(Furnace(FurnaceNum)%Name)//'":'//&
' Iteration limit warning exceeding calculating DX unit cycling ratio continues...' &
,Furnace(FurnaceNum)%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(Furnace(FurnaceNum)%Name))
END IF
Else
! Check to see which speed to meet the load
PartLoadFrac = 1.0d0
SpeedRatio = 1.0d0
If ((QZnReq .LT. (-1.d0*SmallLoad)) .OR. (QLatReq < (-1.d0*SmallLoad))) Then ! Cooling
DO I=2,Furnace(FurnaceNum)%NumOfSpeedCooling
CALL CalcVarSpeedHeatPump(FurnaceNum,FirstHVACIteration,CompOp,I,SpeedRatio,PartLoadFrac,TempOutput, LatOutput,&
QZnReq,QLatReq, OnOffAirFlowRatio,SupHeaterLoad)
IF(QLatReq < (-1.d0*SmallLoad)) 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,Furnace(FurnaceNum)%NumOfSpeedHeating
CALL CalcVarSpeedHeatPump(FurnaceNum,FirstHVACIteration,CompOp,I,SpeedRatio,PartLoadFrac,TempOutput, LatOutput,&
QZnReq,QLatReq,OnOffAirFlowRatio,SupHeaterLoad)
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(Furnace(FurnaceNum)%Name))
CALL ShowContinueErrorTimeStamp('Speed ratio returned=['//trim(RoundSigDigits(SpeedRatio,2))//'], Speed number =' &
//trim(RoundSigDigits(SpeedNum,0)))
Else
ErrCountVar = ErrCountVar+1
CALL ShowRecurringWarningErrorAtEnd(TRIM(Furnace(FurnaceNum)%Name)//'":'//&
' Iteration limit warning exceeding calculating DX unit speed ratio continues...' &
,Furnace(FurnaceNum)%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(Furnace(FurnaceNum)%Name))
END IF
End If
End If
! if the 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 ((QZnReq .GT. SmallLoad .AND. QZnReq .GT. FullOutput) .AND. (Furnace(FurnaceNum)%SuppHeatCoilIndex /= 0))THEN
PartLoadFrac = 1.0d0
SpeedRatio = 1.0d0
IF(Furnace(FurnaceNum)%NumOfSpeedHeating > 0) &
SpeedNum = Furnace(FurnaceNum)%NumOfSpeedHeating !maximum heating speed, avoid zero for cooling only mode
IF(OutDryBulbTemp .LE. Furnace(FurnaceNum)%MaxOATSuppHeat)THEN
SupHeaterLoad = QZnReq - FullOutput
ELSE
SupHeaterLoad = 0.0d0
END IF
CALL CalcVarSpeedHeatPump(FurnaceNum,FirstHVACIteration,CompOp,SpeedNum,SpeedRatio,PartLoadFrac,TempOutput, LatOutput,QZnReq, &
QLatReq, OnOffAirFlowRatio,SupHeaterLoad)
END IF
! check the outlet of the supplemental heater to be lower than the maximum supplemental heater supply air temperature
IF (Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%Temp .GT. Furnace(FurnaceNum)%DesignMaxOutletTemp .AND. &
SupHeaterLoad .GT. 0.0d0) THEN
! If the supply air temperature is to high, turn off the supplemental heater to recalculate the outlet temperature
CALL CalcNonDXHeatingCoils(FurnaceNum,.TRUE.,FirstHVACIteration,0.0d0,OpMode,QCoilActual)
! 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(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%Temp .LT. Furnace(FurnaceNum)%DesignMaxOutletTemp) THEN
CpAir = PsyCpAirFnWTdb(Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%HumRat, &
Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%Temp)
SupHeaterLoad = Node(Furnace(FurnaceNum)%FurnaceInletNodeNum)%MassFlowRate * CpAir * &
(Furnace(FurnaceNum)%DesignMaxOutletTemp - Node(Furnace(FurnaceNum)%FurnaceOutletNodeNum)%Temp)
ELSE
SupHeaterLoad = 0.0d0
END IF
END IF
!prepare module level output
Furnace(FurnaceNum)%CompPartLoadRatio = PartLoadFrac
Furnace(FurnaceNum)%CompSpeedRatio = SpeedRatio
Furnace(FurnaceNum)%CompSpeedNum = SpeedNum
Furnace(FurnaceNum)%CoolingCoilLatentDemand = ABS(QLatReq)
IF (Furnace(FurnaceNum)%OpMode .EQ. ContFanCycCoil) THEN
Furnace(FurnaceNum)%FanPartLoadRatio = 1.0d0
ELSE
Furnace(FurnaceNum)%FanPartLoadRatio = PartLoadFrac
END IF
RETURN
END SUBROUTINE ControlVSHPOutput