SUBROUTINE CalcLowTempCFloRadiantSystem(RadSysNum,LoadMet)
! SUBROUTINE INFORMATION:
! AUTHOR Rick Strand
! DATE WRITTEN August 2003
! MODIFIED na
! RE-ENGINEERED na
! PURPOSE OF THIS SUBROUTINE:
! This subroutine does all of the stuff that is necessary to simulate
! a constant flow low temperature hydronic radiant heating/cooling system.
! Calls are made to appropriate subroutines either in this module or
! outside of it.
! METHODOLOGY EMPLOYED:
! Similar in many aspects to the hydronic (variable flow) radiant system
! except that flow rate through the radiant system is constant (based on
! the user schedule) and the inlet temperature is varied by injecting
! more or less fluid from the main loop to achieve the desired inlet
! temperature.
! REFERENCES:
! Other EnergyPlus modules
! IBLAST-QTF research program, completed in January 1995 (unreleased)
! Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
! Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
! of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
! Engineering.
! Seem, J.E. 1986. "Heat Transfer in Buildings", Ph.D. dissertation, University
! of Wisconsin-Madison.
! USE STATEMENTS:
USE DataZoneEnergyDemands
USE DataEnvironment, ONLY : EnvironmentName, CurMnDy
USE DataHeatBalance, ONLY : MRT, Zone, ZoneData
USE DataHeatBalFanSys, ONLY : MAT
USE DataHVACGlobals, ONLY : SmallLoad
USE DataBranchAirLoopPlant, ONLY : MassFlowTolerance
USE DataLoopNode, ONLY : Node
USE FluidProperties, ONLY : GetSpecificHeatGlycol
USE ScheduleManager, ONLY : GetCurrentScheduleValue
USE General, ONLY : TrimSigDigits
USE PlantUtilities, ONLY : SetComponentFlowRate
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! SUBROUTINE ARGUMENT DEFINITIONS:
INTEGER, INTENT(IN) :: RadSysNum ! name of the low temperature radiant system
REAL(r64), INTENT(INOUT) :: LoadMet ! load met by the radiant system, in Watts
! SUBROUTINE PARAMETER DEFINITIONS:
REAL(r64), PARAMETER :: LowCpFluidValue = 100.d0 ! lowest allowed Cp fluid value (to avoid dividing by zero) [J/kg-K]
! INTERFACE BLOCK SPECIFICATIONS
! na
! DERIVED TYPE DEFINITIONS
! na
! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
REAL(r64) :: CpFluid ! Specific heat of the fluid in the radiant system
REAL(r64) :: InjectFlowRate ! Calculated injection flow rate that will meet the inlet temperature requirement
LOGICAL :: Iteration ! FALSE when a normal solution, TRUE when it is a solution where we must also find the inlet temp
INTEGER :: LoopInNode ! Node on the loop that is the inlet to the constant flow radiant system
REAL(r64) :: OffTempCool ! temperature at which the cooling shuts down
REAL(r64) :: OffTempHeat ! temperature at which the heating shuts down
REAL(r64) :: PumpPartLoadRat ! Pump part load ratio (based on user schedule, or 1.0 for no schedule)
REAL(r64) :: PumpTempRise ! Temperature rise of the fluid as it passes through the pump
REAL(r64) :: QZnReq ! heating or cooling needed by zone [Watts]
REAL(r64) :: RadInTemp ! "Desired" radiant system water inlet temperature [Celsius]
REAL(r64) :: SetpointTemp ! temperature that will be used to control the radiant system [Celsius]
REAL(r64) :: SetpointTempHi ! Current high point in setpoint temperature range
REAL(r64) :: SetpointTempLo ! Current low point in setpoint temperature range
REAL(r64) :: ShaftPower ! Amount of power expended at the pump shaft
INTEGER :: SurfNum ! Surface number in the Surface derived type for a radiant system surface
INTEGER :: SurfNum2 ! Surface number in the Surface derived type for a radiant system surface
LOGICAL :: SysRunning ! TRUE when the system is running
REAL(r64) :: SysWaterInTemp ! Fluid temperature supplied from the loop
REAL(r64) :: WaterTempHi ! Current high point in water temperature range
REAL(r64) :: WaterTempLo ! Current low point in water temperature range
INTEGER :: ZoneNum ! number of zone being served
REAL(r64) :: mdot ! local temporary for water mass flow rate kg/s
! FLOW:
! initialize local variables
ZoneNum = CFloRadSys(RadSysNum)%ZonePtr
SysRunning = .TRUE. ! default to running and turn off only if not running
VarOffCond = .FALSE.
IF (GetCurrentScheduleValue(CFloRadSys(RadSysNum)%SchedPtr) <= 0) SysRunning = .FALSE.
IF (SysRunning) THEN ! Unit is probably on-->this section is intended to control the water
! mass flow rate being sent to the radiant system
! Set the current setpoint temperature (same procedure for either heating or cooling)
SELECT CASE (CFloRadSys(RadSysNum)%ControlType)
CASE (MATControl)
SetpointTemp = MAT(ZoneNum)
CASE (MRTControl)
SetpointTemp = MRT(ZoneNum)
CASE (OperativeControl)
SetpointTemp = 0.5d0*(MAT(ZoneNum)+MRT(ZoneNum))
CASE (ODBControl)
SetpointTemp = Zone(ZoneNum)%OutDryBulbTemp
CASE (OWBControl)
SetpointTemp = Zone(ZoneNum)%OutWetBulbTemp
CASE DEFAULT ! Should never get here
CALL ShowSevereError('Illegal control type in low temperature radiant system: '//TRIM(CFloRadSys(RadSysNum)%Name))
CALL ShowFatalError('Preceding condition causes termination.')
END SELECT
! Avoid problems when there is no heating or cooling control because the system only cools or heats
IF (CFloRadSys(RadSysNum)%HotCtrlHiTempSchedPtr > 0) THEN
OffTempHeat = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%HotCtrlHiTempSchedPtr)
ELSE
OffTempHeat = LowTempHeating
END IF
IF (CFloRadSys(RadSysNum)%ColdCtrlLoTempSchedPtr > 0) THEN
OffTempCool = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%ColdCtrlLoTempSchedPtr)
ELSE
OffTempCool = HighTempCooling
END IF
! Now actually decide what to do based on the setpoint temperature in relation to the control temperatures
IF (SetpointTemp < OffTempHeat) THEN ! HEATING MODE
OperatingMode = HeatingMode
IF (.NOT.CFloRadSys(RadSysNum)%HeatingSystem) THEN
SysRunning = .FALSE. ! Can't heat unless it's a heating system
ELSE ! It is a heating system so set all of the values for controls
SetpointTempHi = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%HotCtrlHiTempSchedPtr)
SetpointTempLo = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%HotCtrlLoTempSchedPtr)
IF (SetpointTempHi < SetpointTempLo) THEN
CALL ShowSevereError('Heating setpoint temperature mismatch in'//TRIM(CFloRadSys(RadSysNum)%Name))
CALL ShowContinueError('High setpoint temperature is less than low setpoint temperature--check your schedule input')
CALL ShowFatalError('Preceding condition causes termination.')
END IF
WaterTempHi = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%HotWaterHiTempSchedPtr)
WaterTempLo = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%HotWaterLoTempSchedPtr)
IF (WaterTempHi < WaterTempLo) THEN
CALL ShowSevereError('Heating water temperature mismatch in'//TRIM(CFloRadSys(RadSysNum)%Name))
CALL ShowContinueError('High water temperature is less than low water temperature--check your schedule input')
CALL ShowFatalError('Preceding condition causes termination.')
END IF
IF (SetpointTemp >= SetpointTempHi) THEN
! System is above high heating setpoint so we should be able to turn the system off
RadInTemp = WaterTempLo
SysRunning = .FALSE.
ELSE IF (SetpointTemp <= SetpointTempLo) THEN
! System is running with its highest inlet temperature
RadInTemp = WaterTempHi
ELSE
! Interpolate to obtain the current radiant system inlet temperature
RadInTemp = WaterTempHi - (WaterTempHi - WaterTempLo)*(SetpointTemp - SetpointTempLo)/(SetpointTempHi - SetpointTempLo)
END IF
END IF
ELSE IF (SetpointTemp > OffTempCool) THEN ! COOLING MODE
OperatingMode = CoolingMode
IF (.NOT.CFloRadSys(RadSysNum)%CoolingSystem) THEN
SysRunning = .FALSE. ! Can't cool unless it's a cooling system
ELSE ! It is a cooling system so set all of the values for controls
SetpointTempHi = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%ColdCtrlHiTempSchedPtr)
SetpointTempLo = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%ColdCtrlLoTempSchedPtr)
IF (SetpointTempHi < SetpointTempLo) THEN
CALL ShowSevereError('Cooling setpoint temperature mismatch in'//TRIM(CFloRadSys(RadSysNum)%Name))
CALL ShowContinueError('High setpoint temperature is less than low setpoint temperature--check your schedule input')
CALL ShowFatalError('Preceding condition causes termination.')
END IF
WaterTempHi = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%ColdWaterHiTempSchedPtr)
WaterTempLo = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%ColdWaterLoTempSchedPtr)
IF (WaterTempHi < WaterTempLo) THEN
CALL ShowSevereError('Cooling water temperature mismatch in'//TRIM(CFloRadSys(RadSysNum)%Name))
CALL ShowContinueError('High water temperature is less than low water temperature--check your schedule input')
CALL ShowFatalError('Preceding condition causes termination.')
END IF
IF (SetpointTemp <= SetpointTempLo) THEN
! System is below low cooling setpoint so we should be able to turn the system off
RadInTemp = WaterTempHi
SysRunning = .FALSE.
ELSE IF (SetpointTemp >= SetpointTempHi) THEN
! System is running with its lowest inlet temperature
RadInTemp = WaterTempLo
ELSE
! Interpolate to obtain the current radiant system inlet temperature
RadInTemp = WaterTempHi - (WaterTempHi - WaterTempLo)*(SetpointTemp - SetpointTempLo)/(SetpointTempHi - SetpointTempLo)
END IF
END IF
ELSE ! System is not running because the setpoint temperature is in the "deadband"
RadInTemp = SetpointTemp
SysRunning = .FALSE.
END IF
END IF
IF (SysRunning) THEN
CpFluid = GetSpecificHeatGlycol('WATER',RadInTemp,CFloRadSys(RadSysNum)%GlycolIndex,'CalcLowTempCFloRadiantSystem')
END IF
IF ((.NOT. SysRunning).OR.(CpFluid < LowCpFluidValue)) THEN
! Unit is off or has no load upon it OR CpFluid value is "zero" so
! set the flow rates to zero and then simulate the components with
! the no flow conditions
OperatingMode = NotOperating
CFloRadSys(RadSysNum)%WaterMassFlowRate = 0.0d0
CFloRadSys(RadSysNum)%WaterInjectionRate = 0.0d0
CFloRadSys(RadSysNum)%WaterRecircRate = 0.0d0
CFloRadSys(RadSysNum)%HeatPower = 0.0d0
CFloRadSys(RadSysNum)%CoolPower = 0.0d0
CFloRadSys(RadSysNum)%PumpPower = 0.0d0
CFloRadSys(RadSysNum)%PumpMassFlowRate = 0.0d0
CFloRadSys(RadSysNum)%PumpHeattoFluid = 0.0d0
DO SurfNum = 1, CFloRadSys(RadSysNum)%NumOfSurfaces
SurfNum2 = CFloRadSys(RadSysNum)%SurfacePtr(SurfNum)
QRadSysSource(SurfNum2) = 0.0D0
IF (Surface(SurfNum2)%ExtBoundCond > 0 .AND. Surface(SurfNum2)%ExtBoundCond /= SurfNum2) &
QRadSysSource(Surface(SurfNum2)%ExtBoundCond) = 0.0D0 ! Also zero the other side of an interzone
END DO
! turn off flow requests made during init because it is not actually running
IF (CFloRadSys(RadSysNum)%CWLoopNum > 0 ) THEN
mdot = 0.d0
CALL SetComponentFlowRate(mdot, &
CFloRadSys(RadSysNum)%ColdWaterInNode, &
CFloRadSys(RadSysNum)%ColdWaterOutNode, &
CFloRadSys(RadSysNum)%CWLoopNum, &
CFloRadSys(RadSysNum)%CWLoopSide, &
CFloRadSys(RadSysNum)%CWBranchNum, &
CFloRadSys(RadSysNum)%CWCompNum)
ENDIF
IF (CFloRadSys(RadSysNum)%HWLoopNum > 0 ) THEN
mdot = 0.d0
CALL SetComponentFlowRate(mdot, &
CFloRadSys(RadSysNum)%HotWaterInNode, &
CFloRadSys(RadSysNum)%HotWaterOutNode, &
CFloRadSys(RadSysNum)%HWLoopNum, &
CFloRadSys(RadSysNum)%HWLoopSide, &
CFloRadSys(RadSysNum)%HWBranchNum, &
CFloRadSys(RadSysNum)%HWCompNum )
ENDIF
ELSE ! (SysRunning) so simulate the system...
! Determine pump flow rate and pump heat addition
CFloRadSys(RadSysNum)%PumpMassFlowRate = CFloRadSys(RadSysNum)%WaterMassFlowRate ! Set in InitLowTempRadiantSystem
IF (CFloRadSys(RadSysNum)%VolFlowSchedPtr > 0) THEN
PumpPartLoadRat = GetCurrentScheduleValue(CFloRadSys(RadSysNum)%VolFlowSchedPtr)
ELSE
PumpPartLoadRat = 1.0d0
END IF
CFloRadSys(RadSysNum)%PumpPower = PumpPartLoadRat*CFloRadSys(RadSysNum)%NomPowerUse
ShaftPower = CFloRadSys(RadSysNum)%PumpPower * CFloRadSys(RadSysNum)%MotorEffic
! This adds the pump heat based on User input for the pump (same as in Pump module)
! We assume that all of the heat ends up in the fluid eventually since this is a closed loop.
CFloRadSys(RadSysNum)%PumpHeattoFluid = ShaftPower &
+( (CFloRadSys(RadSysNum)%PumpPower - ShaftPower) &
* CFloRadSys(RadSysNum)%FracMotorLossToFluid )
IF (CFloRadSys(RadSysNum)%PumpMassFlowRate > 0.d0) THEN
PumpTempRise = CFloRadSys(RadSysNum)%PumpHeattoFluid / (CFloRadSys(RadSysNum)%PumpMassFlowRate * CpFluid)
ELSE
PumpTempRise = 0.d0
ENDIF
LoopReqTemp = RadInTemp - PumpTempRise ! Temperature required at the inlet of the pump to meet the temperature request
IF (OperatingMode == HeatingMode) THEN
! in heating mode so shut down cold water flow request
IF (CFloRadSys(RadSysNum)%CWLoopNum > 0 ) THEN
mdot = 0.d0
CALL SetComponentFlowRate(mdot, &
CFloRadSys(RadSysNum)%ColdWaterInNode, &
CFloRadSys(RadSysNum)%ColdWaterOutNode, &
CFloRadSys(RadSysNum)%CWLoopNum, &
CFloRadSys(RadSysNum)%CWLoopSide, &
CFloRadSys(RadSysNum)%CWBranchNum, &
CFloRadSys(RadSysNum)%CWCompNum)
ENDIF
LoopInNode = CFloRadSys(RadSysNum)%HotWaterInNode
SysWaterInTemp = Node(LoopInNode)%Temp
Iteration = .FALSE.
IF ( (SysWaterInTemp >= LoopReqTemp) .AND. &
(Node(LoopInNode)%MassFlowRateMaxAvail >= CFloRadSys(RadSysNum)%WaterMassFlowRate) ) THEN
! Case 1: Adequate temperature and flow
! Best condition--loop inlet temperature greater than requested and we have enough flow.
! So, proceed assuming the RadInTemp requested by the controls and then figure out the
! mixing after the outlet radiant temperature is calculated.
CFloRadSys(RadSysNum)%WaterInletTemp = RadInTemp
CALL CalcLowTempCFloRadSysComps(RadSysNum,LoopInNode,Iteration,LoadMet)
! We now have inlet and outlet temperatures--we still need to set the flow rates
IF ((SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) /= 0.d0) THEN ! protect divide by zero
CFloRadSys(RadSysNum)%WaterInjectionRate = ( CFloRadSys(RadSysNum)%WaterMassFlowRate &
*(CFloRadSys(RadSysNum)%WaterInletTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) &
/(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) ) &
-( CFloRadSys(RadSysNum)%PumpHeattoFluid &
/(CpFluid*(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp)) )
ENDIF
CFloRadSys(RadSysNum)%WaterRecircRate = CFloRadSys(RadSysNum)%WaterMassFlowRate &
-CFloRadSys(RadSysNum)%WaterInjectionRate
ELSE IF ( (SysWaterInTemp < LoopReqTemp) .AND. &
(Node(LoopInNode)%MassFlowRateMaxAvail >= CFloRadSys(RadSysNum)%WaterMassFlowRate) ) THEN
! Case 2: Adequate flow but temperature too low
! Only thing to do is to reset the inlet temperature and assume that the loop will supply
! the entire flow to the component (no recirculation but potentially some bypass for the
! overall loop). There is no way we can meet the control temperature so don't even try.
CFloRadSys(RadSysNum)%WaterInletTemp = SysWaterInTemp + PumpTempRise
CALL CalcLowTempCFloRadSysComps(RadSysNum,LoopInNode,Iteration,LoadMet)
! We now have inlet and outlet temperatures--we still need to set the flow rates
IF ((SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) /= 0.d0) THEN ! protect divide by zero
CFloRadSys(RadSysNum)%WaterInjectionRate = ( CFloRadSys(RadSysNum)%WaterMassFlowRate &
*(CFloRadSys(RadSysNum)%WaterInletTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) &
/(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) ) &
-( CFloRadSys(RadSysNum)%PumpHeattoFluid &
/(CpFluid*(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp)) )
ELSE
CFloRadSys(RadSysNum)%WaterInjectionRate = CFloRadSys(RadSysNum)%WaterMassFlowRate
ENDIF
IF (CFloRadSys(RadSysNum)%WaterInjectionRate > CFloRadSys(RadSysNum)%WaterMassFlowRate) &
CFloRadSys(RadSysNum)%WaterInjectionRate = CFloRadSys(RadSysNum)%WaterMassFlowRate
CFloRadSys(RadSysNum)%WaterRecircRate = 0.0d0 ! by definition
ELSE IF ( (SysWaterInTemp >= LoopReqTemp) .AND. &
(Node(LoopInNode)%MassFlowRateMaxAvail < CFloRadSys(RadSysNum)%WaterMassFlowRate) ) THEN
! Case 3: Adequate temperature but loop flow is less than component flow
! This case might work out, but there is no guarantee that there is enough loop flow to
! mix with the recirculation flow and still provide a high enough temperature. First
! step is to try the inlet temperature and flow rate as in Case 1. If we can obtain
! the proper temperature inlet to the radiant system, then we are done. If not, we
! have to repeat the solution for an unknown inlet temperature and a known recirculation
! rate.
CFloRadSys(RadSysNum)%WaterInletTemp = RadInTemp
CALL CalcLowTempCFloRadSysComps(RadSysNum,LoopInNode,Iteration,LoadMet)
! Now see if we can really get that desired into temperature (RadInTemp) by solving
! for the flow that is injected from the loop. A heat balance for the mixer that relates
! the important quantities is:
! Mdotradsys*Cp*Tradsysin = Mdotloop*Cp*Tloop + (Mdotradsys-Mdotloop)*Cp*Tradsysout + PumpHeat
! or rearranging to get the injection flow (Mdotloop):
! Mdotloop = Mdotcomp*(Tradsysin-Tradsysout)/(Tloop-Tradsysout) - PumpHeat/(Cp*(Tloop-Tradsysout))
! If Mdotloop from this equation is greater that the loop flow rate (Node%MassFlowRate),
! then we cannot meet the inlet temperature and we have to "iterate" through the
! alternate solution.
InjectFlowRate = ( CFloRadSys(RadSysNum)%WaterMassFlowRate &
*(CFloRadSys(RadSysNum)%WaterInletTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) &
/(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) ) &
-( CFloRadSys(RadSysNum)%PumpHeattoFluid &
/(CpFluid*(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp)) )
IF (InjectFlowRate > Node(LoopInNode)%MassFlowRateMaxAvail) THEN
! We didn't have enough flow from the loop to meet our inlet temperature request.
! So, set the injection rate to the loop flow and calculate the recirculation flow.
! Then, resimulate the radiant system using these values (it will obtain the actual
! inlet temperature that results from this).
CFloRadSys(RadSysNum)%WaterInjectionRate = Node(LoopInNode)%MassFlowRateMaxAvail
CFloRadSys(RadSysNum)%WaterRecircRate = CFloRadSys(RadSysNum)%WaterMassFlowRate &
-CFloRadSys(RadSysNum)%WaterInjectionRate
CFloRadSys(RadSysNum)%WaterInletTemp = SysWaterInTemp + PumpTempRise
Iteration = .TRUE.
CALL CalcLowTempCFloRadSysComps(RadSysNum,LoopInNode,Iteration,LoadMet)
ELSE
CFloRadSys(RadSysNum)%WaterInjectionRate = InjectFlowRate
CFloRadSys(RadSysNum)%WaterRecircRate = CFloRadSys(RadSysNum)%WaterMassFlowRate &
-CFloRadSys(RadSysNum)%WaterInjectionRate
END IF
ELSE IF ( (SysWaterInTemp < LoopReqTemp) .AND. &
(Node(LoopInNode)%MassFlowRateMaxAvail < CFloRadSys(RadSysNum)%WaterMassFlowRate) ) THEN
! Case 4: Temperature too low and loop flow is less than component flow
! Worst condition--can't meet the temperature request at all. Only thing to do is to
! set the loop flow and recirculation rate (known) and solve for the inlet temperature
! using the "iteration" solution scheme from "Case 3B" above
CFloRadSys(RadSysNum)%WaterInjectionRate = Node(LoopInNode)%MassFlowRateMaxAvail
CFloRadSys(RadSysNum)%WaterRecircRate = CFloRadSys(RadSysNum)%WaterMassFlowRate &
-CFloRadSys(RadSysNum)%WaterInjectionRate
CFloRadSys(RadSysNum)%WaterInletTemp = SysWaterInTemp + PumpTempRise
Iteration = .TRUE.
CALL CalcLowTempCFloRadSysComps(RadSysNum,LoopInNode,Iteration,LoadMet)
END IF
ELSE IF (OperatingMode == CoolingMode) THEN
! in cooling mode so shut down heating water flow request
IF (CFloRadSys(RadSysNum)%HWLoopNum > 0) THEN
mdot = 0.d0
CALL SetComponentFlowRate(mdot, &
CFloRadSys(RadSysNum)%HotWaterInNode, &
CFloRadSys(RadSysNum)%HotWaterOutNode, &
CFloRadSys(RadSysNum)%HWLoopNum, &
CFloRadSys(RadSysNum)%HWLoopSide, &
CFloRadSys(RadSysNum)%HWBranchNum, &
CFloRadSys(RadSysNum)%HWCompNum )
ENDIF
LoopInNode = CFloRadSys(RadSysNum)%ColdWaterInNode
SysWaterInTemp = Node(LoopInNode)%Temp
CFloCondIterNum = 1
DO WHILE ( (CFloCondIterNum <= 1) .OR. &
( (CFloCondIterNum <= 2) .AND. (CFloRadSys(RadSysNum)%CondCtrlType == CondCtrlVariedOff) .AND. (VarOffCond) ) )
Iteration = .FALSE.
IF ( (SysWaterInTemp <= LoopReqTemp) .AND. &
(Node(LoopInNode)%MassFlowRateMaxAvail >= CFloRadSys(RadSysNum)%WaterMassFlowRate) ) THEN
! Case 1: Adequate temperature and flow
! Best condition--loop inlet temperature lower than requested and we have enough flow.
! So, proceed assuming the RadInTemp requested by the controls and then figure out the
! mixing after the outlet radiant temperature is calculated.
! This condition can also happen when LoopReqTemp has been reset to dewpoint for condensation control
IF (.NOT. VarOffCond) THEN
CFloRadSys(RadSysNum)%WaterInletTemp = RadInTemp
ELSE
CFloRadSys(RadSysNum)%WaterInletTemp = LoopReqTemp
ENDIF
CALL CalcLowTempCFloRadSysComps(RadSysNum,LoopInNode,Iteration,LoadMet)
! We now have inlet and outlet temperatures--we still need to set the flow rates
CFloRadSys(RadSysNum)%WaterInjectionRate = ( CFloRadSys(RadSysNum)%WaterMassFlowRate &
*(CFloRadSys(RadSysNum)%WaterInletTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) &
/(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) ) &
-( CFloRadSys(RadSysNum)%PumpHeattoFluid &
/(CpFluid*(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp)) )
CFloRadSys(RadSysNum)%WaterRecircRate = CFloRadSys(RadSysNum)%WaterMassFlowRate &
-CFloRadSys(RadSysNum)%WaterInjectionRate
ELSE IF ( (SysWaterInTemp > LoopReqTemp) .AND. &
(Node(LoopInNode)%MassFlowRateMaxAvail >= CFloRadSys(RadSysNum)%WaterMassFlowRate) ) THEN
! Case 2: Adequate flow but temperature too high
! Only thing to do is to reset the inlet temperature and assume that the loop will supply
! the entire flow to the component (no recirculation but potentially some bypass for the
! overall loop). There is no way we can meet the control temperature so don't even try.
CFloRadSys(RadSysNum)%WaterInletTemp = SysWaterInTemp + PumpTempRise
CALL CalcLowTempCFloRadSysComps(RadSysNum,LoopInNode,Iteration,LoadMet)
! We now have inlet and outlet temperatures--we still need to set the flow rates
IF ((SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) /= 0.d0) THEN ! protect div by zero
CFloRadSys(RadSysNum)%WaterInjectionRate = ( CFloRadSys(RadSysNum)%WaterMassFlowRate &
*(CFloRadSys(RadSysNum)%WaterInletTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) &
/(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp ) ) &
-( CFloRadSys(RadSysNum)%PumpHeattoFluid &
/(CpFluid*(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp)) )
ELSE ! no temp change present, set injection rate to full flow
CFloRadSys(RadSysNum)%WaterInjectionRate = CFloRadSys(RadSysNum)%WaterMassFlowRate
ENDIF
IF (CFloRadSys(RadSysNum)%WaterInjectionRate > CFloRadSys(RadSysNum)%WaterMassFlowRate) &
CFloRadSys(RadSysNum)%WaterInjectionRate = CFloRadSys(RadSysNum)%WaterMassFlowRate
CFloRadSys(RadSysNum)%WaterRecircRate = 0.0d0 ! by definition
ELSE IF ( (SysWaterInTemp <= LoopReqTemp) .AND. &
(Node(LoopInNode)%MassFlowRateMaxAvail < CFloRadSys(RadSysNum)%WaterMassFlowRate) ) THEN
! Case 3: Adequate temperature but loop flow is less than component flow
! This case might work out, but there is no guarantee that there is enough loop flow to
! mix with the recirculation flow and still provide a high enough temperature. First
! step is to try the inlet temperature and flow rate as in Case 1. If we can obtain
! the proper temperature inlet to the radiant system, then we are done. If not, we
! have to repeat the solution for an unknown inlet temperature and a known recirculation
! rate.
! This condition might happen when LoopReqTemp has been reset to dewpoint for condensation control
IF (.NOT. VarOffCond) THEN
CFloRadSys(RadSysNum)%WaterInletTemp = RadInTemp
ELSE
CFloRadSys(RadSysNum)%WaterInletTemp = LoopReqTemp
ENDIF
CALL CalcLowTempCFloRadSysComps(RadSysNum,LoopInNode,Iteration,LoadMet)
! Now see if we can really get that desired into temperature (RadInTemp) by solving
! for the flow that is injected from the loop. A heat balance for the mixer that relates
! the important quantities is:
! Mdotradsys*Cp*Tradsysin = Mdotloop*Cp*Tloop + (Mdotradsys-Mdotloop)*Cp*Tradsysout + PumpHeat
! or rearranging to get the injection flow (Mdotloop):
! Mdotloop = Mdotcomp*(Tradsysin-Tradsysout)/(Tloop-Tradsysout) - PumpHeat/(Cp*(Tloop-Tradsysout))
! If Mdotloop from this equation is greater that the loop flow rate (Node%MassFlowRate),
! then we cannot meet the inlet temperature and we have to "iterate" through the
! alternate solution.
InjectFlowRate = ( CFloRadSys(RadSysNum)%WaterMassFlowRate &
*(CFloRadSys(RadSysNum)%WaterInletTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) &
/(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp) ) &
-( CFloRadSys(RadSysNum)%PumpHeattoFluid &
/(CpFluid*(SysWaterInTemp - CFloRadSys(RadSysNum)%WaterOutletTemp)) )
IF (InjectFlowRate > Node(LoopInNode)%MassFlowRateMaxAvail) THEN
! We didn't have enough flow from the loop to meet our inlet temperature request.
! So, set the injection rate to the loop flow and calculate the recirculation flow.
! Then, resimulate the radiant system using these values (it will obtain the actual
! inlet temperature that results from this).
CFloRadSys(RadSysNum)%WaterInjectionRate = Node(LoopInNode)%MassFlowRateMaxAvail
CFloRadSys(RadSysNum)%WaterRecircRate = CFloRadSys(RadSysNum)%WaterMassFlowRate &
-CFloRadSys(RadSysNum)%WaterInjectionRate
CFloRadSys(RadSysNum)%WaterInletTemp = SysWaterInTemp + PumpTempRise
Iteration = .TRUE.
CALL CalcLowTempCFloRadSysComps(RadSysNum,LoopInNode,Iteration,LoadMet)
ELSE
CFloRadSys(RadSysNum)%WaterInjectionRate = InjectFlowRate
CFloRadSys(RadSysNum)%WaterRecircRate = CFloRadSys(RadSysNum)%WaterMassFlowRate &
-CFloRadSys(RadSysNum)%WaterInjectionRate
END IF
ELSE IF ( (SysWaterInTemp > LoopReqTemp) .AND. &
(Node(LoopInNode)%MassFlowRateMaxAvail < CFloRadSys(RadSysNum)%WaterMassFlowRate) ) THEN
! Case 4: Temperature too low and loop flow is less than component flow
! Worst condition--can't meet the temperature request at all. Only thing to do is to
! set the loop flow and recirculation rate (known) and solve for the inlet temperature
! using the "iteration" solution scheme from "Case 3B" above
CFloRadSys(RadSysNum)%WaterInjectionRate = Node(LoopInNode)%MassFlowRateMaxAvail
CFloRadSys(RadSysNum)%WaterRecircRate = CFloRadSys(RadSysNum)%WaterMassFlowRate &
-CFloRadSys(RadSysNum)%WaterInjectionRate
CFloRadSys(RadSysNum)%WaterInletTemp = SysWaterInTemp + PumpTempRise
Iteration = .TRUE.
CALL CalcLowTempCFloRadSysComps(RadSysNum,LoopInNode,Iteration,LoadMet)
END IF
CFloCondIterNum = CFloCondIterNum + 1
END DO
END IF ! Operating mode (heating or cooling)
! Case when system has been shut down because of condensation issues or other limitations:
IF (CFloRadSys(RadSysNum)%WaterMassFlowRate < MassFlowTolerance) THEN
CFloRadSys(RadSysNum)%WaterMassFlowRate = 0.0d0
CFloRadSys(RadSysNum)%WaterInjectionRate = 0.0d0
CFloRadSys(RadSysNum)%WaterRecircRate = 0.0d0
CFloRadSys(RadSysNum)%PumpMassFlowRate = 0.0d0
OperatingMode = NotOperating
END IF
! There are some cases when the pump heat is actually enough to provide all the heating that the system needs.
! In this case, the water injection flow rate will come back as a slightly negative number. Reset it to zero
! and just recirculate all the flow through the local loop.
IF (CFloRadSys(RadSysNum)%WaterInjectionRate < 0.0d0) THEN
CFloRadSys(RadSysNum)%WaterInjectionRate = 0.0d0
CFloRadSys(RadSysNum)%WaterRecircRate = CFloRadSys(RadSysNum)%WaterMassFlowRate
END IF
! Error check, just in case
IF (CFloRadSys(RadSysNum)%WaterRecircRate < 0.0d0) THEN
CALL ShowWarningError('Flow mismatch in radiant system--result will be an energy imbalance--should not get this error')
CALL ShowContinueErrorTimeStamp('WaterRecircRate='//TRIM(TrimSigDigits(CFloRadSys(RadSysNum)%WaterRecircRate,2))// &
', in Radiant System='//TRIM(CFloRadSys(RadSysNum)%Name)// &
',')
CFloRadSys(RadSysNum)%WaterRecircRate = 0.0d0
CFloRadSys(RadSysNum)%WaterInjectionRate = CFloRadSys(RadSysNum)%WaterMassFlowRate
END IF
END IF ! System running mode (yes or no)
RETURN
END SUBROUTINE CalcLowTempCFloRadiantSystem