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 | |||
integer, | intent(in) | :: | LoopSideNum |
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.
TYPE(m_FlowControlValidator) FUNCTION ValidateFlowControlPaths(LoopNum, LoopSideNum) RESULT(ValidLoopSide)
! FUNCTION INFORMATION:
! AUTHOR Edwin Lee
! DATE WRITTEN July 2010
! MODIFIED na
! RE-ENGINEERED na
! PURPOSE OF THIS FUNCTION:
! This routine will scan all the loop side paths and validate the component topology according
! to current topology rules and regulations.
! METHODOLOGY EMPLOYED:
! Scan this loop side and begin by scanning the first branch, then follow with the remainder of the flow paths
! - this would be from splitter outlet nodes all the way to the loop side outlet node.
! The current rules are that "other types" of components (as defined below in the references) can be placed along each
! flow path as needed. At this point, any number of "load-range based" components can be placed along the flow
! path. After this, the user is allowed to place another set of any number of "other types" of components.
! The key restriction is that an "other type" of component may not be sandwiched by "load-range based" components.
! This is due to the load range based needing to be simulated all at once along each flow path.
! REFERENCES:
! "other types" of components: basically not load-range based heat transfer components. This would include:
! - demand based components such as coils
! - component setpoint based operating components
! - heat exchanger components including waterside economizers
! "load-range based" components are heat transfer components which are controlled based on a single load range.
! - currently only one load range based scheme is available at a given time, although other control types
! may be enabled, such as component setpoint.
! Pumps are separate components since the pump heat is not accounted for in the flow path order.
! Improvements during the demand side rewrite has allowed pumps to be placed as -not- the first component on a branch
! Pumps can be placed anywhere, even between load-range based components, since they will not affect loop load
! RETURN VALUE:
! Returns a control validator flow structure, including a flag for successful or not, then if not successful
! the other values are filled in such as location on the loop where the error occurred and a message error description
! USE STATEMENTS:
USE DataPlant, ONLY: PlantLoop, LoadRangeBasedMin, LoadRangeBasedMax, PumpOpSchemeType, NoControlOpSchemeType, &
UnknownStatusOpSchemeType
USE DataLoopNode, ONLY: Node
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! FUNCTION ARGUMENT DEFINITIONS:
INTEGER, INTENT(IN) :: LoopNum
INTEGER, INTENT(IN) :: LoopSideNum
! FUNCTION PARAMETER DEFINITIONS:
INTEGER, PARAMETER :: Parallel = 1
INTEGER, PARAMETER :: Outlet = 2
! FUNCTION LOCAL VARIABLE DECLARATIONS:
!~ Indexing variables
INTEGER :: BranchIndex
INTEGER :: CompIndex
INTEGER :: NumParallelPaths
INTEGER :: PathCounter
INTEGER :: ParallelOrOutletIndex
!~ General variables
LOGICAL :: EncounteredLRB
LOGICAL :: EncounteredNonLRBAfterLRB
!~ Initialze
ValidLoopSide%Valid = .TRUE.
EncounteredLRB = .FALSE.
EncounteredNonLRBAfterLRB = .FALSE.
NumParallelPaths = PlantLoop(LoopNum)%LoopSide(LoopSideNum)%TotalBranches - 2
! We'll start by stepping through the first branch, which may be the only branch
! If we find a load range based, then trip the flag and just keep moving
! If we only have one branch and all is good, then RETURN early
! If we have parallel branches, then start looping through each flow path to
! decide if it is a valid path.
! If any one path is invalid then all is wrong
BranchIndex = 1
DO CompIndex = 1, PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchIndex)%TotalComponents
SELECT CASE (PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchIndex)%Comp(CompIndex)%CurOpSchemeType)
CASE (LoadRangeBasedMin:LoadRangeBasedMax) !~ load range based
IF (EncounteredNonLRBAfterLRB) THEN
! We must have already encountered a LRB, then a non-LRB, and now another LRB, this is bad
ValidLoopSide%Valid = .FALSE.
ValidLoopSide%ErrorPoint%LoopNum = LoopNum
ValidLoopSide%ErrorPoint%LoopSideNum = LoopSideNum
ValidLoopSide%ErrorPoint%BranchNum = BranchIndex
ValidLoopSide%ErrorPoint%CompNum = CompIndex
ValidLoopSide%Reason = 'Invalid: Load range based components are separated by other control type components. '//&
'Load Range Based should be grouped together on each flow path.'
RETURN
ELSE
EncounteredLRB = .TRUE.
END IF
CASE (PumpOpSchemeType) !~ pump
! For now this is just a placeholder, because I think pumps will be available anywhere,
! and they won't affect the load distribution
CASE (NoControlOpSchemeType) !~ Such as pipes
! For now this is just a placeholder, because these components shouldn't cause a problem anywhere...
CASE (UnknownStatusOpSchemeType) !~ Uninitialized, this should be a sufficient place to catch for this on branch 1
!throw fatal
CALL ShowSevereError('ValidateFlowControlPaths: Uninitialized operation scheme type for component Name: ' &
//TRIM(PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchIndex)%Comp(CompIndex)%Name))
CALL ShowFatalError('ValidateFlowControlPaths: developer notice, Inlet path validation loop')
! WRITE(*,*) 'Uninitialized operation scheme type for the following component: '
! WRITE(*,*) 'Name: '//TRIM(PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchIndex)%Comp(CompIndex)%Name)
! WRITE(*,*) 'TYPE: '//TRIM(PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchIndex)%Comp(CompIndex)%TypeOf)
! WRITE(*,*) 'Location: Loop/LoopSide/Branch/Comp'
! 100 FORMAT (3(I2,'//'), I2)
! WRITE(*,100) LoopNum, LoopSideNum, BranchIndex, CompIndex
! WRITE(*,*) 'Occurs in ValidateFlowControlPaths::Inlet path validation loop'
! WRITE(*,*) 'Immediate program closure, press ENTER to end.'
! READ(*,*)
! STOP 45
CASE DEFAULT !~ Other control type
IF (EncounteredLRB) THEN
EncounteredNonLRBAfterLRB = .TRUE.
ELSE
! For now don't do anything, but we'll see...
END IF
END SELECT
END DO
! Return early if we only needed to do the one branch
IF (NumParallelPaths .LE. 0) RETURN
! Now, if we have multiple parallel branches, I think the easiest way is to go all the way from the inlet node
! of each parallel branch to the loop outlet node and check the flow path
! This way we don't have to remember the conditions on each of the parallel branches when we would finally move
! to analyzing the outlet node when all done
! This will reduce allocation on the heap because we will keep from storing that array
! For each parallel path, we will need to check two branches: the parallel branch and the loopside outlet branch
DO PathCounter = 1, NumParallelPaths
DO ParallelOrOutletIndex = Parallel, Outlet
IF (ParallelOrOutletIndex == Parallel) THEN
! The branch index will be the current pathtype + 1 to add the inlet branch
BranchIndex = PathCounter + 1
ELSEIF (ParallelOrOutletIndex == Outlet) THEN
! The branch index will be the loopside outlet node
BranchIndex = PlantLoop(LoopNum)%LoopSide(LoopSideNum)%TotalBranches
END IF
!Now that we have the branch index, let's do the control type check over all the components
DO CompIndex = 1, PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchIndex)%TotalComponents
SELECT CASE (PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchIndex)%Comp(CompIndex)%CurOpSchemeType)
CASE (LoadRangeBasedMin:LoadRangeBasedMax) !~ load range based
IF (EncounteredNonLRBAfterLRB) THEN
! We must have already encountered a LRB, then a non-LRB, and now another LRB, this is bad
ValidLoopSide%Valid = .FALSE.
ValidLoopSide%ErrorPoint%LoopNum = LoopNum
ValidLoopSide%ErrorPoint%LoopSideNum = LoopSideNum
ValidLoopSide%ErrorPoint%BranchNum = BranchIndex
ValidLoopSide%ErrorPoint%CompNum = CompIndex
ValidLoopSide%Reason='Invalid: Load range based components are separated by other control type components. '//&
'Load Range Based should be grouped together on each flow path.'
RETURN
ELSE
EncounteredLRB = .TRUE.
END IF
CASE (NoControlOpSchemeType) !~ Such as pipes
! For now this is just a placeholder, because these components shouldn't cause a problem anywhere...
CASE (PumpOpSchemeType) !~ pump
! For now this is just a placeholder, because I think pumps will be available anywhere,
! and they won't affect the load distribution
CASE (UnknownStatusOpSchemeType) !~ Uninitialized, this should be sufficient place to catch for this on other branches
!throw fatal error
Call ShowSevereError('ValidateFlowControlPaths: Uninitialized operation scheme type for component Name: ' &
//TRIM(PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchIndex)%Comp(CompIndex)%Name))
CALL ShowFatalError('ValidateFlowControlPaths: developer notice, problem in Parallel path validation loop')
! WRITE(*,*) 'Uninitialized operation scheme type for the following component: '
! WRITE(*,*) 'Name: '//TRIM(PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchIndex)%Comp(CompIndex)%Name)
! WRITE(*,*) 'TYPE: '//TRIM(PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchIndex)%Comp(CompIndex)%TypeOf)
! WRITE(*,*) 'Location: Loop/LoopSide/Branch/Comp'
! WRITE(*,100) LoopNum, LoopSideNum, BranchIndex, CompIndex
! WRITE(*,*) 'Occurs in ValidateFlowControlPaths::Parallel path validation loop'
! WRITE(*,*) 'Immediate program closure, press ENTER to end.'
! READ(*,*)
! STOP 45
CASE DEFAULT !~ Other control type
IF (EncounteredLRB) THEN
EncounteredNonLRBAfterLRB = .TRUE.
ELSE
! For now don't do anything, but we'll see...
END IF
END SELECT
END DO !~ CompIndex
END DO !~ Parallel and Outlet Branches
END DO !~ Parallel Paths
RETURN
END FUNCTION ValidateFlowControlPaths