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) | :: | LoopNum | |||
real(kind=r64), | intent(in) | :: | SystemMassFlow | |||
integer, | intent(in) | :: | PumpCurveNum | |||
real(kind=r64), | intent(in) | :: | PumpSpeed | |||
real(kind=r64), | intent(in) | :: | PumpImpellerDia | |||
real(kind=r64), | intent(in) | :: | MinPhi | |||
real(kind=r64), | intent(in) | :: | MaxPhi |
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.
REAL(r64) FUNCTION ResolveLoopFlowVsPressure(LoopNum, SystemMassFlow, PumpCurveNum, &
PumpSpeed, PumpImpellerDia, MinPhi, MaxPhi) RESULT (ResolvedLoopMassFlowRate)
! FUNCTION INFORMATION:
! AUTHOR Kaustubh Phalak
! DATE WRITTEN Feb 2010
! MODIFIED na
! RE-ENGINEERED na
! PURPOSE OF THIS FUNCTION:
! To provide a means to simulate a constant speed pump curve and system curve to
! find a more realistic operating point for the plant.
! METHODOLOGY EMPLOYED:
! Pressure drop of complete loop is found for a perticular flow rate.
! i.e. pressuredrop = K * massflow ^ 2
! System curve is then solved with pump curve already entered
! and flow rate provided by the pump will be calculated.
! This routine does not trap for errors if a pressure simulation is not to be performed.
! Calling routine should only call this if needed.
! REFERENCES:
! -
! USE STATEMENTS:
USE General, ONLY: RoundSigDigits
USE DataPlant, ONLY: PlantLoop, SupplySide
USE DataLoopNode, ONLY: Node
USE FluidProperties, ONLY: GetDensityGlycol, GetViscosityGlycol
USE CurveManager, ONLY: CurveValue
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! FUNCTION ARGUMENT DEFINITIONS:
INTEGER, INTENT(IN) :: LoopNum !- Index of which plant/condenser loop is being simulated
REAL(r64), INTENT(IN) :: SystemMassFlow !- Initial "guess" at system mass flow rate [kg/s]
INTEGER, INTENT(IN) :: PumpCurveNum !- Pump curve to use when calling the curve manager for psi = f(phi)
REAL(r64), INTENT(IN) :: PumpSpeed !- Pump rotational speed, [rps] (revs per second)
REAL(r64), INTENT(IN) :: PumpImpellerDia !- Nominal pump impeller diameter [m]
REAL(r64), INTENT(IN) :: MinPhi !- Minimum allowable value of phi, requested by the pump manager from curve mgr
REAL(r64), INTENT(IN) :: MaxPhi !- Maximum allowable value of phi, requested by the pump manager from curve mgr
! FUNCTION PARAMETER DEFINITIONS:
CHARACTER(len=*), PARAMETER :: RoutineName = 'ResolvedLoopMassFlowRate: '
INTEGER, PARAMETER :: MaxIters = 100
CHARACTER(LEN=*), PARAMETER :: DummyFluidName = ' '
REAL(r64), PARAMETER :: PressureConvergeCriteria = 0.1d0 !Pa
REAL(r64), PARAMETER :: ZeroTolerance = 0.0001d0
! INTERFACE BLOCK SPECIFICATIONS:
! na
! DERIVED TYPE DEFINITIONS:
! na
! FUNCTION LOCAL VARIABLE DECLARATIONS:
REAL(r64) :: PumpPressureRise
Real(r64) :: NodeTemperature
Real(r64) :: NodeDensity
REAL(r64) :: SystemPressureDrop
REAL(r64) :: PhiPump
REAL(r64) :: PhiSystem
REAL(r64) :: PsiPump
INTEGER :: FluidIndex
INTEGER :: Iteration
REAL(r64) :: LocalSystemMassFlow
REAL(r64) :: LoopEffectiveK
LOGICAL :: Converged
INTEGER, SAVE :: ZeroKWarningCounter = 0
INTEGER, SAVE :: MaxIterWarningCounter = 0
REAL(r64), DIMENSION(3) :: MassFlowIterativeHistory
REAL(r64) :: MdotDeltaLatest
REAL(r64) :: MdotDeltaPrevious
REAL(r64) :: DampingFactor
!Get loop level data
FluidIndex = PlantLoop(LoopNum)%FluidIndex
LoopEffectiveK = PlantLoop(LoopNum)%PressureEffectiveK
SystemPressureDrop = LoopEffectiveK * SystemMassFlow **2.0d0
!Read data off the node data structure
NodeTemperature = Node(PlantLoop(LoopNum)%LoopSide(SupplySide)%NodeNumIn)%Temp
NodeDensity = GetDensityGlycol(DummyFluidName, NodeTemperature, FluidIndex, RoutineName)
!Store the passed in (requested, design) flow to the local value for performing iterations
LocalSystemMassFlow = SystemMassFlow
!Check and warn if invalid condition exists
IF (LoopEffectiveK .LE. ZeroTolerance) THEN
ZeroKWarningCounter = ZeroKWarningCounter + 1
IF (ZeroKWarningCounter == 1) THEN
CALL ShowWarningError('Pump pressure-flow resolution attempted, but invalid loop conditions encountered.')
CALL ShowContinueError('Loop being calculated: '//PlantLoop(LoopNum)%Name)
CALL ShowContinueError('An invalid pressure/flow condition existed which resulted in the approximation of')
CALL ShowContinueError('the pressure coefficient K to be zero. The pressure simulation will use the requested (design)')
CALL ShowContinueError('pump flow in order to proceed with the simulation. This warning is only issued once.')
END IF
ResolvedLoopMassFlowRate = SystemMassFlow
RETURN
END IF
!Initialize flag
Converged = .FALSE.
!Initialize the mass flow history array and damping factor
MassFlowIterativeHistory = LocalSystemMassFlow
DampingFactor = 0.9d0
!Start Convergence Loop
DO Iteration = 1, MaxIters
!Calculate System Mass Flow Rate
LocalSystemMassFlow = SQRT(SystemPressureDrop / LoopEffectiveK)
MassFlowIterativeHistory = EOSHIFT(MassFlowIterativeHistory, SHIFT=-1, BOUNDARY=LocalSystemMassFlow)
PhiSystem = LocalSystemMassFlow / (NodeDensity * PumpSpeed * PumpImpellerDia)
!4th order polynomial for non-dimensional pump curve
PhiPump = PhiSystem
!Constrain the value to the valid region
PhiPump = MAX(PhiPump,MinPhi)
PhiPump = MIN(PhiPump,MaxPhi)
!Get the pump curve value from the curve manager
PsiPump = CurveValue(PumpCurveNum, PhiPump)
!Calcuate Pump Pressure rise
PumpPressureRise = PsiPump * NodeDensity * (PumpSpeed**2) * (PumpImpellerDia**2)
!Convergence Criteria Based on Pressure
If (ABS(SystemPressureDrop - PumpPressureRise).LT.(PressureConvergeCriteria)) THEN
ResolvedLoopMassFlowRate = LocalSystemMassFlow
Converged = .TRUE.
EXIT
END IF
IF (Iteration < 2) THEN
!Don't do anything?
ELSE
MdotDeltaLatest = ABS(MassFlowIterativeHistory(1) - MassFlowIterativeHistory(2))
MdotDeltaPrevious = ABS(MassFlowIterativeHistory(2) - MassFlowIterativeHistory(3))
IF (MdotDeltaLatest < MdotDeltaPrevious) THEN
!we are converging
!DampingFactor = MIN(DampingFactor * 1.1, 0.9d0)
ELSE
!we are stuck or diverging
DampingFactor = DampingFactor * 0.9d0
END IF
END IF
!Update pressure value with damping factor
SystemPressureDrop = DampingFactor * PumpPressureRise + (1.0d0 - DampingFactor) * SystemPressureDrop
END DO
!Check if we didn't converge
IF (.NOT. Converged) THEN
MaxIterWarningCounter = MaxIterWarningCounter + 1
IF (MaxIterWarningCounter == 1) THEN
CALL ShowWarningError('Pump pressure-flow resolution attempted, but iteration loop did not converge.')
CALL ShowContinueError('Loop being calculated: '//PlantLoop(LoopNum)%Name)
CALL ShowContinueError('A mismatch between the pump curve entered and the pressure drop components')
CALL ShowContinueError('on the loop may be the cause. The pressure simulation will use the requested (design)')
CALL ShowContinueError('pump flow in order to proceed with the simulation. This warning is only issued once.')
END IF
ResolvedLoopMassFlowRate = SystemMassFlow
RETURN
ENDIF
RETURN
End FUNCTION ResolveLoopFlowVsPressure