SUBROUTINE CalcHeatBalanceInsideSurf(ZoneToResimulate)
! SUBROUTINE INFORMATION:
! AUTHOR George Walton
! DATE WRITTEN December 1979
! MODIFIED Jun 1990 (RDT for new CTF arrays)
! Dec 1999 (FCW for window calculation)
! May 2000 (FCW for window frame and dividers)
! Aug 2000 (RJL for MTF moisture calculations)
! Sep 2000 (RKS for new radiant exchange algorithm)
! Dec 2000 (RKS for radiant system model addition)
! Jul 2003 (CC) set the reference temperatures for inside surface heat balance
! depending on convection algorithms and/or air models used
! May 2006 (RR account for exterior window screen)
! Jul 2008 (P. Biddulph include calls to HAMT)
! Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
! RE-ENGINEERED Mar 1998 (RKS)
! PURPOSE OF THIS SUBROUTINE:
! This subroutine performs a heat balance on the outside face of each
! surface in the building.
! METHODOLOGY EMPLOYED:
! Various boundary conditions are set and additional parameters are set-
! up. Then, the proper heat balance equation is selected based on whether
! the surface is a partition or not and on whether or not movable
! insulation is present on the inside face.
! REFERENCES:
! (I)BLAST legacy routine HBSRF
! USE STATEMENTS:
USE DataPrecisionGlobals
USE DataGlobals
USE DataEnvironment
USE DataHeatBalFanSys
USE DataHeatBalance
USE DataHeatBalSurface
USE DataSurfaces
USE DataInterfaces, ONLY: ShowMessage,ShowContinueError,ShowContinueErrorTimeStamp,ShowFatalError, &
ShowSevereError,ShowSevereMessage,ShowWarningError,ShowWarningMessage,ShowErrorMessage, &
ShowRecurringSevereErrorAtEnd,ShowRecurringWarningErrorAtEnd,ShowRecurringContinueErrorAtEnd, &
SetupOutputVariable
USE DataDaylightingDevices
USE DataMoistureBalance, ONLY : TempOutsideAirFD,RhoVaporAirOut,RhoVaporAirIn,HConvExtFD,HMassConvExtFD, &
HConvInFD,HMassConvInFD,RhoVaporSurfIn, &
HSkyFD,HGrndFD,HAirFD
USE DataMoistureBalanceEMPD, ONLY : MoistEMPDNew, MoistEMPDFlux
USE DataAirflowNetwork, ONLY : SimulateAirflowNetwork,AirflowNetworkControlSimple
USE HeatBalanceMovableInsulation, ONLY : EvalInsideMovableInsulation
USE WindowManager, ONLY : CalcWindowHeatBalance
USE HeatBalFiniteDiffManager, ONLY : ManageHeatBalFiniteDiff, SurfaceFD
USE HeatBalanceHAMTManager, ONLY : ManageHeatBalHAMT,UpdateHeatBalHAMT
USE ConvectionCoefficients, ONLY : InitExteriorConvectionCoeff, InitInteriorConvectionCoeffs, &
SetExtConvectionCoeff, SetIntConvectionCoeff
USE HeatBalanceIntRadExchange, ONLY : CalcInteriorRadExchange
USE MoistureBalanceEMPDManager, ONLY : CalcMoistureBalanceEMPD,UpdateMoistureBalanceEMPD
USE ScheduleManager, ONLY : GetCurrentScheduleValue
USE General, ONLY : RoundSigDigits
USE DaylightingDevices, ONLY : FindTDDPipe
USE DataZoneEquipment, ONLY : ZoneEquipConfig
USE DataLoopNode, ONLY : Node
USE HeatBalanceSurfaceManager, ONLY : CalculateZoneMRT
USE Psychrometrics
USE OutputReportTabular, ONLY: loadConvectedNormal,loadConvectedWithPulse,netSurfRadSeq
USE DataSizing, ONLY: CurOverallSimDay
USE DataTimings
USE WindowEquivalentLayer, ONLY : EQLWindowOutsideEffectiveEmiss
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! SUBROUTINE ARGUMENT DEFINITIONS:
INTEGER, INTENT(IN), OPTIONAL :: ZoneToResimulate ! if passed in, then only calculate surfaces that have this zone
! SUBROUTINE PARAMETER DEFINITIONS:
REAL(r64), PARAMETER :: Sigma = 5.6697d-08 ! Stefan-Boltzmann constant
REAL(r64), PARAMETER :: IterDampConst = 5.0d0 ! Damping constant for inside surface temperature iterations
INTEGER, PARAMETER :: ItersReevalConvCoeff = 30 ! Number of iterations between inside convection coefficient reevaluations
REAL(r64), PARAMETER :: MaxAllowedDelTemp = 0.002d0 ! Convergence criteria for inside surface temperatures
INTEGER, PARAMETER :: MaxIterations = 500 ! Maximum number of iterations allowed for inside surface temps
INTEGER, PARAMETER :: IterationsForCondFDRelaxChange = 5 ! number of iterations for inside temps that triggers a change
! in the CondFD relaxation factor.
INTEGER, PARAMETER :: MinEMPDIterations = 4 ! Minimum number of iterations required for EMPD solution
! INTERFACE BLOCK SPECIFICATIONS:
! na
! DERIVED TYPE DEFINITIONS:
! na
! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
REAL(r64) :: AbsInt ! Solar absorptance of inside movable insulation
INTEGER :: ConstrNum ! Construction index for the current surface
LOGICAL :: Converged ! .true. if inside heat balance has converged
REAL(r64) :: F1 ! Intermediate calculation value
REAL(r64) :: HMovInsul ! "Convection" coefficient of movable insulation
REAL(r64) :: MaxDelTemp ! Maximum change in surface temperature for any
! opaque surface from one iteration to the next
INTEGER :: SurfNum ! Surface number
INTEGER :: ZoneNum ! Zone number the current surface is attached to
INTEGER :: ConstrNumSh ! Shaded construction number for a window
INTEGER :: RoughSurf ! Outside surface roughness
REAL(r64) :: EmisOut ! Glass outside surface emissivity
REAL(r64), SAVE, ALLOCATABLE, DIMENSION(:) :: TempInsOld ! Holds previous iteration's value for convergence check
REAL(r64) :: RhoVaporSat ! Local temporary saturated vapor density for checking
REAL(r64) :: TempSurfOutTmp ! Local Temporary Surface temperature for the outside surface face
REAL(r64) :: TempSurfInSat ! Local temperary surface dew point temperature
LOGICAL, SAVE :: FirstTime = .TRUE. ! Used for trapping errors or other problems
INTEGER :: OtherSideSurfNum ! Surface number index for other side of an interzone partition
INTEGER, SAVE :: MinIterations ! Minimum number of iterations for the inside heat balance
! CHARACTER(len=25):: ErrMsg
! CHARACTER(len=5) :: TimeStmp
INTEGER, SAVE :: ErrCount=0
INTEGER :: PipeNum ! TDD pipe object number
INTEGER :: SurfNum2 ! TDD:DIFFUSER object number
REAL(r64) :: Ueff ! 1 / effective R value between TDD:DOME and TDD:DIFFUSER
INTEGER :: ZoneEquipConfigNum
! LOGICAL :: ControlledZoneAirFlag
INTEGER :: NodeNum
REAL(r64) :: SumSysMCp ! Zone sum of air system MassFlowRate*Cp
REAL(r64) :: SumSysMCpT ! Zone sum of air system MassFlowRate*Cp*T
REAL(r64) :: MassFlowRate
REAL(r64) :: NodeTemp
REAL(r64) :: CpAir
REAL(r64), SAVE, ALLOCATABLE, DIMENSION(:) :: RefAirTemp ! reference air temperatures
LOGICAL, SAVE :: MyEnvrnFlag=.true.
! LOGICAL, SAVE :: DoThisLoop
INTEGER, SAVE :: InsideSurfErrCount=0
REAL(r64) :: Wsurf ! Moisture ratio for HAMT
REAL(r64) :: RhoAirZone ! Zone moisture density for HAMT
INTEGER :: OtherSideZoneNum ! Zone Number index for other side of an interzone partition HAMT
INTEGER,SAVE :: WarmupSurfTemp
LOGICAL :: PartialResimulate
INTEGER :: TimeStepInDay=0 ! time step number
! FLOW:
IF (FirstTime) THEN
ALLOCATE(TempInsOld(TotSurfaces))
ALLOCATE(RefAirTemp(TotSurfaces))
IF (ANY(HeatTransferAlgosUsed == UseEMPD)) THEN
MinIterations = MinEMPDIterations
ELSE
MinIterations = 1
END IF
IF (DisplayAdvancedReportVariables) THEN
CALL SetupOutputVariable('Surface Inside Face Heat Balance Calculation Iteration Count []',InsideSurfIterations, &
'ZONE','Sum','Simulation')
ENDIF
ENDIF
IF (BeginEnvrnFlag .and. MyEnvrnFlag) THEN
TempInsOld=23.0d0
RefAirTemp=23.0d0
TempEffBulkAir=23.0d0
WarmupSurfTemp=0
MyEnvrnFlag=.false.
ENDIF
IF (.not. BeginEnvrnFlag) THEN
MyEnvrnFlag=.true.
ENDIF
PartialResimulate=.false.
! determine reference air temperatures
DO SurfNum = 1, TotSurfaces
ZoneNum = Surface(SurfNum)%Zone
IF (.NOT. Surface(SurfNum)%HeatTransSurf .OR. ZoneNum == 0) CYCLE ! Skip non-heat transfer surfaces
IF (Surface(SurfNum)%Class == SurfaceClass_TDD_Dome) CYCLE ! Skip TDD:DOME objects. Inside temp is handled by TDD:DIFFUSER.
IF (PRESENT(ZoneToResimulate)) THEN
PartialResimulate=.true.
IF ((ZoneNum /= ZoneToResimulate) .AND. (AdjacentZoneToSurface(SurfNum) /= ZoneToResimulate)) THEN
CYCLE ! skip surfaces that are not associated with this zone
ENDIF
ENDIF
IF (PartialResimulate) THEN
WinHeatGain(Surfnum) = 0.0d0
WinHeatGainRep(Surfnum) = 0.0d0
WinHeatLossRep(Surfnum) = 0.0d0
WinGainConvGlazToZoneRep(Surfnum) = 0.0D0
WinGainIRGlazToZoneRep(Surfnum) = 0.0D0
WinLossSWZoneToOutWinRep(Surfnum) = 0.0D0
WinGainFrameDividertoZoneRep(Surfnum) = 0.0D0
WinGainConvGlazShadGapToZoneRep(Surfnum) = 0.0D0
WinGainConvShadeToZoneRep(Surfnum) = 0.0D0
OtherConvGainInsideFaceToZoneRep(Surfnum)= 0.0D0
WinGainIRShadeToZoneRep(Surfnum) = 0.0D0
SurfaceWindow(Surfnum)%FrameQRadOutAbs = 0.0d0
SurfaceWindow(Surfnum)%FrameQRadInAbs = 0.0d0
SurfaceWindow(Surfnum)%DividerQRadOutAbs = 0.0d0
SurfaceWindow(Surfnum)%DividerQRadInAbs = 0.0d0
ENDIF
SELECT CASE (Surface(SurfNum)%TAirRef)
CASE (ZoneMeanAirTemp)
RefAirTemp(SurfNum) = MAT(ZoneNum)
TempEffBulkAir(SurfNum) = MAT(ZoneNum) ! for reporting surf adjacent air temp
CASE (AdjacentAirTemp)
RefAirTemp(SurfNum) = TempEffBulkAir(SurfNum)
CASE (ZoneSupplyAirTemp)
! determine ZoneEquipConfigNum for this zone
ZoneEquipConfigNum = ZoneNum
! check whether this zone is a controlled zone or not
IF (.NOT. Zone(ZoneNum)%IsControlled) THEN
CALL ShowFatalError('Zones must be controlled for Ceiling-Diffuser Convection model. No system serves zone '// &
TRIM(Zone(ZoneNum)%Name))
RETURN
END IF
! determine supply air conditions
SumSysMCp = 0.0d0
SumSysMCpT = 0.0d0
DO NodeNum = 1, ZoneEquipConfig(ZoneEquipConfigNum)%NumInletNodes
NodeTemp = Node(ZoneEquipConfig(ZoneEquipConfigNum)%InletNode(NodeNum))%Temp
MassFlowRate = Node(ZoneEquipConfig(ZoneEquipConfigNum)%InletNode(NodeNum))%MassFlowRate
CpAir = PsyCpAirFnWTdb(ZoneAirHumRat(ZoneNum), NodeTemp)
SumSysMCp = SumSysMCp + MassFlowRate * CpAir
SumSysMCpT = SumSysMCpT + MassFlowRate * CpAir * NodeTemp
END DO
! a weighted average of the inlet temperatures.
IF (SumSysMCp > 0.d0) THEN ! protect div by zero
RefAirTemp(SurfNum) = SumSysMCpT/SumSysMCp ! BG changed 02-16-2005 to add index (SurfNum)
ELSE
RefAirTemp(SurfNum) = NodeTemp
ENDIF
TempEffBulkAir(SurfNum) = RefAirTemp(SurfNum) ! for reporting surf adjacent air temp
CASE DEFAULT
! currently set to mean air temp but should add error warning here
RefAirTemp(SurfNum) = MAT(ZoneNum)
TempEffBulkAir(SurfNum) = MAT(ZoneNum) ! for reporting surf adjacent air temp
END SELECT
END DO
InsideSurfIterations = 0
! Following variables must be reset due to possible recall of this routine by radiant and Resimulate routines.
! CalcWindowHeatBalance is called, then, multiple times and these need to be initialized before each call to
! CalcWindowHeatBalance.
IF (.not. PartialResimulate) THEN
WinHeatGain = 0.0d0
WinHeatGainRep = 0.0d0
WinHeatLossRep = 0.0d0
WinGainConvGlazToZoneRep = 0.0D0
WinGainIRGlazToZoneRep = 0.0D0
WinLossSWZoneToOutWinRep = 0.0D0
WinGainFrameDividertoZoneRep = 0.0D0
WinGainConvGlazShadGapToZoneRep = 0.0D0
WinGainConvShadeToZoneRep = 0.0D0
OtherConvGainInsideFaceToZoneRep= 0.0D0
WinGainIRShadeToZoneRep = 0.0D0
SurfaceWindow%FrameQRadOutAbs = 0.0d0
SurfaceWindow%FrameQRadInAbs = 0.0d0
SurfaceWindow%DividerQRadOutAbs = 0.0d0
SurfaceWindow%DividerQRadInAbs = 0.0d0
ENDIF
Converged = .FALSE.
DO WHILE (.NOT. Converged) ! Start of main inside heat balance DO loop...
TempInsOld = TempSurfIn ! Keep track of last iteration's temperature values
IF (PRESENT(ZoneToResimulate)) THEN
CALL CalcInteriorRadExchange(TempSurfIn,InsideSurfIterations,NetLWRadToSurf, &
ZoneToResimulate,calledfrom='Inside') ! Update the radiation balance
ELSE
CALL CalcInteriorRadExchange(TempSurfIn,InsideSurfIterations,NetLWRadToSurf, &
calledfrom='Inside') ! Update the radiation balance
ENDIF
! Every 30 iterations, recalculate the inside convection coefficients in case
! there has been a significant drift in the surface temperatures predicted.
! This is not fool-proof and it basically means that the outside surface
! heat balance is in error (potentially) once HConvIn is re-evaluated.
! The choice of 30 is not significant--just want to do this a couple of
! times before the iteration limit is hit.
IF ((InsideSurfIterations>0).AND.(MOD(InsideSurfIterations,ItersReevalConvCoeff)==0)) THEN
IF (PRESENT(ZoneToResimulate)) THEN
CALL InitInteriorConvectionCoeffs(TempSurfIn,ZoneToResimulate)
ELSE
CALL InitInteriorConvectionCoeffs(TempSurfIn)
ENDIF
ENDIF
DO SurfNum = 1, TotSurfaces ! Perform a heat balance on all of the inside surface...
ZoneNum = Surface(SurfNum)%Zone
IF (.NOT. Surface(SurfNum)%HeatTransSurf .OR. ZoneNum == 0) CYCLE ! Skip non-heat transfer surfaces
IF (Surface(SurfNum)%Class == SurfaceClass_TDD_Dome) CYCLE ! Skip TDD:DOME objects. Inside temp is handled by TDD:DIFFUSER.
IF (PRESENT(ZoneToResimulate)) THEN
IF ((ZoneNum /= ZoneToResimulate) .AND. (AdjacentZoneToSurface(SurfNum) /= ZoneToResimulate)) THEN
CYCLE ! skip surfaces that are not associated with this zone
ENDIF
ENDIF
ConstrNum = Surface(SurfNum)%Construction
!Calculate the inside surface moisture quantities
!calculate the inside surface moisture transfer conditions
RhoVaporAirIn(SurfNum)=PsyRhovFnTdbWPb(MAT(ZoneNum),ZoneAirHumRat(ZoneNum),OutBaroPress)
!check for saturation conditions of air
RhoVaporSat=PsyRhovFnTdbRh(MAT(ZoneNum),1.0d0,'HB,SurfMan:InsideSurf')
IF (RhoVaporAirIn(SurfNum) .GT. RhoVaporSat) RhoVaporAirIn(SurfNum)=RhoVaporSat
HConvInFD(SurfNum)=HConvIn(SurfNum)
HMassConvInFD(SurfNum)=HConvInFD(SurfNum)/((PsyRhoAirFnPbTdbW(OutBaroPress,MAT(ZoneNum),ZoneAirHumRat(ZoneNum))+ &
RhoVaporAirIn(SurfNum))*PsyCpAirFnWTdb(ZoneAirHumRat(ZoneNum),MAT(ZoneNum)))
! Perform heat balance on the inside face of the surface ...
! The following are possibilities here:
! (a) the surface is a partition, in which case the temperature of both sides are the same
! (b) standard (or interzone) opaque surface with no movable insulation, normal heat balance equation
! (c) standard (or interzone) window: call to CalcWindowHeatBalance to get window layer temperatures
! (d) standard opaque surface with movable insulation, special two-part equation
! In the surface calculation there are the following Algorithm types for opaque surfaces that
! do not have movable insulation:
! (a) the regular CTF calc (SolutionAlgo = UseCTF)
! (b) the EMPD calc (Solutionalgo = UseEMPD)
! (c) the CondFD calc (SolutionAlgo = UseCondFD)
! (d) the HAMT calc (solutionalgo = UseHAMT).
IF (Surface(SurfNum)%ExtBoundCond == SurfNum .and. Surface(SurfNum)%Class /= SurfaceClass_Window) THEN
!CR6869 -- let Window HB take care of it IF (Surface(SurfNum)%ExtBoundCond == SurfNum) THEN
! Surface is a partition
IF ( Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_CTF .OR. &
Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_EMPD) THEN !Regular CTF Surface and/or EMPD surface
If (Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_EMPD) Then
Call CalcMoistureBalanceEMPD(SurfNum, TempSurfInTmp(SurfNum), &
TH(SurfNum,2,2), MAT(ZoneNum),TempSurfInSat)
End If
TempSurfInTmp(SurfNum) = ( CTFConstInPart(SurfNum) & ! Constant portion of conduction eq (history terms)
+QRadThermInAbs(SurfNum) & ! LW radiation from internal sources
+QRadSWInAbs(SurfNum) & ! SW radiation from internal sources
+HConvIn(SurfNum)*RefAirTemp(SurfNum) & ! Convection from surface to zone air
+NetLWRadToSurf(SurfNum) & ! Net radiant exchange with other zone surfaces
+Construct(ConstrNum)%CTFSourceIn(0) & ! Heat source/sink term for radiant systems
*QsrcHist(SurfNum,1) & ! (if there is one present)
+QHTRadSysSurf(SurfNum) & ! Radiant flux from a high temperature radiant heater
+QHWBaseboardSurf(SurfNum) & ! Radiant flux from a hot water baseboard heater
+QSteamBaseboardSurf(SurfNum) & ! Radiant flux from a steam baseboard heater
+QElecBaseboardSurf(SurfNum) & ! Radiant flux from an electric baseboard heater
+IterDampConst &
*TempInsOld(SurfNum) ) & ! Iterative damping term (for stability)
/( Construct(ConstrNum)%CTFInside(0) & ! Conduction term (both partition sides same temp)
-Construct(ConstrNum)%CTFCross(0) & ! Conduction term (both partition sides same temp)
+HConvIn(SurfNum)+IterDampConst ) ! Convection and damping term
If (Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_EMPD) Then
TempSurfInTmp(SurfNum) = TempSurfInTmp(SurfNum) &
-MoistEMPDFlux(SurfNum) &
/( Construct(ConstrNum)%CTFInside(0) & ! Conduction term (both partition sides same temp)
-Construct(ConstrNum)%CTFCross(0) & ! Conduction term (both partition sides same temp)
+HConvIn(SurfNum)+IterDampConst ) ! Convection and damping term
if (TempSurfInSat .GT. TempSurfInTmp(SurfNum)) then
TempSurfInTmp(SurfNum) = TempSurfInSat ! Surface temp cannot be below dew point
end if
End If
! if any mixed heat transfer models in zone, apply limits to CTF result
IF (ANY(Surface(Zone(ZoneNum)%SurfaceFirst:Zone(ZoneNum)%SurfaceLast)%HeatTransferAlgorithm == HeatTransferModel_CondFD)&
.OR. &
ANY(Surface(Zone(ZoneNum)%SurfaceFirst:Zone(ZoneNum)%SurfaceLast)%HeatTransferAlgorithm == HeatTransferModel_HAMT) )&
THEN
TempSurfInTmp(SurfNum) = MAX(MinSurfaceTempLimit,MIN(MaxSurfaceTempLimit,TempSurfInTmp(SurfNum))) !Limit Check
ENDIF
IF (Construct(ConstrNum)%SourceSinkPresent) THEN ! Set the appropriate parameters for the radiant system
! Radiant system does not need the damping coefficient terms (hopefully)
RadSysTiHBConstCoef(SurfNum) = ( CTFConstInPart(SurfNum) & ! Constant portion of conduction eq (history terms)
+QRadThermInAbs(SurfNum) & ! LW radiation from internal sources
+QRadSWInAbs(SurfNum) & ! SW radiation from internal sources
+HConvIn(SurfNum)*RefAirTemp(SurfNum) & ! Convection from surface to zone air
+QHTRadSysSurf(SurfNum) & ! Radiant flux from high temperature radiant heater
+QHWBaseboardSurf(SurfNum) & ! Radiant flux from a hot water baseboard heater
+QSteamBaseboardSurf(SurfNum) & ! Radiant flux from a steam baseboard heater
+QElecBaseboardSurf(SurfNum) & ! Radiant flux from an electric baseboard heater
+NetLWRadToSurf(SurfNum) ) & ! Net radiant exchange with other zone surfaces
/( Construct(ConstrNum)%CTFInside(0) & ! Cond term (both partition sides same temp)
-Construct(ConstrNum)%CTFCross(0) & ! Cond term (both partition sides same temp)
+HConvIn(SurfNum) ) ! Convection and damping term
RadSysTiHBToutCoef(SurfNum) = 0.0d0 ! The outside temp is assumed to be equal to the inside temp for a partition
RadSysTiHBQsrcCoef(SurfNum) = Construct(ConstrNum)%CTFSourceIn(0) & ! QTF term for the source
/( Construct(ConstrNum)%CTFInside(0) & ! Cond term (both partition sides same temp)
-Construct(ConstrNum)%CTFCross(0) & ! Cond term (both partition sides same temp)
+HConvIn(SurfNum) ) ! Convection and damping term
RadSysToHBConstCoef(SurfNum) = RadSysTiHBConstCoef(SurfNum) ! Partitions are assumed to be symmetric
RadSysToHBTinCoef(SurfNum) = RadSysTiHBToutCoef(SurfNum) ! Partitions are assumed to be symmetric
RadSysToHBQsrcCoef(SurfNum) = RadSysTiHBQsrcCoef(SurfNum) ! Partitions are assumed to be symmetric
END IF
ELSE IF(Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_CondFD .OR. &
Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_HAMT) THEN
IF(Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_HAMT) &
CALL ManageHeatBalHAMT(SurfNum,TempSurfInTmp(SurfNum),TempSurfOutTmp) !HAMT
If(Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_CondFD ) &
CALL ManageHeatBalFiniteDiff(SurfNum,TempSurfInTmp(SurfNum),TempSurfOutTmp)
TH(SurfNum,1,1) = TempSurfOutTmp
End If
TempSurfIn(SurfNum) = TempSurfInTmp(SurfNum)
ELSE ! Standard surface or interzone surface
IF (Surface(SurfNum)%Class /= SurfaceClass_Window) THEN ! Opaque surface
HMovInsul = 0.0d0
IF (Surface(SurfNum)%MaterialMovInsulInt > 0) &
CALL EvalInsideMovableInsulation(SurfNum,HMovInsul,AbsInt)
IF (HMovInsul <= 0.0d0) THEN ! No movable insulation present, normal heat balance equation
IF (Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_CTF .OR. &
Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_EMPD) THEN ! Regular CTF Surface and/or EMPD surface
IF (Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_EMPD) THEN
Call CalcMoistureBalanceEMPD(SurfNum, TempSurfInTmp(SurfNum), &
TH(SurfNum,2,2), MAT(ZoneNum),TempSurfInSat)
End If
TempSurfInTmp(SurfNum) = ( CTFConstInPart(SurfNum) & ! Constant part of conduction eq (history terms)
+QRadThermInAbs(SurfNum) & ! LW radiation from internal sources
+QRadSWInAbs(SurfNum) & ! SW radiation from internal sources
+HConvIn(SurfNum)*RefAirTemp(SurfNum) & ! Convection from surface to zone air
+NetLWRadToSurf(SurfNum) & ! Net radiant exchange with other zone surfaces
+Construct(ConstrNum)%CTFSourceIn(0) & ! Heat source/sink term for radiant systems
*QsrcHist(SurfNum,1) & ! (if there is one present)
+QHTRadSysSurf(SurfNum) & ! Radiant flux from high temp radiant heater
+QHWBaseboardSurf(SurfNum) & ! Radiant flux from a hot water baseboard heater
+QSteamBaseboardSurf(SurfNum) & ! Radiant flux from a steam baseboard heater
+QElecBaseboardSurf(SurfNum) & ! Radiant flux from an electric baseboard heater
+IterDampConst &
*TempInsOld(SurfNum) & ! Iterative damping term (for stability)
+Construct(ConstrNum)%CTFCross(0) & ! Current conduction from
*TH(SurfNum,1,1) ) & ! the outside surface
/( Construct(ConstrNum)%CTFInside(0) & ! Coefficient for conduction (current time)
+HConvIn(SurfNum)+IterDampConst ) ! Convection and damping term
IF (Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_EMPD) THEN
TempSurfInTmp(SurfNum) = TempSurfInTmp(SurfNum) &
-MoistEMPDFlux(SurfNum) &
/( Construct(ConstrNum)%CTFInside(0) & ! Coefficient for conduction (current time)
+HConvIn(SurfNum)+IterDampConst ) ! Convection and damping term
if (TempSurfInSat .GT. TempSurfInTmp(SurfNum)) then
TempSurfInTmp(SurfNum) = TempSurfInSat ! Surface temp cannot be below dew point
end if
End If
! if any mixed heat transfer models in zone, apply limits to CTF result
IF (ANY(Surface(Zone(ZoneNum)%SurfaceFirst:Zone(ZoneNum)%SurfaceLast)%HeatTransferAlgorithm &
== HeatTransferModel_CondFD) .OR. &
ANY(Surface(Zone(ZoneNum)%SurfaceFirst:Zone(ZoneNum)%SurfaceLast)%HeatTransferAlgorithm &
== HeatTransferModel_HAMT) )&
THEN
TempSurfInTmp(SurfNum) = MAX(MinSurfaceTempLimit,MIN(MaxSurfaceTempLimit,TempSurfInTmp(SurfNum))) !Limit Check
ENDIF
IF (Construct(ConstrNum)%SourceSinkPresent) THEN ! Set the appropriate parameters for the radiant system
! Radiant system does not need the damping coefficient terms (hopefully)
RadSysTiHBConstCoef(SurfNum) = ( CTFConstInPart(SurfNum) & ! Constant portion of cond eq (history terms)
+QRadThermInAbs(SurfNum) & ! LW radiation from internal sources
+QRadSWInAbs(SurfNum) & ! SW radiation from internal sources
+HConvIn(SurfNum)*RefAirTemp(SurfNum) & ! Convection from surface to zone air
+QHTRadSysSurf(SurfNum) & ! Radiant flux from high temp radiant heater
+QHWBaseboardSurf(SurfNum) & ! Radiant flux from a hot water baseboard heater
+QSteamBaseboardSurf(SurfNum) & ! Radiant flux from a steam baseboard heater
+QElecBaseboardSurf(SurfNum) & ! Radiant flux from an electric baseboard heater
+NetLWRadToSurf(SurfNum) ) & ! Net radiant exchange with other zone surfaces
/( Construct(ConstrNum)%CTFInside(0) & ! Cond term (both partition sides same temp)
+HConvIn(SurfNum) ) ! Convection and damping term
RadSysTiHBToutCoef(SurfNum) = Construct(ConstrNum)%CTFCross(0) & ! Outside temp=inside temp for a partition
/( Construct(ConstrNum)%CTFInside(0) & ! Cond term (both partition sides same temp)
+HConvIn(SurfNum) ) ! Convection and damping term
RadSysTiHBQsrcCoef(SurfNum) = Construct(ConstrNum)%CTFSourceIn(0) & ! QTF term for the source
/( Construct(ConstrNum)%CTFInside(0) & ! Cond term (both partition sides same temp)
+HConvIn(SurfNum) ) ! Convection and damping term
IF (Surface(SurfNum)%ExtBoundCond > 0) THEN ! This is an interzone partition and we need to set outside params
! The inside coefficients of one side are equal to the outside coefficients of the other side. But,
! the inside coefficients are set up once the heat balance equation for that side has been calculated.
! For both sides to actually have been set, we have to wait until we get to the second side in the surface
! derived type. At that point, both inside coefficient sets have been evaluated.
IF (Surface(SurfNum)%ExtBoundCond < SurfNum) THEN ! Both of the inside coefficients have now been set
OtherSideSurfNum = Surface(SurfNum)%ExtBoundCond
RadSysToHBConstCoef(OtherSideSurfNum) = RadSysTiHBConstCoef(SurfNum)
RadSysToHBTinCoef(OtherSideSurfNum) = RadSysTiHBToutCoef(SurfNum)
RadSysToHBQsrcCoef(OtherSideSurfNum) = RadSysTiHBQsrcCoef(SurfNum)
RadSysToHBConstCoef(SurfNum) = RadSysTiHBConstCoef(OtherSideSurfNum)
RadSysToHBTinCoef(SurfNum) = RadSysTiHBToutCoef(OtherSideSurfNum)
RadSysToHBQsrcCoef(SurfNum) = RadSysTiHBQsrcCoef(OtherSideSurfNum)
END IF
END IF
END IF
Else If(Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_CondFD .OR. &
Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_HAMT) THEN
IF(Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_HAMT) THEN
IF (Surface(SurfNum)%ExtBoundCond > 0) THEN
! HAMT get the correct other side zone zone air temperature --
OtherSideSurfNum = Surface(SurfNum)%ExtBoundCond
ZoneNum = Surface(SurfNum)%Zone
OtherSideZoneNum = Surface(OtherSideSurfNum)%Zone
TempOutsideAirFD(SurfNum)= MAT(OtherSideZoneNum)
ENDIF
CALL ManageHeatBalHAMT(SurfNum,TempSurfInTmp(SurfNum),TempSurfOutTmp)
ENDIF
If(Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_CondFD ) &
CALL ManageHeatBalFiniteDiff(SurfNum,TempSurfInTmp(SurfNum),TempSurfOutTmp)
TH(SurfNum,1,1) = TempSurfOutTmp
End If
TempSurfIn(SurfNum) = TempSurfInTmp(SurfNum)
ELSE ! Movable insulation present
IF (Construct(ConstrNum)%SourceSinkPresent.AND.FirstTime) &
CALL ShowSevereError('Movable insulation is not valid with embedded sources/sinks')
F1 = HMovInsul/( HMovInsul + HConvIn(SurfNum) + IterDampConst )
TempSurfIn(SurfNum) = ( CTFConstInPart(SurfNum) &
+QRadSWInAbs(SurfNum) &
+Construct(ConstrNum)%CTFCross(0)*TH(SurfNum,1,1) &
+F1*( QRadThermInAbs(SurfNum) &
+HConvIn(SurfNum)*RefAirTemp(SurfNum) & ! Convection from surface to zone air
+NetLWRadToSurf(SurfNum) &
+QHTRadSysSurf(SurfNum) &
+QHWBaseboardSurf(SurfNum) &
+QSteamBaseboardSurf(SurfNum) &
+QElecBaseboardSurf(SurfNum) &
+IterDampConst*TempInsOld(SurfNum) ) ) &
/( Construct(ConstrNum)%CTFInside(0) &
+HMovInsul - F1*HMovInsul )
TempSurfInTmp(SurfNum) = ( Construct(ConstrNum)%CTFInside(0) &
*TempSurfIn(SurfNum) &
+HMovInsul*TempSurfIn(SurfNum) &
-QRadSWInAbs(SurfNum) &
-CTFConstInPart(SurfNum) &
-Construct(ConstrNum)%CTFCross(0) &
*TH(SurfNum,1,1) ) &
/( HMovInsul )
! if any mixed heat transfer models in zone, apply limits to CTF result
IF (ANY(Surface(Zone(ZoneNum)%SurfaceFirst:Zone(ZoneNum)%SurfaceLast)%HeatTransferAlgorithm &
== HeatTransferModel_CondFD) .OR. &
ANY(Surface(Zone(ZoneNum)%SurfaceFirst:Zone(ZoneNum)%SurfaceLast)%HeatTransferAlgorithm &
== HeatTransferModel_HAMT) )&
THEN
TempSurfInTmp(SurfNum) = MAX(MinSurfaceTempLimit,MIN(MaxSurfaceTempLimit,TempSurfInTmp(SurfNum))) !Limit Check
ENDIF
END IF
ELSE ! Window
IF (Construct(ConstrNum)%SourceSinkPresent.AND.FirstTime) &
CALL ShowSevereError('Windows are not allowed to have embedded sources/sinks')
IF (SurfaceWindow(SurfNum)%OriginalClass == SurfaceClass_TDD_Diffuser) THEN ! Tubular daylighting device
! Lookup up the TDD:DOME object
PipeNum = FindTDDPipe(SurfNum)
SurfNum2 = TDDPipe(PipeNum)%Dome
Ueff = 1.0d0 / TDDPipe(PipeNum)%Reff
! Similar to opaque surface but outside surface temp of TDD:DOME is used, and no embedded sources/sinks.
! Absorbed shortwave radiation is treated similar to a regular window, but only 1 glass layer is allowed.
! = QRadSWwinAbs(SurfNum,1)/2.0
TempSurfInTmp(SurfNum) = ( QRadThermInAbs(SurfNum) & ! LW radiation from internal sources
+QRadSWwinAbs(SurfNum,1)/2.0d0 & ! SW radiation from internal sources and solar
+HConvIn(SurfNum)*RefAirTemp(SurfNum) & ! Convection from surface to zone air
+NetLWRadToSurf(SurfNum) & ! Net radiant exchange with other zone surfaces
+IterDampConst &
*TempInsOld(SurfNum) & ! Iterative damping term (for stability)
+Ueff*TH(SurfNum2,1,1) ) & ! Current conduction from the outside surface
/( Ueff & ! Coefficient for conduction (current time)
+HConvIn(SurfNum)+IterDampConst ) ! Convection and damping term
TempSurfIn(SurfNum) = TempSurfInTmp(SurfNum)
! Calculate window heat gain for TDD:DIFFUSER since this calculation is usually done in WindowManager
WinHeatGain(SurfNum) = WinTransSolar(SurfNum) & ! Transmitted solar
+ HConvIn(SurfNum) * Surface(SurfNum)%Area * (TempSurfIn(SurfNum) - RefAirTemp(SurfNum)) & ! Convection
+ Construct(Surface(SurfNum)%Construction)%InsideAbsorpThermal * Surface(SurfNum)%Area & ! IR exchange
* (Sigma * TempSurfIn(SurfNum)**4 - (SurfaceWindow(SurfNum)%IRfromParentZone + QHTRadSysSurf(SurfNum) + &
QHWBaseboardSurf(SurfNum) + QSteamBaseboardSurf(SurfNum) + QElecBaseboardSurf(SurfNum))) & ! IR
- QS(Surface(SurfNum)%Zone) * Surface(SurfNum)%Area * Construct(Surface(SurfNum)%Construction)%TransDiff
! Zone diffuse interior shortwave reflected back into the TDD
!fill out report vars for components of Window Heat Gain
WinGainConvGlazToZoneRep(SurfNum) = HConvIn(SurfNum) * Surface(SurfNum)%Area &
* (TempSurfIn(SurfNum) - RefAirTemp(SurfNum))
WinGainIRGlazToZoneRep(SurfNum) = Construct(Surface(SurfNum)%Construction)%InsideAbsorpThermal &
* Surface(SurfNum)%Area &
* (Sigma * TempSurfIn(SurfNum)**4 - (SurfaceWindow(SurfNum)%IRfromParentZone + QHTRadSysSurf(SurfNum) + &
QHWBaseboardSurf(SurfNum) + QSteamBaseboardSurf(SurfNum) + QElecBaseboardSurf(SurfNum)))
WinLossSWZoneToOutWinRep(SurfNum) = QS(Surface(SurfNum)%Zone) * Surface(SurfNum)%Area &
* Construct(Surface(SurfNum)%Construction)%TransDiff
IF(WinHeatGain(SurfNum) >= 0.0d0) THEN
WinHeatGainRep(SurfNum) = WinHeatGain(SurfNum)
WinHeatGainRepEnergy(SurfNum) = WinHeatGainRep(SurfNum) * TimeStepZone * SecInHour
ELSE
WinHeatLossRep(SurfNum) = -WinHeatGain(SurfNum)
WinHeatLossRepEnergy(SurfNum) = WinHeatLossRep(SurfNum) * TimeStepZone * SecInHour
END IF
TDDPipe(PipeNum)%HeatGain = WinHeatGainRep(SurfNum)
TDDPipe(PipeNum)%HeatLoss = WinHeatLossRep(SurfNum)
ELSE ! Regular window
IF(InsideSurfIterations == 0) THEN ! Do windows only once
IF(SurfaceWindow(SurfNum)%StormWinFlag==1) ConstrNum = Surface(SurfNum)%StormWinConstruction
! Get outside convection coeff for exterior window here to avoid calling
! InitExteriorConvectionCoeff from CalcWindowHeatBalance, which avoids circular reference
! (HeatBalanceSurfaceManager USEing and WindowManager and
! WindowManager USEing HeatBalanceSurfaceManager)
IF(Surface(SurfNum)%ExtBoundCond == ExternalEnvironment) THEN
RoughSurf = Material(Construct(ConstrNum)%LayerPoint(1))%Roughness
EmisOut = Material(Construct(ConstrNum)%LayerPoint(1))%AbsorpThermalFront
IF(SurfaceWindow(SurfNum)%ShadingFlag == ExtShadeOn .OR. SurfaceWindow(SurfNum)%ShadingFlag==ExtBlindOn .OR. &
SurfaceWindow(SurfNum)%ShadingFlag == ExtScreenOn) THEN
! Exterior shade in place
ConstrNumSh = SurfaceWindow(SurfNum)%ShadedConstruction
RoughSurf = Material(Construct(ConstrNumSh)%LayerPoint(1))%Roughness
EmisOut = Material(Construct(ConstrNumSh)%LayerPoint(1))%AbsorpThermal
END IF
! Get the outside effective emissivity for Equivalent layer model
IF ( Construct(ConstrNum)%WindowTypeEQL ) THEN
EmisOut = EQLWindowOutsideEffectiveEmiss(ConstrNum)
ENDIF
! Set Exterior Convection Coefficient...
IF (Surface(SurfNum)%ExtConvCoeff > 0) THEN
HcExtSurf(SurfNum)=SetExtConvectionCoeff(SurfNum)
ELSEIF (Surface(SurfNum)%ExtWind) THEN ! Window is exposed to wind (and possibly rain)
! Calculate exterior heat transfer coefficients with windspeed (windspeed is calculated internally in subroutine)
CALL InitExteriorConvectionCoeff(SurfNum,0.0d0,RoughSurf,EmisOut,TH(SurfNum,1,1), &
HcExtSurf(SurfNum),HSkyExtSurf(SurfNum),HGrdExtSurf(SurfNum),HAirExtSurf(SurfNum))
IF (IsRain) THEN ! Raining: since wind exposed, outside window surface gets wet
HcExtSurf(SurfNum)=1000.0d0 ! Reset HcExtSurf because of wetness
ENDIF
ELSE ! Not Wind exposed
! Calculate exterior heat transfer coefficients for windspeed = 0
CALL InitExteriorConvectionCoeff(SurfNum,0.0d0,RoughSurf,EmisOut,TH(SurfNum,1,1), &
HcExtSurf(SurfNum),HSkyExtSurf(SurfNum),HGrdExtSurf(SurfNum),HAirExtSurf(SurfNum))
END IF
ELSE ! Interior Surface
IF (Surface(SurfNum)%ExtConvCoeff > 0) THEN
HcExtSurf(SurfNum)=SetExtConvectionCoeff(SurfNum)
ELSE
! Exterior Convection Coefficient for the Interior or Interzone Window is the Interior Convection Coeff of same
HcExtSurf(SurfNum)=HConvIn(Surface(SurfNum)%ExtBoundCond)
ENDIF
ENDIF
! Following call determines inside surface temperature of glazing, and of
! frame and/or divider, if present
CALL CalcWindowHeatBalance(SurfNum,HcExtSurf(SurfNum),TempSurfInTmp(SurfNum),TH(SurfNum,1,1))
IF(WinHeatGain(SurfNum) >= 0.0d0) THEN
WinHeatGainRep(SurfNum) = WinHeatGain(SurfNum)
WinHeatGainRepEnergy(SurfNum) = WinHeatGainRep(SurfNum) * TimeStepZone * SecInHour
ELSE
WinHeatLossRep(SurfNum) = -WinHeatGain(SurfNum)
WinHeatLossRepEnergy(SurfNum) = WinHeatLossRep(SurfNum) * TimeStepZone * SecInHour
END IF
TempSurfIn(SurfNum) = TempSurfInTmp(SurfNum)
END IF
END IF
END IF
END IF ! ...end of inside surface heat balance equation selection
TH(SurfNum,1,2) = TempSurfIn(SurfNum)
TempSurfInRep(SurfNum) = TempSurfIn(SurfNum)
TempSurfOut(SurfNum) = TH(SurfNum,1,1) ! For reporting
! sign convention is positive means energy going into inside face from the air.
QdotConvInRep(surfNum) = - Surface(SurfNum)%Area * HConvIn(SurfNum) * (TempSurfIn(SurfNum)-RefAirTemp(SurfNum))
QdotConvInRepPerArea(surfNum) = - HConvIn(SurfNum) * (TempSurfIn(SurfNum)-RefAirTemp(SurfNum))
QConvInReport(surfNum) = QdotConvInRep(surfNum)* SecInHour * TimeStepZone
! The QdotConvInRep which is called "Surface Inside Face Convection Heat Gain" is stored during
! sizing for both the normal and pulse cases so that load components can be derived later.
IF (ZoneSizingCalc .AND. CompLoadReportIsReq) THEN
IF (.NOT. WarmupFlag) THEN
TimeStepInDay = (HourOfDay-1)*NumOfTimeStepInHour + TimeStep
IF (isPulseZoneSizing) THEN
loadConvectedWithPulse(surfNum,TimeStepInDay,CurOverallSimDay) = QdotConvInRep(surfNum)
ELSE
loadConvectedNormal(surfNum,TimeStepInDay,CurOverallSimDay) = QdotConvInRep(surfNum)
netSurfRadSeq(surfNum,TimeStepInDay,CurOverallSimDay) = QdotRadNetSurfInRep(surfNum)
END IF
END IF
END IF
IF (SurfaceWindow(SurfNum)%OriginalClass == SurfaceClass_TDD_Diffuser) THEN ! Tubular daylighting device
! Tubular daylighting devices are treated as one big object with an effective R value.
! The outside face temperature of the TDD:DOME and the inside face temperature of the
! TDD:DIFFUSER are calculated with the outside and inside heat balances respectively.
!
! Below, the resulting temperatures are copied to the inside face of the TDD:DOME
! and the outside face of the TDD:DIFFUSER for reporting.
! Set inside temp variables of TDD:DOME equal to inside temp of TDD:DIFFUSER
TH(SurfNum2,1,2) = TempSurfIn(SurfNum)
TempSurfIn(SurfNum2) = TempSurfIn(SurfNum)
TempSurfInTmp(SurfNum2) = TempSurfIn(SurfNum)
TempSurfInRep(SurfNum2) = TempSurfIn(SurfNum)
! Set outside temp reporting variable of TDD:DOME (since it gets skipped otherwise)
TempSurfOut(SurfNum2) = TH(SurfNum2,1,1)
! Reset outside temp variables of TDD:DIFFUSER equal to outside temp of TDD:DOME
TH(SurfNum,1,1) = TH(SurfNum2,1,1)
TempSurfOut(SurfNum) = TH(SurfNum2,1,1)
END IF
IF ((TH(SurfNum,1,2) > MaxSurfaceTempLimit) .OR. &
(TH(SurfNum,1,2) < MinSurfaceTempLimit) ) THEN
IF (WarmupFlag) WarmupSurfTemp=WarmupSurfTemp+1
IF (.not. WarmupFlag .or. (WarmupFlag .and. WarmupSurfTemp > 10) .or. DisplayExtraWarnings) THEN
IF (TH(SurfNum,1,2) < MinSurfaceTempLimit) THEN
IF (Surface(SurfNum)%LowTempErrCount == 0) THEN
CALL ShowSevereMessage('Temperature (low) out of bounds ['//TRIM(RoundSigDigits(TH(SurfNum,1,2),2))// &
'] for zone="'//trim(Zone(ZoneNum)%Name)//'", for surface="'//TRIM(Surface(SurfNum)%Name)//'"')
CALL ShowContinueErrorTimeStamp(' ')
IF (.not. Zone(ZoneNum)%TempOutOfBoundsReported) THEN
CALL ShowContinueError('Zone="'//trim(Zone(ZoneNum)%Name)//'", Diagnostic Details:')
IF (Zone(ZoneNum)%FloorArea > 0.0d0) THEN
CALL ShowContinueError('...Internal Heat Gain ['// &
trim(RoundSigDigits(Zone(ZoneNum)%InternalHeatGains/Zone(ZoneNum)%FloorArea,3))//'] W/m2')
ELSE
CALL ShowContinueError('...Internal Heat Gain (no floor) ['// &
trim(RoundSigDigits(Zone(ZoneNum)%InternalHeatGains,3))//'] W')
ENDIF
IF (SimulateAirflowNetwork <= AirflowNetworkControlSimple) THEN
CALL ShowContinueError('...Infiltration/Ventilation ['// &
trim(RoundSigDigits(Zone(ZoneNum)%NominalInfilVent,3))//'] m3/s')
CALL ShowContinueError('...Mixing/Cross Mixing ['// &
trim(RoundSigDigits(Zone(ZoneNum)%NominalMixing,3))//'] m3/s')
ELSE
CALL ShowContinueError('...Airflow Network Simulation: Nominal Infiltration/Ventilation/Mixing not available.')
ENDIF
IF (Zone(ZoneNum)%isControlled) THEN
CALL ShowContinueError('...Zone is part of HVAC controlled system.')
ELSE
CALL ShowContinueError('...Zone is not part of HVAC controlled system.')
ENDIF
Zone(ZoneNum)%TempOutOfBoundsReported=.true.
ENDIF
CALL ShowRecurringSevereErrorAtEnd('Temperature (low) out of bounds for zone='//trim(Zone(ZoneNum)%Name)// &
' for surface='//TRIM(Surface(SurfNum)%Name), &
Surface(SurfNum)%LowTempErrCount,ReportMaxOf=TH(SurfNum,1,2),ReportMaxUnits='C', &
ReportMinOf=TH(SurfNum,1,2),ReportMinUnits='C')
ELSE
CALL ShowRecurringSevereErrorAtEnd('Temperature (low) out of bounds for zone='//trim(Zone(ZoneNum)%Name)// &
' for surface='//TRIM(Surface(SurfNum)%Name), &
Surface(SurfNum)%LowTempErrCount,ReportMaxOf=TH(SurfNum,1,2),ReportMaxUnits='C', &
ReportMinOf=TH(SurfNum,1,2),ReportMinUnits='C')
ENDIF
ELSE
IF (Surface(SurfNum)%HighTempErrCount == 0) THEN
CALL ShowSevereMessage('Temperature (high) out of bounds ('//TRIM(RoundSigDigits(TH(SurfNum,1,2),2))// &
'] for zone="'//trim(Zone(ZoneNum)%Name)//'", for surface="'//TRIM(Surface(SurfNum)%Name)//'"')
CALL ShowContinueErrorTimeStamp(' ')
IF (.not. Zone(ZoneNum)%TempOutOfBoundsReported) THEN
CALL ShowContinueError('Zone="'//trim(Zone(ZoneNum)%Name)//'", Diagnostic Details:')
IF (Zone(ZoneNum)%FloorArea > 0.0d0) THEN
CALL ShowContinueError('...Internal Heat Gain ['// &
trim(RoundSigDigits(Zone(ZoneNum)%InternalHeatGains/Zone(ZoneNum)%FloorArea,3))//'] W/m2')
ELSE
CALL ShowContinueError('...Internal Heat Gain (no floor) ['// &
trim(RoundSigDigits(Zone(ZoneNum)%InternalHeatGains,3))//'] W')
ENDIF
IF (SimulateAirflowNetwork <= AirflowNetworkControlSimple) THEN
CALL ShowContinueError('...Infiltration/Ventilation ['// &
trim(RoundSigDigits(Zone(ZoneNum)%NominalInfilVent,3))//'] m3/s')
CALL ShowContinueError('...Mixing/Cross Mixing ['// &
trim(RoundSigDigits(Zone(ZoneNum)%NominalMixing,3))//'] m3/s')
ELSE
CALL ShowContinueError('...Airflow Network Simulation: Nominal Infiltration/Ventilation/Mixing not available.')
ENDIF
IF (Zone(ZoneNum)%isControlled) THEN
CALL ShowContinueError('...Zone is part of HVAC controlled system.')
ELSE
CALL ShowContinueError('...Zone is not part of HVAC controlled system.')
ENDIF
Zone(ZoneNum)%TempOutOfBoundsReported=.true.
ENDIF
CALL ShowRecurringSevereErrorAtEnd('Temperature (high) out of bounds for zone='//trim(Zone(ZoneNum)%Name)// &
' for surface='//TRIM(Surface(SurfNum)%Name), &
Surface(SurfNum)%HighTempErrCount,ReportMaxOf=TH(SurfNum,1,2),ReportMaxUnits='C', &
ReportMinOf=TH(SurfNum,1,2),ReportMinUnits='C')
ELSE
CALL ShowRecurringSevereErrorAtEnd('Temperature (high) out of bounds for zone='//trim(Zone(ZoneNum)%Name)// &
' for surface='//TRIM(Surface(SurfNum)%Name), &
Surface(SurfNum)%HighTempErrCount,ReportMaxOf=TH(SurfNum,1,2),ReportMaxUnits='C', &
ReportMinOf=TH(SurfNum,1,2),ReportMinUnits='C')
ENDIF
ENDIF
IF (Zone(ZoneNum)%EnforcedReciprocity) THEN
IF (WarmupSurfTemp > 3) THEN
CALL ShowSevereError('CalcHeatBalanceInsideSurf: Zone="'//trim(Zone(ZoneNum)%Name)// &
'" has view factor enforced reciprocity')
CALL ShowContinueError(' and is having temperature out of bounds errors. Please correct zone geometry and rerun.')
CALL ShowFatalError('CalcHeatBalanceInsideSurf: Program terminates due to preceding conditions.')
ENDIF
ELSEIF (WarmupSurfTemp > 10) THEN
CALL ShowFatalError('CalcHeatBalanceInsideSurf: Program terminates due to preceding conditions.')
ENDIF
END IF
END IF
IF ((TH(SurfNum,1,2) > MaxSurfaceTempLimitBeforeFatal) .OR. &
(TH(SurfNum,1,2) < MinSurfaceTempLimitBeforeFatal) ) THEN
IF (.not. WarmupFlag) THEN
IF (TH(SurfNum,1,2) < MinSurfaceTempLimitBeforeFatal) THEN
CALL ShowSevereError('Temperature (low) out of bounds ['//TRIM(RoundSigDigits(TH(SurfNum,1,2),2))// &
'] for zone="'//trim(Zone(ZoneNum)%Name)//'", for surface="'//TRIM(Surface(SurfNum)%Name)//'"')
CALL ShowContinueErrorTimeStamp(' ')
IF (.not. Zone(ZoneNum)%TempOutOfBoundsReported) THEN
CALL ShowContinueError('Zone="'//trim(Zone(ZoneNum)%Name)//'", Diagnostic Details:')
IF (Zone(ZoneNum)%FloorArea > 0.0d0) THEN
CALL ShowContinueError('...Internal Heat Gain ['// &
trim(RoundSigDigits(Zone(ZoneNum)%InternalHeatGains/Zone(ZoneNum)%FloorArea,3))//'] W/m2')
ELSE
CALL ShowContinueError('...Internal Heat Gain (no floor) ['// &
trim(RoundSigDigits(Zone(ZoneNum)%InternalHeatGains/Zone(ZoneNum)%FloorArea,3))//'] W')
ENDIF
IF (SimulateAirflowNetwork <= AirflowNetworkControlSimple) THEN
CALL ShowContinueError('...Infiltration/Ventilation ['// &
trim(RoundSigDigits(Zone(ZoneNum)%NominalInfilVent,3))//'] m3/s')
CALL ShowContinueError('...Mixing/Cross Mixing ['// &
trim(RoundSigDigits(Zone(ZoneNum)%NominalMixing,3))//'] m3/s')
ELSE
CALL ShowContinueError('...Airflow Network Simulation: Nominal Infiltration/Ventilation/Mixing not available.')
ENDIF
IF (Zone(ZoneNum)%isControlled) THEN
CALL ShowContinueError('...Zone is part of HVAC controlled system.')
ELSE
CALL ShowContinueError('...Zone is not part of HVAC controlled system.')
ENDIF
Zone(ZoneNum)%TempOutOfBoundsReported=.true.
ENDIF
CALL ShowFatalError('Program terminates due to preceding condition.')
ELSE
CALL ShowSevereError('Temperature (high) out of bounds ['//TRIM(RoundSigDigits(TH(SurfNum,1,2),2))// &
'] for zone="'//trim(Zone(ZoneNum)%Name)//'", for surface="'//TRIM(Surface(SurfNum)%Name)//'"')
CALL ShowContinueErrorTimeStamp(' ')
IF (.not. Zone(ZoneNum)%TempOutOfBoundsReported) THEN
CALL ShowContinueError('Zone="'//trim(Zone(ZoneNum)%Name)//'", Diagnostic Details:')
IF (Zone(ZoneNum)%FloorArea > 0.0d0) THEN
CALL ShowContinueError('...Internal Heat Gain ['// &
trim(RoundSigDigits(Zone(ZoneNum)%InternalHeatGains/Zone(ZoneNum)%FloorArea,3))//'] W/m2')
ELSE
CALL ShowContinueError('...Internal Heat Gain (no floor) ['// &
trim(RoundSigDigits(Zone(ZoneNum)%InternalHeatGains/Zone(ZoneNum)%FloorArea,3))//'] W')
ENDIF
IF (SimulateAirflowNetwork <= AirflowNetworkControlSimple) THEN
CALL ShowContinueError('...Infiltration/Ventilation ['// &
trim(RoundSigDigits(Zone(ZoneNum)%NominalInfilVent,3))//'] m3/s')
CALL ShowContinueError('...Mixing/Cross Mixing ['// &
trim(RoundSigDigits(Zone(ZoneNum)%NominalMixing,3))//'] m3/s')
ELSE
CALL ShowContinueError('...Airflow Network Simulation: Nominal Infiltration/Ventilation/Mixing not available.')
ENDIF
IF (Zone(ZoneNum)%isControlled) THEN
CALL ShowContinueError('...Zone is part of HVAC controlled system.')
ELSE
CALL ShowContinueError('...Zone is not part of HVAC controlled system.')
ENDIF
Zone(ZoneNum)%TempOutOfBoundsReported=.true.
ENDIF
CALL ShowFatalError('Program terminates due to preceding condition.')
ENDIF
END IF
END IF
END DO ! ...end of loop over all surfaces for inside heat balances
! Interzone surface updating: interzone surfaces have other side temperatures
! which can vary as the simulation iterates through the inside heat
! balance. This block is intended to "lock" the opposite side (outside)
! temperatures to the correct value, namely the value calculated by the
! inside surface heat balance for the other side.
DO SurfNum = 1, TotSurfaces
IF (PRESENT(ZoneToResimulate)) THEN
IF ((Surface(SurfNum)%Zone /= ZoneToResimulate) .AND. (AdjacentZoneToSurface(SurfNum) /= ZoneToResimulate)) THEN
CYCLE ! skip surfaces that are not associated with this zone
ENDIF
ENDIF
! Interzones must have an exterior boundary condition greater than zero
! (meaning that the other side is a surface) and the surface number must
! not be the surface itself (which is just a simple partition)
IF ( (Surface(SurfNum)%ExtBoundCond > 0) .AND. (Surface(SurfNum)%ExtBoundCond /= SurfNum) ) THEN
! Set the outside surface temperature to the inside surface temperature
! of the interzone pair and reassign the reporting variable. By going
! through all of the surfaces, this should pick up the other side as well
! as affect the next iteration.
TH(SurfNum,1,1) = TH(Surface(SurfNum)%ExtBoundCond,1,2)
TempSurfOut(SurfNum) = TH(SurfNum,1,1)
END IF
END DO
InsideSurfIterations = InsideSurfIterations + 1
! Convergence check
MaxDelTemp = 0.0d0
DO SurfNum = 1, TotSurfaces ! Loop through all surfaces to check for convergence...
IF (.NOT. Surface(SurfNum)%HeatTransSurf) CYCLE ! Skip non-heat transfer surfaces
IF (PRESENT(ZoneToResimulate)) THEN
IF ((Surface(SurfNum)%Zone /= ZoneToResimulate) .AND. (AdjacentZoneToSurface(SurfNum) /= ZoneToResimulate)) THEN
CYCLE ! skip surfaces that are not associated with this zone
ENDIF
ENDIF
ConstrNum = Surface(SurfNum)%Construction
IF(Construct(ConstrNum)%TransDiff <= 0.0d0) THEN ! Opaque surface
MaxDelTemp = MAX(ABS(TempSurfIn(SurfNum)-TempInsOld(SurfNum)),MaxDelTemp)
IF (Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_CondFD) THEN
! also check all internal nodes as well as surface faces
MaxDelTemp = MAX(MaxDelTemp, SurfaceFD(SurfNum)%MaxNodeDelTemp)
ENDIF
END IF
END DO ! ...end of loop to check for convergence
IF (.NOT. ANY(HeatTransferAlgosUsed == UseCondFD)) THEN
IF (MaxDelTemp <= MaxAllowedDelTemp) Converged = .TRUE.
ELSE
IF (MaxDelTemp <= MaxAllowedDelTempCondFD) Converged = .TRUE.
!Feb2012 IF ((InsideSurfIterations > IterationsForCondFDRelaxChange) .and. (.NOT. Converged) .AND. &
!Feb2012 (.NOT. CondFDVariableProperties) ) THEN
!Feb2012 ! adjust relaxation factor down, assume large number of iterations is result of instability
!Feb2012 CondFDRelaxFactor = CondFDRelaxFactor * 0.9d0
!Feb2012 IF (CondFDRelaxFactor < 0.2d0) CondFDRelaxFactor = 0.2d0
! resets relaxation factor to speed up iterations when under-relaxatation is not needed.
IF (InsideSurfIterations <=1) THEN
CondFDRelaxFactor=CondFDRelaxFactorInput
ENDIF
IF ((InsideSurfIterations > IterationsForCondFDRelaxChange) .and. .not. Converged) THEN
! adjust relaxation factor down, assume large number of iterations is result of instability
CondFDRelaxFactor = CondFDRelaxFactor * 0.9d0
IF (CondFDRelaxFactor < 0.1d0) CondFDRelaxFactor = 0.1d0
ENDIF
ENDIF
#ifdef EP_Count_Calls
NumMaxInsideSurfIterations=MAX(NumMaxInsideSurfIterations,InsideSurfIterations)
#endif
IF (InsideSurfIterations < MinIterations) Converged = .FALSE.
IF (InsideSurfIterations > MaxIterations) THEN
IF (.NOT.WarmupFlag) THEN
ErrCount=ErrCount+1
IF (ErrCount < 16) THEN
IF (.NOT. ANY(HeatTransferAlgosUsed == UseCondFD)) THEN
CALL ShowWarningError('Inside surface heat balance did not converge '// &
'with Max Temp Difference [C] ='//TRIM(RoundSigDigits(MaxDelTemp,3))// &
' vs Max Allowed Temp Diff [C] ='//TRIM(RoundSigDigits(MaxAllowedDelTemp,3)))
CALL ShowContinueErrorTimeStamp(' ')
ELSE
CALL ShowWarningError('Inside surface heat balance did not converge '// &
'with Max Temp Difference [C] ='//TRIM(RoundSigDigits(MaxDelTemp,3))// &
' vs Max Allowed Temp Diff [C] ='//TRIM(RoundSigDigits(MaxAllowedDelTempCondFD,6)))
CALL ShowContinueErrorTimeStamp(' ')
ENDIF
ELSE
CALL ShowRecurringWarningErrorAtEnd('Inside surface heat balance convergence problem continues', &
InsideSurfErrCount,ReportMaxOf=MaxDelTemp,ReportMinOf=MaxDelTemp, &
ReportMaxUnits='[C]',ReportMinUnits='[C]')
ENDIF
ENDIF
EXIT ! DO loop
END IF
END DO ! ...end of main inside heat balance DO loop (ends when Converged)
! Update SumHmXXXX
IF ( ANY(HeatTransferAlgosUsed == UseCondFD) .OR. &
ANY(HeatTransferAlgosUsed == UseEMPD) .OR. ANY(HeatTransferAlgosUsed == UseHAMT)) THEN
DO SurfNum = 1, TotSurfaces
IF (.NOT. Surface(SurfNum)%HeatTransSurf) CYCLE ! Skip non-heat transfer surfaces
IF (Surface(SurfNum)%Class == SurfaceClass_Window) CYCLE
ZoneNum = Surface(SurfNum)%Zone
IF (PRESENT(ZoneToResimulate)) THEN
IF ((ZoneNum /= ZoneToResimulate) .AND. (AdjacentZoneToSurface(SurfNum) /= ZoneToResimulate)) THEN
CYCLE ! skip surfaces that are not associated with this zone
ENDIF
ENDIF
IF(Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_HAMT) THEN
CALL UpdateHeatBalHAMT(SurfNum)
SumHmAW(ZoneNum)= SumHmAW(ZoneNum)+HMassConvInFD(SurfNum)*Surface(SurfNum)%Area* &
(RhoVaporSurfIn(SurfNum)-RhoVaporAirIn(SurfNum))
RhoAirZone=PsyRhoAirFnPbTdbW(OutBaroPress,Mat(Surface(SurfNum)%Zone),PsyWFnTdbRhPb(Mat(Surface(SurfNum)%Zone), &
PsyRhFnTdbRhov(Mat(Surface(SurfNum)%Zone),RhoVaporAirIn(SurfNum),'RhoAirZone'),OutBaroPress))
Wsurf=PsyWFnTdbRhPb(TempSurfInTmp(SurfNum), &
PsyRhFnTdbRhov(TempSurfInTmp(SurfNum),RhoVaporSurfIn(SurfNum),'Wsurf'),OutBaroPress)
SumHmARa(ZoneNum)= SumHmARa(ZoneNum)+HMassConvInFD(SurfNum)*Surface(SurfNum)%Area*RhoAirZone
SumHmARaW(ZoneNum)= SumHmARaW(ZoneNum)+HMassConvInFD(SurfNum)*Surface(SurfNum)%Area*RhoAirZone*Wsurf
ENDIF
IF (Surface(SurfNum)%HeatTransferAlgorithm == HeatTransferModel_EMPD) THEN
! need to calculate the amount of moisture that is entering or
! leaving the zone Qm [kg/sec] = hmi * Area * (Del Rhov)
! {Hmi [m/sec]; Area [m2]; Rhov [kg moist/m3] }
! Positive values are into the zone and negative values are
! leaving the zone. SumHmAw is the sum of the moisture entering or
! leaving the zone from all of the surfaces and is a rate. Multiply
! by time to get the actual amount affecting the zone volume of air.
CALL UpdateMoistureBalanceEMPD(SurfNum)
RhoVaporSurfIn(SurfNum) = MoistEMPDNew(SurfNum)
!SUMC(ZoneNum) = SUMC(ZoneNum)-MoistEMPDFlux(SurfNum)*Surface(SurfNum)%Area
SumHmAW(ZoneNum)= SumHmAW(ZoneNum)+HMassConvInFD(SurfNum)*Surface(SurfNum)%Area* &
(RhoVaporSurfIn(SurfNum)-RhoVaporAirIn(SurfNum))
SumHmARa(ZoneNum)= SumHmARa(ZoneNum)+HMassConvInFD(SurfNum)*Surface(SurfNum)%Area* &
PsyRhoAirFnPbTdbW(OutBaroPress, &
TempSurfInTmp(SurfNum), &
PsyWFnTdbRhPb(TempSurfInTmp(SurfNum), &
PsyRhFnTdbRhovLBnd0C(TempSurfInTmp(SurfNum), &
RhoVaporAirIn(SurfNum)), &
OutBaroPress))
SumHmARaW(ZoneNum)= SumHmARaW(ZoneNum)+HMassConvInFD(SurfNum)*Surface(SurfNum)%Area*RhoVaporSurfIn(SurfNum)
END IF
END DO
ENDIF
! Calculate ZoneWinHeatGain/Loss
IF (.not. PartialResimulate) THEN
ZoneWinHeatGain =0.d0
ZoneWinHeatGainRep =0.d0
ZoneWinHeatGainRepEnergy=0.d0
ZoneWinHeatLossRep =0.d0
ZoneWinHeatLossRepEnergy=0.d0
ELSE
ZoneWinHeatGain(ZoneToResimulate) =0.d0
ZoneWinHeatGainRep(ZoneToResimulate) =0.d0
ZoneWinHeatGainRepEnergy(ZoneToResimulate)=0.d0
ZoneWinHeatLossRep(ZoneToResimulate) =0.d0
ZoneWinHeatLossRepEnergy(ZoneToResimulate)=0.d0
ENDIF
DO SurfNum=1,TotSurfaces
IF(.not. Surface(SurfNum)%ExtSolar) CYCLE ! WindowManager's definition of ZoneWinHeatGain/Loss
IF(Surface(SurfNum)%Class /= SurfaceClass_Window) CYCLE
ZoneNum=Surface(SurfNum)%Zone
IF (ZoneNum == 0) CYCLE
IF (PRESENT(ZoneToResimulate)) THEN
IF ((ZoneNum /= ZoneToResimulate) .AND. (AdjacentZoneToSurface(SurfNum) /= ZoneToResimulate)) THEN
CYCLE ! skip surfaces that are not associated with this zone
ENDIF
ENDIF
ZoneWinHeatGain(ZoneNum) = ZoneWinHeatGain(ZoneNum) + WinHeatGain(SurfNum)
ENDDO
DO ZoneNum = 1,NumOfZones
IF ( PRESENT(ZoneToResimulate) .AND. (ZoneNum /= ZoneToResimulate)) CYCLE
IF(ZoneWinHeatGain(ZoneNum) >= 0.0d0) THEN
ZoneWinHeatGainRep(ZoneNum) = ZoneWinHeatGain(ZoneNum)
ZoneWinHeatGainRepEnergy(ZoneNum) = ZoneWinHeatGainRep(ZoneNum) * TimeStepZone * SecInHour
ELSE
ZoneWinHeatLossRep(ZoneNum) = -ZoneWinHeatGain(ZoneNum)
ZoneWinHeatLossRepEnergy(ZoneNum) = ZoneWinHeatLossRep(ZoneNum) * TimeStepZone * SecInHour
END IF
END DO
IF (PRESENT(ZoneToResimulate)) THEN
CALL CalculateZoneMRT(ZoneToResimulate) ! Update here so that the proper value of MRT is available to radiant systems
ELSE
CALL CalculateZoneMRT ! Update here so that the proper value of MRT is available to radiant systems
ENDIF
FirstTime = .FALSE.
RETURN
END SUBROUTINE CalcHeatBalanceInsideSurf