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) | :: | ControlNum | |||
logical, | intent(in) | :: | FirstHVACIteration | |||
logical, | intent(out) | :: | IsConvergedFlag | |||
logical, | intent(out) | :: | IsUpToDateFlag | |||
character(len=*), | intent(in) | :: | ControllerName |
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed arrows point from an interface to procedures which implement that interface. This could include the module procedures in a generic interface or the implementation in a submodule of an interface in a parent module. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed arrows point from an interface to procedures which implement that interface. This could include the module procedures in a generic interface or the implementation in a submodule of an interface in a parent module. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
SUBROUTINE FindRootSimpleController(ControlNum, FirstHVACIteration, IsConvergedFlag, IsUpToDateFlag, ControllerName)
! SUBROUTINE INFORMATION:
! AUTHOR Dimitri Curtil (LBNL)
! DATE WRITTEN March 2006
! MODIFIED na
! MODIFIED na
! RE-ENGINEERED na
! PURPOSE OF THIS SUBROUTINE:
! New routine to fire the root finder using the current actuated and sensed values.
! - Updates IsConvergedFlag depending ou iteration status.
! - Sets next actuated value to try in ControllerProps(ControlNum)%NextActuatedValue
!
! METHODOLOGY EMPLOYED:
! REFERENCES:
! USE STATEMENTS:
USE General, ONLY : TrimSigDigits
USE RootFinder, ONLY : IterateRootFinder, CheckRootFinderCandidate
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! SUBROUTINE ARGUMENT DEFINITIONS:
INTEGER, INTENT(IN) :: ControlNum
LOGICAL, INTENT(IN) :: FirstHVACIteration
LOGICAL, INTENT(OUT) :: IsConvergedFlag
LOGICAL, INTENT(OUT) :: IsUpToDateFlag
CHARACTER(len=*), INTENT(IN) :: ControllerName ! used when errors occur
! SUBROUTINE PARAMETER DEFINITIONS:
! na
! INTERFACE BLOCK SPECIFICATIONS
! na
! DERIVED TYPE DEFINITIONS
! na
! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
INTEGER :: ActuatedNode
INTEGER :: SensedNode
! TRUE if root finder needs to continue iterating, FALSE otherwise.
LOGICAL :: IsDoneFlag
LOGICAL :: ReusePreviousSolutionFlag
INTEGER :: PreviousSolutionIndex
LOGICAL :: PreviousSolutionDefinedFlag
INTEGER :: PreviousSolutionMode
REAL(r64) :: PreviousSolutionValue
! Obtain actuated and sensed nodes
ActuatedNode = ControllerProps(ControlNum)%ActuatedNode
SensedNode = ControllerProps(ControlNum)%SensedNode
! Update root finder with latest solution point
! Check for unconstrained/constrained convergence
! Compute next candidate if not converged yet.
CALL IterateRootFinder( &
RootFinders(ControlNum), & ! root finder's data
ControllerProps(ControlNum)%ActuatedValue, & ! X
ControllerProps(ControlNum)%DeltaSensed, & ! Y
IsDoneFlag & ! not used
)
! Process root finder if converged or error
! Map root finder status onto controller mode
SelectStatus: SELECT CASE ( RootFinders(ControlNum)%StatusFlag )
CASE (iStatusNone, iStatusWarningNonMonotonic, iStatusWarningSingular)
! We need to keep iterating...
IsConvergedFlag = .FALSE.
IF ( FirstHVACIteration ) THEN
PreviousSolutionIndex = 1
ELSE
PreviousSolutionIndex = 2
END IF
PreviousSolutionDefinedFlag = ControllerProps(ControlNum)%SolutionTrackers(PreviousSolutionIndex)%DefinedFlag
PreviousSolutionMode = ControllerProps(ControlNum)%SolutionTrackers(PreviousSolutionIndex)%Mode
PreviousSolutionValue = ControllerProps(ControlNum)%SolutionTrackers(PreviousSolutionIndex)%ActuatedValue
! Attempt to use root at previous HVAC step in place of the candidate produced by the
! root finder.
ReusePreviousSolutionFlag = &
! Set in InitController() depending on controller mode at previous HVAC step iteration
ControllerProps(ControlNum)%ReusePreviousSolutionFlag .AND. &
! Only attempted during bracketing phase of root finder.
(RootFinders(ControlNum)%CurrentMethodType == iMethodBracket) .AND. &
! Check that a previous solution is available
PreviousSolutionDefinedFlag .AND. &
! Make sure that mode of previous solution was active
(PreviousSolutionMode == iModeActive) .AND. &
! Make sure that proposed candidate does not conflict with current min/max range and lower/upper brackets
CheckRootFinderCandidate( RootFinders(ControlNum), PreviousSolutionValue )
IF ( ReusePreviousSolutionFlag ) THEN
! Try to reuse saved solution from previous call to SolveAirLoopControllers()
! instead of candidate proposed by the root finder
ControllerProps(ControlNum)%NextActuatedValue = PreviousSolutionValue
! Turn off flag since we can only use the previous solution once per HVAC iteration
ControllerProps(ControlNum)%ReusePreviousSolutionFlag = .FALSE.
ELSE
! By default, use candidate value computed by root finder
ControllerProps(ControlNum)%NextActuatedValue = RootFinders(ControlNum)%XCandidate
END IF
CASE ( iStatusOK, iStatusOKRoundOff )
! Indicate convergence with base value (used to obtain DeltaSensed!)
CALL ExitCalcController( &
ControlNum, &
RootFinders(ControlNum)%XCandidate, &
iModeActive, &
IsConvergedFlag, &
IsUpToDateFlag &
)
CASE (iStatusOKMin)
! Indicate convergence with min value
CALL ExitCalcController( &
ControlNum, &
! Should be the same as ControllerProps(ControlNum)%MinAvailActuated
RootFinders(ControlNum)%MinPoint%X, &
iModeMinActive, &
IsConvergedFlag, &
IsUpToDateFlag &
)
CASE (iStatusOKMax)
! Indicate convergence with max value
CALL ExitCalcController( &
ControlNum, &
! Should be the same as ControllerProps(ControlNum)%MaxAvailActuated
RootFinders(ControlNum)%MaxPoint%X, &
iModeMaxActive, &
IsConvergedFlag, &
IsUpToDateFlag &
)
CASE (iStatusErrorSingular)
! Indicate inactive mode with min actuated value
CALL ExitCalcController( &
ControlNum, &
! NOTE: Original code returned Node(ActuatedNode)%MassFlowRateMinAvail
! This was not portable in case the actuated variable was NOT a mass flow rate!
!
! Replaced Node(ActuatedNode)%MassFlowRateMinAvail
! with RootFinders(ControlNum)%MinPoint%X
! which is the same as (see SUBROUTINE InitController)
! ControllerProps(ControlNum)%MinAvailActuated
RootFinders(ControlNum)%MinPoint%X, &
iModeInactive, &
IsConvergedFlag, &
IsUpToDateFlag &
)
! Abnormal case: should never happen
CASE (iStatusErrorRange)
CALL ShowSevereError('FindRootSimpleController: Root finder failed at '//TRIM(CreateHVACStepFullString()))
CALL ShowContinueError( &
' Controller name="'//TRIM(ControllerName)//'"' &
)
CALL ShowContinueError( &
' Root candidate x='// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%ActuatedValue,NumSigDigits))// &
' does not lie within the min/max bounds.' &
)
CALL ShowContinueError( &
' Min bound is x='// &
TRIM(TrimSigDigits(RootFinders(ControlNum)%MinPoint%X,NumSigDigits)) &
)
CALL ShowContinueError( &
' Max bound is x='// &
TRIM(TrimSigDigits(RootFinders(ControlNum)%MaxPoint%X,NumSigDigits)) &
)
CALL ShowFatalError('Preceding error causes program termination.')
! Abnormal case: should never happen
CASE (iStatusErrorBracket)
CALL ShowSevereError('FindRootSimpleController: Root finder failed at '//TRIM(CreateHVACStepFullString()))
CALL ShowContinueError( &
' Controller name='//TRIM(ControllerProps(ControlNum)%ControllerName) &
)
CALL ShowContinueError( &
' Controller action='//TRIM(ActionTypes(ControllerProps(ControlNum)%Action)) &
)
CALL ShowContinueError( &
' Root candidate x='// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%ActuatedValue,NumSigDigits))// &
' does not lie within the lower/upper brackets.' &
)
IF ( RootFinders(ControlNum)%LowerPoint%DefinedFlag ) THEN
CALL ShowContinueError( &
' Lower bracket is x='// &
TRIM(TrimSigDigits(RootFinders(ControlNum)%LowerPoint%X,NumSigDigits)) &
)
END IF
IF ( RootFinders(ControlNum)%UpperPoint%DefinedFlag ) THEN
CALL ShowContinueError( &
' Upper bracket is x='// &
TRIM(TrimSigDigits(RootFinders(ControlNum)%UpperPoint%X,NumSigDigits)) &
)
END IF
CALL ShowFatalError('Preceding error causes program termination.')
! Detected control function with wrong action between the min and max points.
! Should never happen: probably indicative of some serious problems in IDFs
!
! NOTE: This approach is more robust and consistent than what was done in version 1.3.
! Indeed, such a function with the wrong action characteristic would have silently returned
! either of the following values depending on the specified action:
! - NORMAL ACTION:
! - If y(xMin) > ySetPoint && y(xMax) < y(xMin), then x = xMin
! - If y(xMin) < ySetPoint && y(xMax) < y(xMin), then x = xMax
! - REVERSE ACTION:
! - If y(xMin) < ySetPoint && y(xMax) > y(xMin), then x = xMin
! - If y(xMin) > ySetPoint && y(xMax) > y(xMin), then x = xMax
CASE (iStatusErrorSlope)
! CALL ShowSevereError('FindRootSimpleController: Root finder failed at '//TRIM(CreateHVACStepFullString()))
! CALL ShowContinueError( &
! 'FindRootSimpleController: Controller name='//TRIM(ControllerProps(ControlNum)%ControllerName) &
! )
! CALL ShowContinueError( &
! 'FindRootSimpleController: Controller action='//TRIM(ActionTypes(ControllerProps(ControlNum)%Action)) &
! )
! CALL ShowContinueError( &
! 'FindRootSimpleController: Controller setpoint='// &
! TRIM(TrimSigDigits(ControllerProps(ControlNum)%SetPointValue,NumSigDigits)) &
! )
! CALL ShowContinueError( &
! 'FindRootSimpleController: Controller function is inconsistent with the specified action.' &
! )
! CALL ShowContinueError( &
! 'FindRootSimpleController: Min bound is '// &
! 'x='//TRIM(TrimSigDigits(RootFinders(ControlNum)%MinPoint%X,NumSigDigits))//','// &
! 'y='//TRIM(TrimSigDigits(RootFinders(ControlNum)%MinPoint%Y,NumSigDigits)) &
! )
! CALL ShowContinueError( &
! 'FindRootSimpleController: Max bound is '// &
! 'x='//TRIM(TrimSigDigits(RootFinders(ControlNum)%MaxPoint%X,NumSigDigits))//','// &
! 'y='//TRIM(TrimSigDigits(RootFinders(ControlNum)%MaxPoint%Y,NumSigDigits)) &
! )
! CALL ShowFatalError('FindRootSimpleController: Preceding error causes program termination.')
IF (.NOT. WarmupFlag .AND. ControllerProps(ControlNum)%BadActionErrCount == 0) THEN
ControllerProps(ControlNum)%BadActionErrCount = ControllerProps(ControlNum)%BadActionErrCount + 1
CALL ShowSevereError('FindRootSimpleController: Controller error for controller = "'// &
TRIM(ControllerName)//'"')
CALL ShowContinueErrorTimeStamp(' ')
CALL ShowContinueError(' Controller function is inconsistent with user specified controller action = ' // &
TRIM(ActionTypes(ControllerProps(ControlNum)%Action)))
CALL ShowContinueError(' Actuator will be set to maximum action')
CALL ShowContinueError( 'Controller control type='// TRIM(ControlVariableTypes(ControllerProps(ControlNum)%ControlVar)) )
IF (ControllerProps(ControlNum)%ControlVar == iTemperature) THEN
CALL ShowContinueError('Controller temperature setpoint = '// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%SetPointValue,2))//' [C]')
CALL ShowContinueError('Controller sensed temperature = '// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%SensedValue,2))//' [C]')
ELSE IF (ControllerProps(ControlNum)%ControlVar == iHumidityRatio) THEN
CALL ShowContinueError('Controller humidity ratio setpoint = '// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%SetPointValue,2))// &
' [kg-H2O/kg-air]')
CALL ShowContinueError('Controller sensed humidity ratio = '// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%SensedValue,2))// &
' [kg-H2O/kg-air]')
ELSE IF (ControllerProps(ControlNum)%ControlVar == iTemperatureAndHumidityRatio) THEN
CALL ShowContinueError('Controller temperature setpoint = '// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%SetPointValue,2))//' [C]')
CALL ShowContinueError('Controller sensed temperature = '// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%SensedValue,2))//' [C]')
CALL ShowContinueError('Controller humidity ratio setpoint = '// &
TRIM(TrimSigDigits(Node(ControllerProps(ControlNum)%SensedNode)%HumRatMax,2))//' [kg-H2O/kg-air]')
CALL ShowContinueError('Controller sensed humidity ratio = '// &
TRIM(TrimSigDigits(Node(ControllerProps(ControlNum)%SensedNode)%HumRat,2))//' [kg-H2O/kg-air]')
ELSE IF (ControllerProps(ControlNum)%ControlVar == iFlow) THEN
CALL ShowContinueError('Controller mass flow rate setpoint = '// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%SetPointValue,2))//' [kg/s]')
CALL ShowContinueError('Controller sensed mass flow rate = '// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%SensedValue,2))//' [kg/s]')
ELSE
! bad control variable input checked in input routine
END IF
IF (ControllerProps(ControlNum)%ActuatorVar == iFlow) THEN
CALL ShowContinueError('Controller actuator mass flow rate set to '// &
TRIM(TrimSigDigits(ControllerProps(ControlNum)%MaxAvailActuated,2))//' [kg/s]')
IF (ControllerProps(ControlNum)%ControlVar == iTemperature) THEN
CALL ShowContinueError('Controller actuator temperature = '// &
TRIM(TrimSigDigits(Node(ControllerProps(ControlNum)%ActuatedNode)%Temp,2))//' [C]')
CALL ShowContinueError(' Note: Chilled water coils should be reverse action and the entering chilled')
CALL ShowContinueError(' water temperature (controller actuator temperature) should be '// &
'below the setpoint temperature')
CALL ShowContinueError(' Note: Hot water coils should be normal action and the entering hot')
CALL ShowContinueError(' water temperature (controller actuator temperature) should be '// &
'above the setpoint temperature')
END IF
ELSE
! bad actuator variable input checked in input routine
END IF
ELSE IF (.NOT. WarmupFlag) THEN
ControllerProps(ControlNum)%BadActionErrCount = ControllerProps(ControlNum)%BadActionErrCount + 1
CALL ShowRecurringSevereErrorAtEnd('FindRootSimpleController: Previous controller action error'// &
' continues for controller = '// &
TRIM(ControllerName), &
ControllerProps(ControlNum)%BadActionErrIndex)
ELSE
! do nothing
END IF
! Indicate convergence with min value
CALL ExitCalcController( &
ControlNum, &
! Should be the same as ControllerProps(ControlNum)%MaxAvailActuated
RootFinders(ControlNum)%MaxPoint%X, &
iModeMaxActive, &
IsConvergedFlag, &
IsUpToDateFlag &
)
CASE DEFAULT
! Should never happen
CALL ShowSevereError('FindRootSimpleController: Root finder failed at '//TRIM(CreateHVACStepFullString()))
CALL ShowContinueError( &
' Controller name='//TRIM(ControllerName) &
)
CALL ShowContinueError( &
' Unrecognized root finder status flag='// &
TRIM(TrimSigDigits(RootFinders(ControlNum)%StatusFlag)) &
)
CALL ShowFatalError('Preceding error causes program termination.')
END SELECT SelectStatus
RETURN
END SUBROUTINE FindRootSimpleController